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

工控存储外设:U 盘/SD 卡自动挂载、插拔检测、文件拷贝备份
工控存储外设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 什么是 udevudev是 Linux 的设备管理器负责在设备插入/拔出时执行预定义规则。工控场景下我们靠它实现自动挂载和权限设置。2.2 udev 规则语法规则文件放在/etc/udev/rules.d/目录下文件名以数字开头控制优先级# /etc/udev/rules.d/99-usb-storage.rules # U盘插入时触发 ACTIONadd, SUBSYSTEMblock, KERNELsd[a-z][0-9], \ RUN/etc/udev/scripts/mount-usb.sh %k # U盘拔出时触发 ACTIONremove, SUBSYSTEMblock, KERNELsd[a-z][0-9], \ RUN/etc/udev/scripts/umount-usb.sh %k # SD卡插入时触发 ACTIONadd, SUBSYSTEMblock, KERNELmmcblk[0-9]p[0-9], \ RUN/etc/udev/scripts/mount-usb.sh %k # SD卡拔出时触发 ACTIONremove, SUBSYSTEMblock, KERNELmmcblk[0-9]p[0-9], \ RUN/etc/udev/scripts/umount-usb.sh %k规则字段解读ACTIONadd插入或remove拔出SUBSYSTEM设备子系统存储设备是blockKERNEL内核设备名匹配支持通配RUN匹配时执行的脚本%k传入设备名如sda12.3 自定义设备名如果想让特定的U盘固定挂载名比如数据盘可以通过设备的唯一标识匹配# 查看U盘的唯一标识 udevadm info --queryall --name/dev/sda1 | grep ID_SERIAL # 按序列号绑定固定名称 ACTIONadd, SUBSYSTEMblock, \ ENV{ID_SERIAL}USB_Flash_Drive_123456, \ SYMLINKdata_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-matchblock# 查看设备详细属性用于写规则udevadm info-a-n/dev/sda1插拔U盘时终端会实时输出事件流方便你确认KERNEL和SUBSYSTEM字段是否正确。五、自动挂载脚本实现5.1 挂载脚本#!/bin/sh# /etc/udev/scripts/mount-usb.sh# 用法: mount-usb.sh device 例如: mount-usb.sh sda1DEV$1MOUNT_DIR/mnt/usb/$DEV# 等待设备节点就绪内核可能还没创建完i0while[!-e/dev/$DEV][$i-lt20];dosleep0.1i$((i1))doneif[!-e/dev/$DEV];thenloggermount-usb: /dev/$DEVnot found, timeoutexit1fi# 创建挂载点mkdir-p$MOUNT_DIR# 尝试挂载支持vfat和ext4等常见格式mount-tvfat/dev/$DEV$MOUNT_DIR2/dev/null||\mount-texfat/dev/$DEV$MOUNT_DIR2/dev/null||\mount-text4/dev/$DEV$MOUNT_DIR2/dev/null||\mount/dev/$DEV$MOUNT_DIR2/dev/nullif[$?-eq0];thenloggermount-usb: /dev/$DEVmounted to$MOUNT_DIR# 触发数据同步脚本可选/etc/udev/scripts/sync-data.sh$MOUNT_DIRelseloggermount-usb: failed to mount /dev/$DEVrmdir$MOUNT_DIR2/dev/nullfi5.2 卸载脚本#!/bin/sh# /etc/udev/scripts/umount-usb.sh# 用法: umount-usb.sh deviceDEV$1MOUNT_DIR/mnt/usb/$DEV# 检查是否还在挂载状态ifmountpoint-q$MOUNT_DIR;then# 先sync刷新缓冲防止数据损坏syncumount$MOUNT_DIRloggerumount-usb: /dev/$DEVunmounted from$MOUNT_DIRfi# 清理挂载点目录rmdir$MOUNT_DIR2/dev/null loggerumount-usb: cleanup$MOUNT_DIR关键细节卸载前一定要syncLinux 文件系统有写缓存直接拔U盘可能丢数据。六、文件拷贝备份脚本工控场景典型需求U盘插入后自动把设备上的数据目录拷贝过去并校验完整性。#!/bin/sh# /etc/udev/scripts/sync-data.sh# 用法: sync-data.sh mount_dirMOUNT_DIR$1DATA_DIR/var/log/device_data# 本地数据目录BACKUP_LOG/var/log/backup.log# 等待挂载稳定sleep2loggersync-data: starting backup to$MOUNT_DIR# 生成本次备份的目录名带时间戳BACKUP_NAMEbackup_$(date%Y%m%d_%H%M%S)TARGET$MOUNT_DIR/$BACKUP_NAME# 执行拷贝mkdir-p$TARGETcp-a$DATA_DIR/*$TARGET/2/dev/nullif[$?-ne0];thenloggersync-data: ERROR copy failedexit1fi# MD5校验 - 生成本次备份的文件清单和校验值cd$TARGETfind.-typef-execmd5sum{}\;checksum.md5# 验证校验md5sum-cchecksum.md5/dev/null21if[$?-eq0];thenloggersync-data: backup OK, files at$TARGET# 写入备份日志echo$(date%Y-%m-%d %H:%M:%S)BACKUP OK -$TARGET$BACKUP_LOGelseloggersync-data: WARNING checksum verification failedecho$(date%Y-%m-%d %H:%M:%S)BACKUP CHECKSUM FAIL -$TARGET$BACKUP_LOGfi# 刷新缓冲确保数据落盘sync七、热插拔安全性工控现场拔U盘不讲究所以驱动和脚本层面要做好保护措施说明卸载前sync刷新文件系统缓冲到物理设备使用umount而非直接拔通知文件系统释放资源mount加sync选项mount -o sync实时写入牺牲性能换安全只读挂载选项mount -o ro读取场景下防止误写日志记录logger记录每次挂载/卸载事件便于追溯挂载时加上sync,uid0,gid0,umask000参数对 vfat 格式很实用mount-tvfat-osync,umask000/dev/$DEV$MOUNT_DIRumask000让所有用户可读写避免工控程序因权限问题写不进U盘。八、多分区 U 盘处理一个U盘可能有多个分区如sda1、sda2udev 规则中KERNELsd[a-z][0-9]已经能匹配所有分区但脚本需要处理每个分区独立挂载# 挂载点按分区号区分不会互相覆盖MOUNT_DIR/mnt/usb/$DEV# sda1 - /mnt/usb/sda1# sda2 - /mnt/usb/sda2九、工控存储常见问题汇总问题原因解决方案U盘识别但无法挂载文件系统不支持编译内核时开启 vfat/exfat/ntfs 支持挂载后权限不足默认只有root可写mount -o umask000或修改 udev 规则赋权拔U盘后数据丢失缓冲未刷新脚本中加sync或挂载时用-o sync设备节点名不固定按插入顺序分配字母用ENV{ID_SERIAL}匹配固定符号链接频繁插拔导致挂载点残留umount 失败脚本中fuser -k杀死占用进程后再卸载SD卡分区识别不到没有分区表直接挂/dev/mmcblk0而非mmcblk0p1存储外设自动挂载看似简单但要在工控环境中做到无人值守、数据不丢、即插即用每一个环节的细节都不能含糊。sync该加的加校验该做的做脚本该有的容错一个都不能少。