如何防止故障USB驱动器导致Ubuntu服务器冻结无响应?
如何防止故障USB驱动器导致Ubuntu服务器冻结无响应?
遇到过一模一样的糟心情况!USB磁盘挂掉后把整个系统拖得完全没法操作,连SSH都连不上,只能硬重启,折腾死人。结合我踩过的坑,给你几个实际可行的解决方案,从简单到进阶:
1. 先优化fstab挂载参数(最快速见效)
你现有的fstab参数已经有nofail和x-systemd.device-timeout,但还可以调整几个关键选项来避免系统无限等待IO:
修改后的fstab条目参考:
UUID=UUID_HERE /data/path/disk1 ext4 user,defaults,nofail,noatime,commit=60,x-systemd.device-timeout=30,x-systemd.mount-timeout=30,errors=remount-ro 0 2 # Modified to prevent freeze on failure
逐个解释调整的点:
errors=remount-ro:把你原来的errors=continue换成这个,当文件系统检测到错误时,自动把磁盘挂载为只读模式,避免系统持续重试IO操作导致IO Wait飙升卡死。x-systemd.mount-timeout=30:新增这个参数,让systemd在挂载操作超时30秒后直接放弃,不会一直等设备响应。- 缩小
x-systemd.device-timeout到30:原来的120秒太长,缩短后系统能更快识别设备故障,不会长时间卡在IO等待上。
修改后记得执行sudo mount -a测试挂载是否正常,没问题的话重启让参数生效。
2. 用udev规则自动处理故障磁盘(进阶自动修复)
如果单纯调整挂载参数还不够,可以用udev规则监控磁盘状态,一旦检测到故障就自动卸载甚至断电USB端口,彻底切断故障设备的影响:
步骤1:安装USB端口控制工具
先装uhubctl,这个工具能控制USB端口的电源:
sudo apt update && sudo apt install uhubctl
步骤2:写故障处理脚本
创建脚本/usr/local/bin/usb-fault-handler.sh,内容如下:
#!/bin/bash MOUNT_POINT="/data/path/disk1" DISK_SERIAL="你的磁盘序列号" # 替换成实际的磁盘序列号 # 先尝试正常卸载 umount "$MOUNT_POINT" if [ $? -ne 0 ]; then # 正常卸载失败就用懒卸载(安全强制卸载) umount -l "$MOUNT_POINT" fi # 找到对应USB端口并断电 # 先查看你的USB总线编号,执行uhubctl会输出类似1-1、2-1的总线标识 uhubctl -l 1-1 -a status | grep "$DISK_SERIAL" | awk '{print $4}' | while read PORT; do uhubctl -l 1-1 -p "$PORT" -a off done
给脚本加执行权限:
sudo chmod +x /usr/local/bin/usb-fault-handler.sh
步骤3:写udev规则
创建/etc/udev/rules.d/99-usb-fault.rules规则文件:
KERNEL=="sd*", SUBSYSTEM=="block", ENV{DEVTYPE}=="disk", ACTION=="change", ENV{ID_SERIAL_SHORT}=="你的磁盘序列号", RUN+="/usr/local/bin/usb-fault-handler.sh"
替换里面的“你的磁盘序列号”,可以用这个命令获取:
lsblk -no SERIAL /dev/sdX # 把sdX换成你的USB磁盘设备名,比如sdb
最后重载udev规则生效:
sudo udevadm control --reload-rules
3. 定时监控脚本(兜底方案)
如果udev规则没触发,还可以加个定时脚本,每分钟检查一次磁盘状态,发现故障就强制卸载:
创建脚本/usr/local/bin/check-disk-health.sh:
#!/bin/bash MOUNT_POINT="/data/path/disk1" DISK_DEVICE="/dev/sdX" # 替换成你的磁盘设备名 # 尝试读取磁盘的第一个扇区,测试是否响应 if ! dd if="$DISK_DEVICE" of=/dev/null bs=512 count=1 2>/dev/null; then echo "磁盘$DISK_DEVICE无响应,尝试卸载..." umount -l "$MOUNT_POINT" fi
加执行权限:
sudo chmod +x /usr/local/bin/check-disk-health.sh
然后用crontab添加定时任务,每分钟执行一次:
crontab -e
添加一行:
* * * * * /usr/local/bin/check-disk-health.sh >> /var/log/disk-monitor.log 2>&1
这样脚本会把日志写到/var/log/disk-monitor.log,方便后续排查。
额外小贴士
- 尽量用
umount -l(懒卸载)代替umount -f(强制卸载),前者不会强制终止正在运行的进程,更安全,系统会在合适的时候清理挂载点。 - 可以开启
smartmontools监控磁盘健康,提前预警故障:sudo apt install smartmontools,然后配置/etc/smartd.conf让它定期检测磁盘状态。
备注:内容来源于stack exchange,提问作者Hackeron
相关产品推荐
相关产品推荐

