Udev钩子自动备份USB内容失效,但脚本单独运行正常求助
UDEV规则触发U盘自动备份失败的排查与解决
问题描述
我在/etc/udev/rules.d中配置了规则,意图实现插入指定厂商的U盘时自动备份内容到指定目录。手动执行脚本一切正常,但U盘插入触发时挂载失败,仅能创建备份目录。相关配置如下:
规则文件80-local.rules
student@student-VirtualBox:/etc/udev/rules.d$ cat 80-local.rules SUBSYSTEM=="block", ACTION=="add", ATTRS{idVendor}=="058f", RUN+="/home/student/psop/triggertools/bin/principal.sh"
脚本principal.sh
#!/bin/bash log_file="/home/student/psop/logs" first_script="/home/student/psop/triggertools/bin/trigger.sh" echo Starting scrip ... > "$log_file" bash "$first_script"
脚本trigger.sh
#!/bin/bash log_file="/home/student/psop/logs" backup_dir="/home/student/psop/backupdir" mount_dir="/home/student/psop/mountdir" usb_device="/dev/sdb1" if [ ! -d "$backup_dir" ] then mkdir -p "$backup_dir" fi sudo systemd-mount --no-block --automount=no --collect "$usb_device" "$mount_dir" >> "$log_file" 2>&1 sleep 5 echo "Continut folder de montare: " >> "$log_file" ls "$mount_dir" >> "$log_file" if [ $? -eq 0 ] then sudo /usr/local/bin/backup "$mount_dir" "$backup_dir" >> "$log_file" 2>&1 sleep 5 sudo umount "$usb_device" >> "$log_file" else echo "Eroare la montarea dispozitivului!" >> "$log_file" 2>&1 fi
核心问题点
- UDEV运行环境受限:UDEV触发的脚本在无完整用户环境的后台进程中运行,
sudo无法获取用户权限上下文,导致挂载命令执行失败。 - 硬编码设备路径:固定写死
/dev/sdb1,但U盘设备路径可能随系统存储设备状态变化,导致脚本找不到正确设备。 - 设备初始化时机:UDEV触发
add动作时,设备可能尚未完全初始化完成,此时执行挂载会失败,手动执行时设备已就绪所以正常。
修复步骤
1. 修改UDEV规则,传递设备信息并调度到用户会话
更新80-local.rules,用systemd-run将脚本放到用户会话环境中运行,同时传递设备路径:
SUBSYSTEM=="block", ACTION=="add", ATTRS{idVendor}=="058f", ENV{DEVNAME}=="?*", RUN+="/usr/bin/systemd-run --user --scope /home/student/psop/triggertools/bin/principal.sh $env{DEVNAME}"
--user:让脚本在当前用户的会话环境中运行,获取完整权限和环境变量$env{DEVNAME}:将UDEV识别到的实际设备路径传递给脚本
2. 修改脚本接收动态设备路径
更新principal.sh,把设备路径参数传递给trigger.sh:
#!/bin/bash log_file="/home/student/psop/logs" first_script="/home/student/psop/triggertools/bin/trigger.sh" echo Starting script ... > "$log_file" bash "$first_script" "$1" # 传递UDEV传来的设备路径
更新trigger.sh,替换硬编码的设备路径为传入参数:
#!/bin/bash log_file="/home/student/psop/logs" backup_dir="/home/student/psop/backupdir" mount_dir="/home/student/psop/mountdir" usb_device="$1" # 接收设备路径参数 # 检查是否获取到设备路径 if [ -z "$usb_device" ]; then echo "未获取到有效设备路径" >> "$log_file" exit 1 fi if [ ! -d "$backup_dir" ] then mkdir -p "$backup_dir" fi # 移除sudo,利用systemd-run的用户权限上下文执行挂载 systemd-mount --no-block --automount=no --collect "$usb_device" "$mount_dir" >> "$log_file" 2>&1 sleep 8 # 延长等待时间,确保设备完全初始化 echo "Continut folder de montare: " >> "$log_file" ls "$mount_dir" >> "$log_file" if [ $? -eq 0 ] then /usr/local/bin/backup "$mount_dir" "$backup_dir" >> "$log_file" 2>&1 sleep 5 umount "$usb_device" >> "$log_file" else echo "Eroare la montarea dispozitivului!" >> "$log_file" 2>&1 fi
3. 配置用户免权限挂载(可选)
如果用户执行systemd-mount仍有权限问题,创建sudoers规则文件:
sudo nano /etc/sudoers.d/student-mount
添加内容:
student ALL=(ALL) NOPASSWD: /usr/bin/systemd-mount, /usr/bin/umount
设置文件权限:
sudo chmod 0440 /etc/sudoers.d/student-mount
4. 重新加载UDEV规则
使修改后的规则生效:
sudo udevadm control --reload-rules sudo udevadm trigger
内容的提问来源于stack exchange,提问作者Samuel Edi
相关产品推荐
相关产品推荐

