使用 Bash 防止猫咪干扰屏幕锁
我在卧室里有一台电脑。我也养了猫。不幸的是,猫咪和屏幕锁不太相容,尤其是在晚上。准确地说,这更多是显示器电源管理的问题,而不是实际的屏幕锁定。情况是这样的:我运行一个脚本来“晚上关灯”(即,锁定屏幕并强制显示器断电),这效果很好,直到其中一只猫跳到桌子上,导致鼠标移动并重新打开显示器。而且猫咪甚至不必碰到鼠标;桌子的轻微移动就足以引起鼠标的反应。最近,我受够了这种情况,并认为必须有一种方法来禁用鼠标并“重构”脚本。
脚本的初始版本非常简单
qdbus org.kde.screensaver /ScreenSaver Lock
sleep 2
xset +dpms
xset dpms force off
第一行锁定屏幕。第三行确保启用显示器电源管理,最后一行关闭显示器电源。
如果您使用 GNOME,qdbus行可能不起作用,因此请尝试以下方法代替
dbus-send --type=method_call --dest=org.gnome.ScreenSaver \
/org/gnome/ScreenSaver org.gnome.ScreenSaver.Lock
使用xinput命令(您可能需要安装)来关闭鼠标也很简单
xinput --set-prop "Your-Mouse-Name" "Device Enabled" "0"
稍微棘手的部分是弄清楚“您的鼠标名称”应该使用什么。使用xinput命令再次查找也很简单
$ xinput list
⎡ Virtual core pointer id=2 [master pointer (3)]
⎜ ↳ Virtual core XTEST pointer id=4 [slave pointer (2)]
⎜ ↳ HOLTEK USB-HID Keyboard Mouse id=10 [slave pointer (2)]
⎜ ↳ HOLTEK USB-HID Keyboard Consumer Control id=12 [slave pointer (2)]
⎜ ↳ mini keyboard Mouse id=16 [slave pointer (2)]
⎜ ↳ mini keyboard Consumer Control id=18 [slave pointer (2)]
⎜ ↳ USB Mouse id=14 [slave pointer (2)]
⎣ Virtual core keyboard id=3 [master keyboard (2)]
↳ Virtual core XTEST keyboard id=5 [slave keyboard (3)]
↳ Power Button id=6 [slave keyboard (3)]
↳ Video Bus id=7 [slave keyboard (3)]
↳ Power Button id=8 [slave keyboard (3)]
↳ HOLTEK USB-HID Keyboard id=9 [slave keyboard (3)]
↳ HOLTEK USB-HID Keyboard System Control id=11 [slave keyboard (3)]
↳ HOLTEK USB-HID Keyboard Keyboard id=13 [slave keyboard (3)]
↳ mini keyboard id=15 [slave keyboard (3)]
↳ mini keyboard System Control id=17 [slave keyboard (3)]
↳ HOLTEK USB-HID Keyboard Consumer Control id=19 [slave keyboard (3)]
↳ mini keyboard Consumer Control id=20 [slave keyboard (3)]
好吧,也许并没有那么简单,因为在我的系统上,有三个东西被命名为“Mouse”。但我知道这不是前两个,因为它们的名称表明它们是键盘的一部分,只剩下通用的“USB Mouse”。
不幸的是,当我在另一个系统上尝试使用不同类型的 USB 鼠标时,鼠标名称并没有显示为“USB Mouse”,而是显示为“Logitech USB Laser Mouse”,这意味着我无法将鼠标名称硬编码到脚本中。在查看这两个列表后,我注意到我想要的鼠标名称始终是“Virtual core keyboard”行之前的名称。诚然,我的假设是基于一个非常小的测试组,但在我看到不同的情况之前,它会起作用。注意:当我写这篇文章时,我突然想到也许我可以只禁用“Virtual core pointer”,这可能是一个“通用”名称,但我还没有尝试过。
因此,通过一些 grepping,我现在可以在任何系统上获取鼠标的名称
mouse_name=$(xinput list --name-only | grep -B 1 'Virtual core keyboard' | head -n 1)
的--name-only选项到xinput list消除了所有花哨的箭头和其他额外信息,只输出名称。
的-B选项使 grep 输出它找到的任何匹配项的上下文前导行。在这种情况下,除了“Virtual core keyboard”行之外,它还输出它之前的行(这是我想要的行)。然后我使用head来挑选出那一行,这给了我关闭鼠标的名称(在上面的示例中为“USB Mouse”)。
提示:Grep 上下文选项
Grep 的上下文选项有时会非常方便,来自 grep 手册页
-A NUM, --after-context=NUM
打印匹配行之后 NUM 行的后续上下文。在连续的匹配组之间放置包含组分隔符 (--) 的行。使用 -o 或 --only-matching 选项,这不起作用,并且会发出警告。
-B NUM, --before-context=NUM
打印匹配行之前 NUM 行的前导上下文。在连续的匹配组之间放置包含组分隔符 (--) 的行。使用 -o 或 --only-matching 选项,这不起作用,并且会发出警告。
-C NUM, -NUM, --context=NUM
打印 NUM 行的输出上下文。在连续的匹配组之间放置包含组分隔符 (--) 的行。使用 -o 或 --only-matching 选项,这不起作用,并且会发出警告。
整个mouse-on-off脚本如下
#!/bin/bash
function usage()
{
cat <<EOF
Usage: $0 MOUSE-STATE
MOUSE-STATE:
on|enable|enabled|1 Enable mouse
off|disable|disabled|0 Disable mouse
test|mouse Display mouse name
EOF
}
if test "$DISPLAY"; then
mouse_name=$(xinput list --name-only | grep -B 1 'Virtual core keyboard' | head -n 1)
if [[ "$1" =~ ^(on|enable|enabled|1)$ ]]; then
xinput --set-prop "$mouse_name" "Device Enabled" "1"
echo "on"
elif [[ "$mouse_name" && "$1" =~ ^(off|disable|disabled|0)$ ]]; then
xinput --set-prop "$mouse_name" "Device Enabled" "0"
echo "off"
elif [[ "$1" =~ ^(test|mouse)$ ]]; then
echo "Mouse name: ${mouse_name}"
else
echo "Mouse name: ${mouse_name}" >&2
usage >&2
fi
else
echo "Mouse name: UNKNOWN (No X server ???)"
if [[ "$1" =~ ^(on|enable|enabled|1|off|disable|disabled|0)$ ]]; then
echo "on"
elif [[ "$1" =~ ^(test|mouse)$ ]]; then
:
else
usage >&2
fi
fi
一些使用示例
$ mouse-on-off mouse # Show mouse name
Mouse name: USB Mouse
$ mouse-on-off off # Turn off mouse
off
$ mouse-on-off on # Turn on mouse
on
出错示例
$ mouse-on-off mouse # Unable to get mouse name
Mouse name: UNKNOWN (No X server ???)
$ mouse-on-off off # Unable to turn off mouse
Mouse name: UNKNOWN (No X server ???)
on # Mouse is still on
现在我需要做的就是修改原始脚本以使用 mouse-on-off 命令
#!/bin/bash
qdbus org.kde.screensaver /ScreenSaver Lock
sleep 2
mouse=$(mouse-on-off off)
xset +dpms
xset dpms force off
if [[ "$mouse" == 'off' ]]; then
kdialog --msgbox "Enter to re-enable the mouse"
mouse-on-off on
fi
的mouse=$(mouse-on-off off)调用新命令并捕获其标准输出,标准输出应该是“on”或“off”(错误消息会转到标准错误)。关闭显示器后,假设我能够关闭鼠标,我弹出一个消息框。当我解锁计算机时,我只需按 Enter 键即可关闭迎接我的消息框,并且脚本会重新打开鼠标并退出。以防您想知道,是的,在使用这个脚本的头几天,当我早上摇晃鼠标试图唤醒显示器时,我一直认为鼠标在夜间坏死了 [在此处插入猫/鼠标笑话]。旧习惯很难改掉,但最终还是会改掉的。