介绍
我觉得不止我一个拥有多台laptop作为主力机人会遇到这个问题,那就是桌面空间有限,不会每一台电脑都需要他打开盖子。
像我平常是用一个游戏本进行居家的娱乐、办公。一台轻薄Linux / Win双系统作为开发环境,因为在家的笔记本接了鼠标、键盘、显示器。也不方便将轻薄本将其替换。我的轻薄本是ASUS Zenbook S 14 UX5406SA_UX5406SA 目前有以下痛点:
- 盒盖后系统会进入休眠,导致所有例如ssh等服务关闭。
- 如果单纯忽略盒盖休眠,会导致屏幕未关闭,一个是不够节能,更主要的是害怕OLED烧屏。
想要实现以下功能。
- 未插电时 -> 盒盖 :系统默认休眠代理。
- 插电时 -> 盒盖 : 关闭屏幕但保持一切服务。
- 插电时 -> 开盖 :将屏幕亮度恢复到原来的亮度。
关闭系统默认的休眠代理
关闭桌面环境自动休眠

按照图片操作在 Setting -> Power -> PowerSaving -> When Plugged in 关闭即可
KDE Xface等桌面环境,与之相似。
关闭Systemd盒盖代理
Systemd 的代理文件在此中
/etc/systemd/logind.conf
对于盒盖有关的Lid句柄如下:
HandleLidSwitch:合上笔记本盖
HandleLidSwitchDocked:链接外部显示器下合上盖子
HandleLidSwitchExternalPower: 当外接电源时合上盖子
他的值包括:
poweroff和halt 都是关机,实现方式不同
suspend 挂起/暂停 设备通电,内容保存在内存中
hybernate 休眠,设备断电(同关机状态),内容保存在硬盘中
hybrid-sleep 混合睡眠,设备通电,内容保存在硬盘和内存中
lock 锁屏
kexec 是从当前正在运行的内核直接引导到一个新内核
ignore 空事件 / 什么都不做
我们只需要进行设置
HandleLidSwitchExternalPower=ignore (默认为suspend)
即可,然后重启服务后重启
systemctl restart systemd-logind
reboot
就此,充电时的默认盒盖事件就被我们都关闭了。
添加自己的盒盖脚本
原理
我们检测三个状态,一个是盖子是否打开,一个是是否有充电,一个是我们要更改的亮度。我们分别按三个部分来说:
供电
供电的信息存储在 /sys/class/power_supply
对于我的电脑,分为 AC0(充电) 与 BAT0(电池), 其中 ./AC0/online 的信息就是电脑判断是否外接电源的文件。1为接电,0为电池带载。
也就是说 只要判断 /sys/class/power_supply/AC0/online 为 1 或 0 即可知道是否接电。
值得注意的是,不同的电脑可能AC也是不同,假如你的电脑有多个充电口,就分为 AC0 、 AC1 等… 也有可能只有一个AC。
盒盖状态
盒盖状态存储在 /proc/acpi/button/lid
对于我的电脑,相关信息存储在 ./LID0/state 当中。其中 open代表开盖,close代表盒盖。
同样的 LID0 与 AC0 情况类似,代表序号。
屏幕背光
屏幕亮度存储在 /sys/class/backlight 当中
不同显卡驱动也不一样,我使用的是intel核显,相关信息存储在 ./intel_backlight 文件当中。 在这当中有两个我们需要关注的文件,一个是 brightness 与 max_brightness 文件。
max_brightness当中为亮度上限,亮度切莫高于此。brightness存储的是当前的屏幕亮度,你可以读取这个值来获取屏幕亮度,同时可以更改这个值来调节屏幕背光。
编写脚本
我提供一个我使用的简单脚本,名字为 lid_watcher.sh 你们只需要根据需要进行更改就可以了。如果你的电脑也是 UX5406 , 应该也能直接用。如果是其他电脑,虽然我做了一些适配,但或许还是需要根据情况修改一下。
#!/bin/bash
# 记录初始亮度
BRIGHTNESS_FILE="/sys/class/backlight/intel_backlight/brightness"
MAX_BRIGHTNESS=$(cat $BRIGHTNESS_FILE)
LAST_STATE="open"
while true; do
# 获取当前电源状态
AC_ONLINE=$(cat /sys/class/power_supply/AC*/online)
# 获取当前 lid 状态
LID_STATE=$(cat /proc/acpi/button/lid/LID*/state | awk '{print $2}')
if [ "$AC_ONLINE" -eq 1 ]; then
if [ "$LID_STATE" == "closed" ]; then
if [ "$LAST_STATE" == "open" ]; then
# 盒盖后第一次检测到,保存当前亮度并设置为0
MAX_BRIGHTNESS=$(cat $BRIGHTNESS_FILE)
echo 0 | tee $BRIGHTNESS_FILE
LAST_STATE="closed"
fi
else
if [ "$LAST_STATE" == "closed" ]; then
# 重新打开盖子,恢复亮度
echo $MAX_BRIGHTNESS > $BRIGHTNESS_FILE
LAST_STATE="open"
fi
fi
fi
# 每5秒检测一次
sleep 5
done
可以使用 sudo命令对该脚本进行测试,打开后尝试反复开关盖子进行测试,请确定该脚本能够正常使用后再进行之后的操作。
设定systemd服务
将脚本移动到 /usr/local/bin 来确保使用权限
sudo mv lid_watcher.sh /usr/local/bin/lid_watcher.sh
sudo chmod +x /usr/local/bin/lid_watcher.sh
创建一个新的 systemd 服务文件
sudo vim /etc/systemd/system/lid-watcher.service
文件内容如下
[Unit]
Description=Lid and Power Watcher Script
After=multi-user.target
StartLimitIntervalSec=0
[Service]
Type=simple
ExecStart=/usr/local/bin/lid_watcher.sh
Restart=on-failure
RestartSec=5s
[Install]
WantedBy=multi-user.target
启动并启用服务
# 重新加载 systemd 配置
sudo systemctl daemon-reexec
sudo systemctl daemon-reload
# 启动服务
sudo systemctl start lid-watcher.service
# 设置为开机自启动
sudo systemctl enable lid-watcher.service
最后检查日志之后
# 查看运行状态
sudo systemctl status lid-watcher.service
# 查看输出日志
journalctl -u lid-watcher.service -f
如果服务正常,我们的脚本就被正常挂在到 systemd 当中了。之后就能享受到 通电时也可盒盖保持屏幕关闭,电脑运行了!