You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Linux下如何实现插入USB时自动执行Python脚本并显示输出?

Linux下如何实现插入USB时自动执行Python脚本并显示输出?

嗨,我来帮你搞定这个问题!你遇到的「udev能触发脚本但没输出」的情况,其实是个很常见的坑——udev是在后台系统环境里运行的,它不绑定当前登录用户的显示会话,所以脚本的输出根本找不到地方去显示。下面给你一步步讲怎么解决:

核心思路:让脚本跑在用户的显示会话里

要让输出显示在屏幕上,必须让Python脚本在当前登录用户的X11/Wayland会话环境中执行,而不是udev的孤立后台环境。我们可以通过「udev触发shell中转脚本」+「中转脚本切换到用户会话」的方式实现。

步骤1:写好udev规则(匹配USB插入事件)

先创建一个udev规则文件,让系统检测到USB插入时触发中转脚本:

  1. 打开终端,创建规则文件:
    sudo nano /etc/udev/rules.d/99-usb-auto-run.rules
    
  2. 写入以下内容(可根据你的需求调整匹配条件):
    ACTION=="add", SUBSYSTEM=="block", ENV{ID_BUS}=="usb", RUN+="/usr/local/bin/usb-trigger-script.sh"
    
    • ACTION=="add":匹配设备插入事件
    • SUBSYSTEM=="block":匹配块设备(U盘属于这类)
    • ENV{ID_BUS}=="usb":限定触发对象是USB设备
    • RUN+="...":指定要执行的中转脚本路径

步骤2:编写中转shell脚本(处理会话环境)

这个脚本的作用是获取当前用户的显示会话信息,让Python脚本在正确的环境里跑:

  1. 创建中转脚本:
    sudo nano /usr/local/bin/usb-trigger-script.sh
    
  2. 写入以下内容:
    #!/bin/bash
    
    # 拿到当前登录的第一个用户(多用户登录时可按需调整取哪个)
    LOGGED_USER=$(who | grep -E "\(:[0-9]+\)$" | head -n1 | cut -d" " -f1)
    # 拿到对应的显示端口(比如:0)
    DISPLAY=$(who | grep -E "\(:[0-9]+\)$" | head -n1 | grep -oE ":[0-9]+")
    # X11会话的权限文件路径
    XAUTHORITY="/home/$LOGGED_USER/.Xauthority"
    
    # 切换到登录用户,设置环境变量后执行Python脚本
    # 这里提供两种输出方式,选一种注释掉另一种即可:
    # 方式1:输出到终端(若用户在使用终端)+ 写入日志文件备查
    su $LOGGED_USER -c "export DISPLAY=$DISPLAY; export XAUTHORITY=$XAUTHORITY; /path/to/your/script.py | tee /tmp/usb-script-output.log"
    
    # 方式2:用图形弹窗显示输出(适合图形界面用户)
    # su $LOGGED_USER -c "export DISPLAY=$DISPLAY; export XAUTHORITY=$XAUTHORITY; zenity --info --text=\"\$(/path/to/your/script.py)\""
    
  3. /path/to/your/script.py改成你实际的Python脚本路径。

步骤3:给脚本加权限并重新加载规则

  1. 给中转脚本添加执行权限:
    sudo chmod +x /usr/local/bin/usb-trigger-script.sh
    
  2. 重新加载udev规则,让新规则立即生效:
    sudo udevadm control --reload-rules
    

进阶:用systemd替代直接RUN(更稳定)

如果你的U盘挂载有延迟,udev触发时设备还没准备好,可以用systemd服务来处理,可靠性更高:

  1. 修改udev规则为:
    ACTION=="add", SUBSYSTEM=="block", ENV{ID_BUS}=="usb", TAG+="systemd", ENV{SYSTEMD_WANTS}="usb-auto-run.service"
    
  2. 创建systemd服务文件:
    sudo nano /etc/systemd/system/usb-auto-run.service
    
  3. 写入内容:
    [Unit]
    Description=Auto run Python script when USB is inserted
    After=multi-user.target
    
    [Service]
    Type=oneshot
    User=%I
    ExecStart=/usr/local/bin/usb-trigger-script.sh
    Environment="DISPLAY=:0"
    Environment="XAUTHORITY=/home/%I/.Xauthority"
    
  4. 重新加载systemd配置:
    sudo systemctl daemon-reload
    

一些实用注意点

  • 如果你用的是Wayland会话,DISPLAY变量通常还是:0,如果不行,可以用loginctl show-user $LOGGED_USER -p Display来获取正确的显示标识。
  • 测试时可以先手动执行中转脚本,确认它能正常输出后,再拔插USB做实际测试。
  • 如果Python脚本需要访问U盘内的文件,记得在脚本开头加sleep 2之类的延迟,给系统留足挂载U盘的时间。

备注:内容来源于stack exchange,提问作者Andrea Aggiunto

火山引擎 最新活动