工控存储外设:U 盘/SD 卡自动挂载、插拔检测、文件拷贝备份
2026/7/25 2:52:20 网站建设 项目流程

工控存储外设:U 盘/SD 卡自动挂载、插拔检测、文件拷贝备份

工控现场最常见的需求之一:插上U盘,自动把数据拷走,拔掉U盘,数据不损坏。听起来简单,坑却不少。

一、Linux USB / SD 卡设备识别机制

当外部存储设备插入时,Linux 内核会自动识别并分配设备节点:

设备类型设备节点说明
U盘/dev/sda1,/dev/sdb1SCSI子系统分配,按字母递增
SD卡/dev/mmcblk0p1MMC子系统分配,pN表示第N分区
CD-ROM/dev/sr0较少见,工控中偶尔用于离线升级

关键区分:U盘是/dev/sd*,SD卡是/dev/mmcblk*,写脚本时千万别搞混。

查看当前已识别的块设备:

cat/proc/partitions# 或者lsblk

二、udev 规则配置

2.1 什么是 udev

udev是 Linux 的设备管理器,负责在设备插入/拔出时执行预定义规则。工控场景下,我们靠它实现自动挂载权限设置

2.2 udev 规则语法

规则文件放在/etc/udev/rules.d/目录下,文件名以数字开头控制优先级:

# /etc/udev/rules.d/99-usb-storage.rules # U盘插入时触发 ACTION=="add", SUBSYSTEM=="block", KERNEL=="sd[a-z][0-9]", \ RUN+="/etc/udev/scripts/mount-usb.sh %k" # U盘拔出时触发 ACTION=="remove", SUBSYSTEM=="block", KERNEL=="sd[a-z][0-9]", \ RUN+="/etc/udev/scripts/umount-usb.sh %k" # SD卡插入时触发 ACTION=="add", SUBSYSTEM=="block", KERNEL=="mmcblk[0-9]p[0-9]", \ RUN+="/etc/udev/scripts/mount-usb.sh %k" # SD卡拔出时触发 ACTION=="remove", SUBSYSTEM=="block", KERNEL=="mmcblk[0-9]p[0-9]", \ RUN+="/etc/udev/scripts/umount-usb.sh %k"

规则字段解读

  • ACTIONadd(插入)或remove(拔出)
  • SUBSYSTEM:设备子系统,存储设备是block
  • KERNEL:内核设备名匹配,支持通配
  • RUN+:匹配时执行的脚本,%k传入设备名(如sda1

2.3 自定义设备名

如果想让特定的U盘固定挂载名(比如"数据盘"),可以通过设备的唯一标识匹配:

# 查看U盘的唯一标识 udevadm info --query=all --name=/dev/sda1 | grep ID_SERIAL # 按序列号绑定固定名称 ACTION=="add", SUBSYSTEM=="block", \ ENV{ID_SERIAL}=="USB_Flash_Drive_123456", \ SYMLINK+="data_usb"

这样该U盘插入后会出现/dev/data_usb软链接,换一个U盘就不行——工控现场防插错U盘的神技。

三、mdev 配置(精简 Buildroot 系统)

如果工控板用的是 Buildroot 精简系统,可能没有udev,而是用busybox mdev。配置方式不同:

# /etc/mdev.conf# U盘分区自动挂载sd[a-z][0-9]0:0 0666 */etc/udev/scripts/mount-usb.sh$MDEVmmcblk[0-9]p[0-9]0:0 0666 */etc/udev/scripts/mount-usb.sh$MDEV# 拔出时卸载sd[a-z][0-9]0:0 0666 *$/etc/udev/scripts/umount-usb.sh$MDEV

同时需要确保/etc/init.d/中有启动mdev -s的脚本,并在内核中开启热插拔支持:

echo/sbin/mdev>/proc/sys/kernel/hotplug mdev-s

四、udevadm monitor 监控插拔事件

调试 udev 规则时,最实用的命令就是udevadm monitor

# 监控所有uevent事件udevadm monitor# 只看block子系统udevadm monitor --subsystem-match=block# 查看设备详细属性(用于写规则)udevadm info-a-n/dev/sda1

插拔U盘时,终端会实时输出事件流,方便你确认KERNELSUBSYSTEM字段是否正确。

五、自动挂载脚本实现

5.1 挂载脚本

#!/bin/sh# /etc/udev/scripts/mount-usb.sh# 用法: mount-usb.sh <device> 例如: mount-usb.sh sda1DEV=$1MOUNT_DIR="/mnt/usb/$DEV"# 等待设备节点就绪(内核可能还没创建完)i=0while[!-e"/dev/$DEV"]&&[$i-lt20];dosleep0.1i=$((i+1))doneif[!-e"/dev/$DEV"];thenlogger"mount-usb: /dev/$DEVnot found, timeout"exit1fi# 创建挂载点mkdir-p"$MOUNT_DIR"# 尝试挂载(支持vfat和ext4等常见格式)mount-tvfat"/dev/$DEV""$MOUNT_DIR"2>/dev/null||\mount-texfat"/dev/$DEV""$MOUNT_DIR"2>/dev/null||\mount-text4"/dev/$DEV""$MOUNT_DIR"2>/dev/null||\mount"/dev/$DEV""$MOUNT_DIR"2>/dev/nullif[$?-eq0];thenlogger"mount-usb: /dev/$DEVmounted to$MOUNT_DIR"# 触发数据同步脚本(可选)/etc/udev/scripts/sync-data.sh"$MOUNT_DIR"&elselogger"mount-usb: failed to mount /dev/$DEV"rmdir"$MOUNT_DIR"2>/dev/nullfi

5.2 卸载脚本

#!/bin/sh# /etc/udev/scripts/umount-usb.sh# 用法: umount-usb.sh <device>DEV=$1MOUNT_DIR="/mnt/usb/$DEV"# 检查是否还在挂载状态ifmountpoint-q"$MOUNT_DIR";then# 先sync刷新缓冲,防止数据损坏syncumount"$MOUNT_DIR"logger"umount-usb: /dev/$DEVunmounted from$MOUNT_DIR"fi# 清理挂载点目录rmdir"$MOUNT_DIR"2>/dev/null logger"umount-usb: cleanup$MOUNT_DIR"

关键细节:卸载前一定要sync!Linux 文件系统有写缓存,直接拔U盘可能丢数据。

六、文件拷贝备份脚本

工控场景典型需求:U盘插入后自动把设备上的数据目录拷贝过去,并校验完整性。

#!/bin/sh# /etc/udev/scripts/sync-data.sh# 用法: sync-data.sh <mount_dir>MOUNT_DIR=$1DATA_DIR="/var/log/device_data"# 本地数据目录BACKUP_LOG="/var/log/backup.log"# 等待挂载稳定sleep2logger"sync-data: starting backup to$MOUNT_DIR"# 生成本次备份的目录名(带时间戳)BACKUP_NAME="backup_$(date+%Y%m%d_%H%M%S)"TARGET="$MOUNT_DIR/$BACKUP_NAME"# 执行拷贝mkdir-p"$TARGET"cp-a"$DATA_DIR"/*"$TARGET"/2>/dev/nullif[$?-ne0];thenlogger"sync-data: ERROR copy failed"exit1fi# MD5校验 - 生成本次备份的文件清单和校验值cd"$TARGET"find.-typef-execmd5sum{}\;>checksum.md5# 验证校验md5sum-cchecksum.md5>/dev/null2>&1if[$?-eq0];thenlogger"sync-data: backup OK, files at$TARGET"# 写入备份日志echo"$(date'+%Y-%m-%d %H:%M:%S')BACKUP OK ->$TARGET">>"$BACKUP_LOG"elselogger"sync-data: WARNING checksum verification failed"echo"$(date'+%Y-%m-%d %H:%M:%S')BACKUP CHECKSUM FAIL ->$TARGET">>"$BACKUP_LOG"fi# 刷新缓冲,确保数据落盘sync

七、热插拔安全性

工控现场拔U盘不讲究,所以驱动和脚本层面要做好保护:

措施说明
卸载前sync刷新文件系统缓冲到物理设备
使用umount而非直接拔通知文件系统释放资源
mountsync选项mount -o sync实时写入,牺牲性能换安全
只读挂载选项mount -o ro读取场景下防止误写
日志记录logger记录每次挂载/卸载事件,便于追溯

挂载时加上sync,uid=0,gid=0,umask=000参数对 vfat 格式很实用:

mount-tvfat-osync,umask=000"/dev/$DEV""$MOUNT_DIR"

umask=000让所有用户可读写,避免工控程序因权限问题写不进U盘。

八、多分区 U 盘处理

一个U盘可能有多个分区(如sda1sda2),udev 规则中KERNEL=="sd[a-z][0-9]"已经能匹配所有分区,但脚本需要处理每个分区独立挂载:

# 挂载点按分区号区分,不会互相覆盖MOUNT_DIR="/mnt/usb/$DEV"# sda1 -> /mnt/usb/sda1# sda2 -> /mnt/usb/sda2

九、工控存储常见问题汇总

问题原因解决方案
U盘识别但无法挂载文件系统不支持编译内核时开启 vfat/exfat/ntfs 支持
挂载后权限不足默认只有root可写mount -o umask=000或修改 udev 规则赋权
拔U盘后数据丢失缓冲未刷新脚本中加sync,或挂载时用-o sync
设备节点名不固定按插入顺序分配字母ENV{ID_SERIAL}匹配固定符号链接
频繁插拔导致挂载点残留umount 失败脚本中fuser -k杀死占用进程后再卸载
SD卡分区识别不到没有分区表直接挂/dev/mmcblk0而非mmcblk0p1

存储外设自动挂载看似简单,但要在工控环境中做到无人值守、数据不丢、即插即用,每一个环节的细节都不能含糊。sync该加的加,校验该做的做,脚本该有的容错一个都不能少。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询