USB连接时自动运行Bash脚本无法获取USB信息
问题分析与解决方案
你完全说对了——就是脚本执行时机太早!
当udev触发你的规则时,系统只是刚识别到USB设备的底层块设备(比如/dev/sdb),但还没完成分区扫描、文件系统识别这些后续步骤,这时候blkid根本找不到对应的LABEL、TYPE信息,而且你用tail -1取最后一条的方式本身也很不稳定(万一系统里有其他块设备,很容易拿到错误的结果)。
下面给你几个针对性的解决办法:
1. 调整udev规则,精准触发且延迟执行
首先修改你的10.usb-rules,改成针对分区设备(比如/dev/sdb1)触发,而不是整个块设备,同时把设备名传给脚本:
KERNEL=="sd*[0-9]", SUBSYSTEMS=="usb", RUN+="/home/user/test.sh %k"
KERNEL=="sd*[0-9]":匹配USB的分区设备(比如sdb1、sdc2),这时候分区已经被识别,文件系统信息也基本就绪%k:udev会把当前设备的短名称(比如sdb1)作为参数传给你的脚本
如果还是遇到时机问题,可以给规则加个执行优先级,让它晚一点触发:
KERNEL=="sd*[0-9]", SUBSYSTEMS=="usb", ENV{UDevRuleRunOrder}="99", RUN+="/home/user/test.sh %k"
2. 重写脚本,精准查询指定设备
把脚本改成直接接收udev传过来的设备名,然后针对性查询,避免全局查找的不确定性:
#!/bin/bash # 接收udev传递的设备短名称(比如sdb1) DEVICE_SHORT_NAME="$1" USB_DEVICE="/dev/$DEVICE_SHORT_NAME" # 用绝对路径调用blkid,避免udev环境找不到命令 BLKID="/sbin/blkid" # 直接查询指定设备的LABEL和TYPE USB_NAME=$($BLKID -o value -s LABEL "$USB_DEVICE") USB_TYPE=$($BLKID -o value -s TYPE "$USB_DEVICE") # (可选)如果还是偶尔拿不到信息,加个短延时确保设备完全就绪 # sleep 1 # 这里写你的后续逻辑,比如打印信息或者做其他处理 echo "USB设备路径: $USB_DEVICE" >> /tmp/usb-log.txt echo "USB名称: $USB_NAME" >> /tmp/usb-log.txt echo "USB文件系统类型: $USB_TYPE" >> /tmp/usb-log.txt
额外注意事项
- udev的
RUN命令是在udev守护进程的环境下运行的,环境变量非常少,所以所有命令尽量用绝对路径(比如/sbin/blkid而不是blkid) - 不要在udev触发的脚本里做耗时操作,udev会超时终止;如果需要做复杂操作,可以把任务放到后台,或者用
at now + 1 minute这类命令延迟执行 - 如果脚本需要访问桌面环境(比如弹出通知),需要手动设置
DISPLAY和XAUTHORITY环境变量,比如:export DISPLAY=:0 export XAUTHORITY=/home/user/.Xauthority notify-send "USB已连接" "名称: $USB_NAME"
内容的提问来源于stack exchange,提问作者tiger_groove
相关产品推荐
相关产品推荐

