You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何配置Polkit规则:当指定文件存在时阻止系统关机?

这个方案思路挺清晰的,我帮你把各个环节的实现细节和注意事项梳理清楚,分三大部分来落地:

一、U盘插拔监控程序的实现

咱们的核心目标是通过监控U盘的插拔动作,维护一个锁文件的状态:

  • U盘连接时:把它的唯一标识符(比如序列号)写入锁文件(推荐放在/var/run/下,因为是临时文件目录,系统重启会自动清空)
  • U盘断开时:从锁文件中移除对应标识符,若文件为空则删除它

这里给你一个Python实现的示例(用pyudev库来监听系统设备事件,兼容性好):

import pyudev
import os

# 定义锁文件路径,建议放在/var/run下,系统重启自动清理
LOCK_FILE = '/var/run/usb_shutdown_lock'

def update_lock_file(action, device_id):
    # 处理文件更新逻辑
    if not os.path.exists(LOCK_FILE):
        if action == 'remove':
            return
        # 首次添加U盘,创建文件并写入标识符
        with open(LOCK_FILE, 'w') as f:
            f.write(f"{device_id}\n")
        return
    
    # 读取现有内容,过滤掉当前要移除的标识符
    with open(LOCK_FILE, 'r') as f:
        lines = [line.strip() for line in f if line.strip() != device_id]
    
    # 如果是添加动作,把标识符加回去
    if action == 'add':
        lines.append(device_id)
    
    # 根据处理后的内容决定是写入还是删除文件
    if lines:
        with open(LOCK_FILE, 'w') as f:
            f.write('\n'.join(lines) + '\n')
    else:
        os.remove(LOCK_FILE)

# 初始化设备监控上下文
context = pyudev.Context()
monitor = pyudev.Monitor.from_netlink(context)
# 只监听块设备中的磁盘(U盘属于这类)
monitor.filter_by(subsystem='block', device_type='disk')

# 循环监听设备事件
for device in iter(monitor.poll, None):
    # 只处理有序列号的设备(排除内置磁盘)
    if 'ID_SERIAL_SHORT' in device:
        device_id = device['ID_SERIAL_SHORT']
        if device.action == 'add':
            update_lock_file('add', device_id)
        elif device.action == 'remove':
            update_lock_file('remove', device_id)
二、Polkit规则配置

接下来要写Polkit规则,让系统在处理关机请求时检查锁文件的存在性:

  1. 在/etc/polkit-1/rules.d/目录下创建规则文件,比如99-usb-shutdown.rules(文件名数字越大优先级越高)
  2. 写入以下规则内容:
polkit.addRule(function(action, subject) {
    // 匹配所有关机、重启相关的动作
    var shutdownActions = [
        "org.freedesktop.login1.power-off",
        "org.freedesktop.login1.power-off-multiple-sessions",
        "org.freedesktop.login1.reboot",
        "org.freedesktop.login1.reboot-multiple-sessions"
    ];
    
    if (shutdownActions.indexOf(action.id) !== -1) {
        // 检查锁文件是否存在
        var lockFile = "/var/run/usb_shutdown_lock";
        var fileExists = Polkit.File.exists(lockFile);
        
        if (fileExists) {
            // 锁文件存在,拒绝关机/重启请求
            return polkit.Result.REJECT;
        } else {
            // 锁文件不存在,允许操作
            return polkit.Result.ALLOW;
        }
    }
});
三、额外注意事项和优化点
  • 依赖安装:如果用上面的Python脚本,需要安装pyudev库,Debian/Ubuntu系统可以用sudo apt install python3-pyudev,其他系统用pip install pyudev
  • 后台运行:把监控程序做成systemd守护进程,避免终端关闭就停止运行。创建/etc/systemd/system/usb-shutdown-monitor.service文件:
    [Unit]
    Description=USB Shutdown Monitor
    After=multi-user.target
    
    [Service]
    Type=simple
    User=root
    ExecStart=/usr/bin/python3 /path/to/your/monitor.py
    Restart=always
    
    [Install]
    WantedBy=multi-user.target
    
    然后执行sudo systemctl daemon-reload && sudo systemctl enable --now usb-shutdown-monitor.service启用服务
  • 权限问题:锁文件和Polkit规则文件都需要属于root用户,确保普通用户无法篡改,规则文件权限设为644即可
  • 测试验证:插U盘后尝试执行systemctl poweroff,应该会被拒绝;拔掉U盘后再次尝试,就能正常关机了

内容的提问来源于stack exchange,提问作者AlmuHS

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 09:01:41