我有 Debian jessie 和 xfce。当我按下电源按钮时,我的系统暂停。当我按键盘上的任意键时,系统会唤醒,并收到 Xscreensaver 的登录提示(屏幕锁定处于活动状态)。现在,如果我按下电源按钮,系统不会暂停,我必须登录,然后才能使用电源按钮暂停系统。有没有办法从 Xscreensaver 的登录屏幕暂停系统?
答案1
问题是(可能)您的 xfce 会话中的某些程序正在处理挂起按钮按下事件,即系统托盘中的某些电源管理器程序。如果屏幕被锁定,全部屏幕保护程序会拦截按键操作,包括暂停按钮。
修复可能检查您的按钮处理/etc/systemd/logind.conf
是否systemd
已配置。如果有HandleSuspendKey=suspend
,systemd
按下暂停按钮将启动暂停。不过,我不知道如果你的屏幕解锁了会是什么效果!您可能需要告诉电源管理器程序忽略暂停按钮的按下。很难给出完整的答案,但我希望这个答案至少能给你一个正确的方向推动。
答案2
Xscreensaver 运行正常。据我了解,XGrabKeyboard
Xscreensaver 使用它在显示登录窗口时抓取按键。简而言之,您通常无法在锁定屏幕上使用电源按钮,但我确实查看了大量文档和一些代码,以找出原因以及可能存在的解决方案。
只有少数例外情况可以绕过 Xscreensaver 锁定,所有这些都依赖于使用较低级别的键盘快捷键1。
后门#1:Ctrl-Alt-Backspace。此击键会终止 X 服务器,并且在某些系统上,您将留在文本控制台。如果用户手动启动 X11,该文本控制台仍将登录。要全局且永久地禁用此击键,您需要在 xorg.conf 或 XF86Config 或 XF86Config-4 文件中设置 DontZap 标志(无论在哪个名称上使用)你的系统)。有关更多详细信息,请参阅 XF86Config(或变体)的手册。
后门 #2:Ctrl-Alt-F1、Ctrl-Alt-F2 等。这些击键将切换到不同的虚拟控制台,同时锁定运行 X11 的控制台。如果您让 shell 登录到另一个虚拟控制台,则该 shell 将不受保护。因此,不要让自己在其他控制台上保持登录状态。您可以通过在 xorg.conf 中设置 DontVTSwitch 来全局且永久地禁用 VT 切换,但这可能会使您的系统更难使用。
后门#3:Alt-SysRq-F。这是 Linux 内核的“OOM-killer”按键。它会随机击落其选择的长时间运行的程序,因此可能会瞄准并杀死 xscreensaver,而 xscreensaver 无法保护自己免受这种情况的影响。您可以使用以下命令全局禁用它: sudo 'echo 176 > /proc/sys/kernel/sysrq'
后门#4:Ctrl-Alt-KP_Multiply。此按键会杀死任何持有锁的 X11 应用程序,因此输入此键将杀死 xscreensaver 并解锁屏幕。此“功能”于 2008 年出现在 X 服务器中,截至 2011 年,一些供应商默认将其打开。多好。您可以通过关闭 xorg.conf 中的AllowClosedownGrabs 来禁用它。
事实上,您可以将 Xorg 配置为AllowClosedownGrabs
关闭持有锁的 Xscreensaver 进程或AllowDeactivateGrabs
停用和激活键盘抓取2。当然,这使得锁对于任何能够物理访问键盘的人来说毫无用处,但您至少应该能够测试电源按钮,看看它在使用AllowClosedownGrabs或AllowDeactivateGrabs快捷方式后是否会挂起计算机。
如果此时您成功地暂停了机器,那么至少我们知道存在一定程度的键盘映射,其操作可以控制服务器的行为而不会被 XGrabkeyboard 捕获。
该快捷方式Ctrl-Alt-FX
将在屏幕锁定时通过 切换虚拟终端XF86_Switch_VT_X
,其中X
是 F 键 1-12 的编号。所以我们知道 xkb 的这些密钥没有被抢到。
节目输出摘录grep -r "XF86_Switch" /usr/share/X11/xkb/
:
/usr/share/X11/xkb/compat/xfree86: interpret XF86_Switch_VT_1 {
/usr/share/X11/xkb/symbols/srvr_ctrl: symbols[Group1]= [ F1, F1, F1, F1, XF86_Switch_VT_1 ]
如果您查看这些文件,您会发现它们还包含用于取消键盘抓取和终止已生效的客户端的组合键。
因此,如果有办法让电源按钮在锁定屏幕期间暂停,则可能需要电源按钮的自定义 xkb 键。它还必须用来Ungrab
取消所有当前活跃的抢夺。
目前我能带你了解的就这么多了。它可能会提出几个新问题,特别是关于电源按钮的 xkb 键映射,以及映射要使用的键,Ungrab
如下所示。
来自提交 7d2543a3cb3089241982ce4f8984fd723d5312a13
Add four new private XKB actions for debugging:
* PrGrbs: print active grabs to the log file
* Ungrab: ungrab all currently active grabs
* ClsGrb: kill clients with active grabs
* PrWins: dump the current window tree to the log file
To use these, you need to modify your XKB maps, e.g. the following to
have Ctrl+Alt+(F9-F12) mapped to the above:
- compat/xfree86:
interpret XF86LogGrabInfo {
action = Private(type=0x86, data="PrGrbs");
};
interpret XF86Ungrab {
action = Private(type=0x86, data="Ungrab");
}
interpret XF86ClearGrab {
action = Private(type=0x86, data="ClsGrb");
}
interpret XF86LogWindowTree {
action = Private(type=0x86, data="PrWins");
}
- symbols/pc:
key <FK09> { type="CTRL+ALT", [ Return, XF86LogGrabInfo ] };
key <FK10> { type="CTRL+ALT", [ Return, XF86Ungrab ] };
key <FK11> { type="CTRL+ALT", [ Return, XF86ClearGrab ] };
key <FK12> { type="CTRL+ALT", [ Return, XF86LogWindowTree ] };
编辑:来自 ACPI 的电源按钮事件可能正常运行,但由于以下原因未得到处理:XGrabServer
4xscreensaver 使用的锁5。
XGrabServer 功能禁用请求处理并关闭除此请求到达的连接之外的所有其他连接。
我知道解决这个问题的唯一方法是启用选项AllowClosedownGrabs
并使用Ctrl+Alt+Keypad-Multiply
组合键6。
请注意,选项AllowDeactivateGrabs 和AllowClosedownGrabs 将允许用户删除屏幕保护程序/储物柜程序使用的抓取。
如果你真的想对此感到厌烦,你可以尝试为 xscreensaver 编写一个补丁来支持电源按钮(也许监听 ACPI 事件,XUngrabServer
然后再次发出该事件)。当系统恢复时,它必须再次抓取,否则锁就没有意义了。我不知道这还会带来什么其他安全影响。
编辑2:测试xfce4-power-manager-settings
设置为按下电源按钮时关闭,它在屏幕锁定时工作。我相信这是因为 ACPI 处理只需要电源按钮的扫描码,而无需在窗口管理器级别进行处理。
将电源按钮设置为 的测试Suspend
会被 xscreensaver 捕获并阻止。
我读了以下内容7,并决定pm-suspend
在 xscreensaver 运行时进行测试,以确保它不会受到直接干扰。
xfce4-power-manager,它使用 pkexec 调用 pm-suspend。 pkexec 允许以另一个用户(在本例中为 root)身份执行程序。
首先我跑去sudo ls
输入密码并授予用户临时 sudo 权限。
接下来我运行以下命令:
sleep 60 && xscreensaver-command -lock &
sleep 60 && sudo pm-suspend
屏幕被锁定,随后系统如预期般暂停了。
我相信挂起是在窗口管理器级别处理的,并xfce4-power-manager
依赖 xkb 键映射在扫描码转换为可以在窗口管理器级别处理的键码后处理它。这可以解释为什么它会受到抓取并被阻止执行pm-suspend
8。
udev 键盘映射是正确的。正如我所说,在内核级别只有 KEY_SLEEP(挂起到 RAM)和 KEY_SUSPEND(挂起到磁盘,又名休眠)。
在 X.org 级别,/usr/share/X11/xkb/keycodes/evdev 分配给 KEY_SLEEP 和 KEY_SUSPEND。然后 /usr/share/X11/xkb/symbols/inet 映射到 XF86Sleep 和 XF86Suspend,镜像 evdev 命名。
如果我正确阅读的话,这在我的系统上是类似的:
grep -r "Suspend" /usr/share/X11/xkb/
输出:
/usr/share/X11/xkb/geometry/everex: indicator "Suspend" { left=112; };
/usr/share/X11/xkb/keycodes/evdev: indicator 7 = "Suspend";
/usr/share/X11/xkb/symbols/inet: key <I213> { [ XF86Suspend ] };
/usr/share/X11/xkb/server-0.xkb: indicator 7 = "Suspend";
/usr/share/X11/xkb/server-0.xkb: key <I213> { [ XF86Suspend ] };
编辑3:xfce4-power-manager
如果是这种情况,请尝试将 ACPI 配置为直接挂起而不是使用。
您可能需要编写一个要调用的 shell 脚本才能/etc/acpi/events/powerbtn
正确处理此问题。看如何在 Linux 下暂停和休眠笔记本电脑
xscreensaver-command -lock
如果您想确保系统恢复时屏幕被锁定,您可能必须在挂起之前在脚本中使用。Xscreensaver 检查屏幕是否已锁定,xscreensaver-command: already locked.
如果是则输出。
答案3
如果有人仍然感兴趣,几天前我在笔记本电脑上遇到了类似的问题,我没有使用 systemd 基础设施来处理挂起键(这是一个很长的故事,与这里不太相关)。无论如何,我的解决方案是使用 acpid 进行系统范围的反应:
1) 我的窗口管理器 (openbox) 通过显示 OSD 消息并执行 xscreensaver-command lock 对挂起键 (XF86Sleep) 做出反应
2) acpid 对挂起键(event=button/sleep SBTN)做出反应,休眠 2 秒,然后从 uswsusp 执行 s2ram(参见,例如,https://wiki.debian.org/Uswsusp)