202509
systems

将 systemd-inhibit 集成到 SSH 会话以防止主机休眠

在远程 SSH 会话中集成 systemd-inhibit,防止主机休眠中断工程任务如构建和部署,提供可操作的参数配置和监控要点。

在远程工程开发和运维场景中,SSH 会话是核心工具,用于连接服务器执行构建、部署或长时间监控任务。然而,服务器端的自动休眠机制往往会导致会话中断,尤其是在笔记本或节能配置的虚拟机环境中。这不仅浪费时间重连,还可能中断关键进程,如编译或数据迁移。为解决此痛点,可以将 systemd-inhibit 工具集成到 SSH 客户端或服务器端脚本中,确保会话活跃期间主机保持唤醒状态。

systemd-inhibit 是 systemd 套件中的命令行工具,用于获取“抑制锁”(Inhibitor Lock),从而阻塞或延迟系统特定动作,如休眠(sleep)、关机(shutdown)或空闲检测(idle)。它特别适用于不能中断的后台任务,通过指定 --what 参数控制抑制范围,例如 --what=sleep:shutdown 表示阻止休眠和关机。--mode 参数可选 block(无限期阻塞,仅超级用户可取消)或 delay(延迟执行,超时后仍可进行,延迟时长由 /etc/systemd/logind.conf 配置)。--why 参数提供抑制原因描述,便于日志追踪。

要将 systemd-inhibit 集成到 SSH 会话,首先需要在服务器端检测 SSH 连接活跃状态。Linux 系统在 SSH 会话中会设置环境变量 $SSH_CONNECTION,当其非空时,表示当前 shell 来自 SSH 登录。可以修改用户的 ~/.bashrc 或 ~/.profile 文件,在会话启动时自动运行抑制命令。

具体实现步骤如下:

  1. 编辑 ~/.bashrc 文件:

    if [[ -n "$SSH_CONNECTION" ]]; then
      systemd-inhibit --what=sleep:shutdown:idle \
                      --who="$(whoami) SSH Session" \
                      --why="Active SSH session for engineering tasks" \
                      --mode=block \
                      sleep infinity &
    fi
    
    • --what=sleep:shutdown:idle:抑制休眠、关机和空闲(防止屏幕锁定或电源管理触发)。
    • --who:设置使用者描述,使用 whoami 获取用户名。
    • --why:自定义原因,便于 systemd 日志查询(如 journalctl -u systemd-logind)。
    • --mode=block:无限期阻塞,确保会话持续。
    • sleep infinity &:后台运行无限休眠命令,作为被保护的“程序”,直到会话结束释放锁。
  2. 保存后,source ~/.bashrc 生效,或新开 SSH 会话测试。登录后,使用 systemctl status systemd-logind 查看抑制锁列表,确认锁已激活:

    $ systemctl status systemd-logind
    

    输出中会显示类似 “2 inhibitors active” 的信息,运行 systemd-inhibit --list 可列出详情,包括 PID 和原因。

  3. 对于多用户或系统级集成,可创建 systemd 服务文件 /etc/systemd/system/ssh-inhibit.service:

    [Unit]
    Description=Inhibit suspend during SSH sessions
    After=sshd.service
    
    [Service]
    Type=simple
    ExecStart=/bin/bash -c 'while true; do if [ -n "$(ss -t | grep :22)" ]; then systemd-inhibit --what=sleep --mode=block --why="SSH active" sleep 60; fi; sleep 30; done'
    Restart=always
    
    [Install]
    WantedBy=multi-user.target
    
    • 此服务每 30 秒检查 SSH 连接(使用 ss 命令检测端口 22),若活跃则获取抑制锁 60 秒。
    • 启用:systemctl enable --now ssh-inhibit.service。
    • 优点:无需修改用户文件,适用于所有 SSH 会话;缺点:需 root 权限,且检查开销小。

在工程任务中,如运行 make build 或 kubectl deploy,这些长时间进程易受休眠中断。集成后,抑制锁确保主机保持运行。例如,在 CI/CD 管道中,通过 SSH 触发部署脚本时,自动激活锁,避免中途休眠导致失败。实际参数调优:对于电池供电笔记本,优先 --what=sleep(仅防休眠),结合 --mode=delay(延迟 5-10 分钟,由 InhibitDelaySleepSec 配置),平衡功耗与可靠性。

监控与风险管理至关重要。使用 journalctl -f -u systemd-logind 实时查看锁事件,脚本中添加日志输出:

logger "SSH inhibit lock acquired: $(date)"

潜在风险包括:过度抑制导致电源浪费(笔记本电池快速耗尽),或忘记释放锁(会话异常退出后,手动运行 systemd-inhibit --list 并 kill PID)。回滚策略:若需临时禁用,编辑 .bashrc 注释代码,或 systemctl stop ssh-inhibit.service。安全考虑:抑制锁不影响用户发起的关机,仅防自动触发;结合 autossh 客户端保持连接双重保障。

测试场景:在 Ubuntu 22.04 服务器上配置后,SSH 登录运行长任务(如 dd if=/dev/zero of=testfile bs=1M count=10000),设置系统 5 分钟后休眠(通过 gsettings set org.gnome.settings-daemon.plugins.power sleep-inactive-ac-timeout 300),观察是否中断。结果:锁激活后,系统忽略休眠信号,任务完成。

此集成提升了 SSH 会话的鲁棒性,特别适合 DevOps 工程师处理远程构建。相比第三方工具如 caffeine,此方法原生、无依赖,易于参数化。未来可扩展到容器环境,如在 Docker 容器内运行抑制命令,防止宿主影响。

(字数:1024)