Proxmox环境下udev触发脚本时scp超时,手动或cron执行正常求助
问题核心成因
- udev 触发脚本的时机是电源硬件事件发生的第一时间,此时物理机刚从AC供电切换到电池供电,笔记本网卡会同步触发电源模式切换,网络连通性存在数十秒的中断窗口,scp在这个时间点发起连接必然超时。
- udevd 派生的子进程运行在精简的系统上下文里,没有继承手动登录环境下的完整路由栈、网络权限配置,很容易出现网络不通的问题。
- udev 原生定位是快速处理硬件事件,不支持长耗时的网络操作,对派生的子进程有强制超时监控,日志里看到的59秒超时就是udev的默认监控阈值触发的告警。
对应可落地的解决方案
1. 优化脚本逻辑,适配状态切换的等待窗口
不要在udev触发的瞬间立刻执行网络操作,增加等待时间和重试机制,避开网卡状态切换的断流窗口:
#!/usr/bin/bash # 等待30秒,留足网卡电源模式切换、网络连通性恢复的时间 sleep 30 FILE=/sys/class/power_supply/BAT1/uevent awk -F'=' 'BEGIN {printf "{"} /POWER_SUPPLY/ {printf "\"" $1 "\":\"" $2 "\","} END {print "}"}' $FILE | sed 's/,}/}/' >/root/uevent1.json # 缩短单次连接超时,增加最多3次重试,避免单次卡满1分钟超时 for i in {1..3}; do /usr/bin/scp -o ConnectTimeout=10 /root/uevent1.json root@192.168.7.48:/root/config/BAT1 && break sleep 10 done
注意:去掉原scp命令里的
-v调试参数,非交互场景下的调试输出会占用进程句柄,容易触发udev的异常判定。
2. 调整架构,将脚本执行权从udev转移给systemd
udev规则仅做简单的事件触发,不要直接执行业务脚本,让脚本在完整的系统环境下运行,从根源上规避udev环境的限制:
- 新建systemd服务单元文件
/etc/systemd/system/bat-update.service,内容为:
[Unit] Description=推送电池状态到Home Assistant虚拟机 After=network.target [Service] Type=oneshot ExecStart=/usr/local/bin/batupdate1.sh
- 修改原有udev规则,把直接调用脚本的逻辑改成触发systemd服务:
SUBSYSTEM=="power_supply", ACTION=="change", RUN+="/usr/bin/systemctl start bat-update.service"
- 执行以下命令让配置生效:
udevadm control --reload-rules systemctl daemon-reload
这种方式下,脚本会由systemd负责调度,运行在和手动执行完全一致的系统环境里,且自带网络就绪判断,不会被udev的超时机制强制中断。
3. 消除网卡电源管理的断流影响
从系统层面禁用笔记本网卡的runtime电源管理,避免AC供电状态切换时网卡自动进入低功耗模式造成的临时断网:
- 用
ip addr查到对应正在使用的网卡名称,执行ethtool <网卡名>查看当前电源唤醒状态 - 临时关闭网卡的唤醒功能:
ethtool -s <网卡名> wol d - 把对应的网卡配置写入udev规则,实现永久禁用电源管理的效果。
排查验证方法
修改完成后,可以手动模拟电源事件触发udev规则,观察脚本执行流程:
# 模拟BAT1的状态变更事件 udevadm trigger --subsystem-match=power_supply --action=change # 实时查看syslog日志确认执行状态 journalctl -f -u bat-update.service
内容的提问来源于stack exchange,提问作者JJC
相关产品推荐
相关产品推荐

