工控必备Shell脚本开发:自动挂载、日志归档、看门狗、程序守护脚本

📅 2026/7/24 2:15:53 👁️ 阅读次数 📝 编程学习
工控必备Shell脚本开发:自动挂载、日志归档、看门狗、程序守护脚本

工控必备Shell脚本开发:自动挂载、日志归档、看门狗、程序守护脚本

工控设备没有人在旁边盯着,出问题得自己修自己扛。Shell脚本就是工控系统的"瑞士军刀"——挂磁盘、管日志、喂狗、保活,一个脚本搞定一个活。

一、Shell脚本在工控中的重要性

工控设备部署在现场,无人值守。U盘插上去要自动挂载,日志满了要自动归档,程序崩了要自动重启,系统卡死要看门狗强制恢复——这些活全靠Shell脚本干。

Shell脚本的优势:无需编译、直接运行、依赖极少。工控板资源有限,装Python解释器可能都嫌重,但busybox自带ash/sh,任何Linux板子都能跑Shell。

二、脚本基础语法速查

写工控脚本不需要精通Shell所有特性,掌握以下核心语法足矣:

2.1 变量与条件

#!/bin/bash# 变量赋值(等号两边不能有空格)DEVICE_PORT="/dev/ttyS0"BAUD_RATE=115200# 条件判断if[-e"$DEVICE_PORT"];thenecho"串口设备存在"elseecho"串口设备不存在"exit1fi# 数值比较if["$BAUD_RATE"-gt9600];thenecho"高速串口"fi# 字符串比较if["$MODE"="debug"];thenecho"调试模式"fi

2.2 循环与函数

# for循环遍历forportin/dev/ttyS{0..3};doecho"检查端口:$port"done# while循环count=0while[$count-lt10];doecho"计数:$count"count=$((count+1))done# 函数定义check_process(){localname=$1ifpgrep-x"$name">/dev/null;thenreturn0# 存活elsereturn1# 不存在fi}

2.3 关键注意事项

  • 变量引用必须加双引号:"$VAR",防止空值导致语法错误
  • 脚本头部加set -e:遇到错误立即退出,不让脚本带着错误继续跑
  • 比较用[ ]时,运算符和值之间必须有空格

三、实战脚本1:U盘/SD卡自动挂载

工控设备经常需要从U盘或SD卡读取配置文件、更新程序。手动挂载不现实,脚本自动检测并挂载。

#!/bin/bash# auto_mount.sh - U盘/SD卡自动挂载脚本set-eMOUNT_POINT="/mnt/usb"LOG_FILE="/var/log/auto_mount.log"log_msg(){echo"[$(date'+%Y-%m-%d %H:%M:%S')]$1">>"$LOG_FILE"}# 检测可移动存储设备find_usb_device(){fordevin/dev/sd{a,b,c}{1,2,3};doif[-b"$dev"];then# 检查是否已在挂载if!mountpoint-q"$MOUNT_POINT";thenecho"$dev"return0fifidonereturn1}# 挂载设备mount_device(){localdev=$1mkdir-p"$MOUNT_POINT"# 尝试挂载,支持常见文件系统ifmount-tvfat,ext4,ntfs-3g"$dev""$MOUNT_POINT"2>/dev/null;thenlog_msg"挂载成功:$dev->$MOUNT_POINT"return0elselog_msg"挂载失败:$dev"return1fi}# 安全卸载umount_device(){ifmountpoint-q"$MOUNT_POINT";thensync# 先刷新缓冲区umount"$MOUNT_POINT"log_msg"卸载完成:$MOUNT_POINT"fi}# 主逻辑DEVICE=$(find_usb_device)if[-n"$DEVICE"];thenmount_device"$DEVICE"elselog_msg"未检测到可挂载设备"fi

配合udev规则可实现真正的"插上即挂载":

# /etc/udev/rules.d/85-usb-mount.rulesACTION=="add",KERNEL=="sd[a-z][1-9]",RUN+="/usr/local/bin/auto_mount.sh"ACTION=="remove",KERNEL=="sd[a-z][1-9]",RUN+="/usr/local/bin/auto_umount.sh"

四、实战脚本2:日志归档脚本

工控程序24小时运行,日志文件持续增长,磁盘迟早撑爆。归档脚本按日期分割、压缩旧日志、自动清理过期文件。

#!/bin/bash# log_archive.sh - 日志归档与自动清理脚本set-eLOG_DIR="/var/log/app"ARCHIVE_DIR="/var/log/app/archive"MAX_ARCHIVE_DAYS=30# 保留30天归档MAX_LOG_SIZE_MB=100# 单个日志文件超过100MB就归档mkdir-p"$ARCHIVE_DIR"# 获取当前日期标签DATE_TAG=$(date'+%Y%m%d')# 扫描日志目录,归档大文件forlog_filein"$LOG_DIR"/*.log;do[-f"$log_file"]||continue# 检查文件大小(KB为单位)file_size_kb=$(du-k"$log_file"|cut-f1)file_size_mb=$((file_size_kb/1024))if[$file_size_mb-ge$MAX_LOG_SIZE_MB];then# 归档:拷贝+压缩+清空原文件archive_name="$(basename"$log_file".log)_${DATE_TAG}.log.gz"cp"$log_file""${ARCHIVE_DIR}/${DATE_TAG}_tmp"gzip-c"${ARCHIVE_DIR}/${DATE_TAG}_tmp">"${ARCHIVE_DIR}/${archive_name}"rm"${ARCHIVE_DIR}/${DATE_TAG}_tmp"# 清空原日志文件(不是删除,进程还在写)truncate-s0"$log_file"2>/dev/null||\>"$log_file"# truncate不可用时用重定向清空echo"[$(date)] 归档完成:$log_file(${file_size_mb}MB)"fidone# 清理过期归档find"$ARCHIVE_DIR"-name"*.log.gz"-mtime+$MAX_ARCHIVE_DAYS-deleteecho"[$(date)] 过期归档清理完成(>${MAX_ARCHIVE_DAYS}天)"

关键细节:用truncate或重定向清空日志而不是删除文件,因为进程仍然持有文件描述符——删了文件进程还在往"幽灵文件"里写,磁盘空间照涨不误。

五、实战脚本3:看门狗喂狗脚本

看门狗是工控系统的最后防线——软件卡死时,看门狗超时触发硬件复位,强制重启系统。喂狗就是告诉看门狗"我还活着"。

#!/bin/bash# watchdog_feed.sh - 看门狗喂狗脚本set-eWDOG_DEVICE="/dev/watchdog"FEED_INTERVAL=10# 每10秒喂一次,看门狗超时通常设30秒MAX_FEED_RETRIES=3# 检查看门狗设备是否存在if[!-e"$WDOG_DEVICE"];thenecho"看门狗设备不存在:$WDOG_DEVICE"exit1fi# 打开看门狗设备(写入任意字符即喂狗)# 注意:一旦打开,必须持续喂狗,否则超时系统复位exec3<>"$WDOG_DEVICE"echo"看门狗喂狗启动,间隔:${FEED_INTERVAL}秒"feed_count=0whiletrue;do# 写入喂狗字符forretryin$(seq1$MAX_FEED_RETRIES);doifecho"1">&3;thenfeed_count=$((feed_count+1))breakelseecho"喂狗失败,重试$retry/$MAX_FEED_RETRIES"sleep1fidone# 额外检查:关键进程是否存活if!pgrep-x"main_app">/dev/null;thenecho"关键进程异常!停止喂狗,等待看门狗复位系统"exec3>&-# 关闭看门狗,停止喂狗,触发超时复位exit1fisleep"$FEED_INTERVAL"done

这段脚本有两个核心机制:

  1. 正常喂狗:每10秒写一次/dev/watchdog,告知硬件"系统正常运行"
  2. 主动停喂:检测到关键进程崩溃时,主动关闭看门狗文件描述符,不再喂狗,让看门狗超时触发硬件复位

这不是简单的定时写文件,而是把进程健康检查和系统复位联动起来——软件自己发现问题时主动触发重启,比等看门狗被动超时更快更可控。

六、实战脚本4:程序守护脚本

工控程序崩溃是常态——内存泄漏、通信超时、硬件异常都可能导致进程退出。守护脚本的任务是:检测到进程不在,立即重启

#!/bin/bash# process_guard.sh - 程序守护脚本set-uAPP_NAME="data_collector"APP_CMD="/opt/app/data_collector --config /etc/app/config.ini"APP_DIR="/opt/app"CHECK_INTERVAL=5RESTART_DELAY=3MAX_RESTART_COUNT=10# 一小时内最多重启10次,防止无限重启循环RESTART_WINDOW=3600# 重启计数窗口:1小时restart_count=0window_start=$(date+%s)log_msg(){logger-t"guard[$APP_NAME]""$1"}whiletrue;doifpgrep-x"$APP_NAME">/dev/null;then# 进程存活,重置重启计数窗口restart_count=0window_start=$(date+%s)sleep"$CHECK_INTERVAL"continuefi# 进程不存在now=$(date+%s)elapsed=$((now-window_start))# 重置窗口计数if[$elapsed-ge$RESTART_WINDOW];thenrestart_count=0window_start=$nowfi# 检查重启次数限制restart_count=$((restart_count+1))if[$restart_count-ge$MAX_RESTART_COUNT];thenlog_msg"重启次数超限(${MAX_RESTART_COUNT}次/${RESTART_WINDOW}秒),停止守护"# 可选:触发看门狗或告警通知exit1filog_msg"进程$APP_NAME不存在,第${restart_count}次重启"# 重启进程cd"$APP_DIR"nohup$APP_CMD>>/var/log/app/guard.log2>&1&sleep"$RESTART_DELAY"done

这个脚本有防无限重启机制:1小时内重启超过10次就停止守护。连续崩溃说明问题不是偶发的,继续重启只会反复日志刷屏,不如停下来报警让运维介入。

七、Shell脚本调试技巧

7.1 bash -x 调试模式

# 运行脚本时开启调试,每行执行前都会打印bash-x/usr/local/bin/auto_mount.sh# 输出类似:# + MOUNT_POINT=/mnt/usb# + find_usb_device# + for dev in /dev/sda1 /dev/sda2 /dev/sdb1# + [ -b /dev/sda1 ]

7.2 set选项组合

#!/bin/bashset-e# 遇到错误立即退出set-u# 引用未定义变量时报错(防止$VAR空值导致意外)set-opipefail# 管道中任一命令失败,整条管道返回失败

工控脚本建议加上这三行,让脚本在错误时立即停止而不是带着问题继续跑——继续跑往往比停下来后果更严重。

八、crontab定时执行配置

有些脚本不需要常驻运行,定时执行即可:

# 编辑crontabcrontab-e# 每天凌晨2点执行日志归档02* * * /usr/local/bin/log_archive.sh# 每5分钟检查U盘挂载*/5 * * * * /usr/local/bin/auto_mount.sh# 每小时检查磁盘空间,超过90%报警0* * * * /usr/local/bin/disk_check.sh# crontab时间格式:分 时 日 月 周# * 表示任意值# */5 表示每5分钟# 0 2 * * * 表示每天2:00

Shell脚本在工控里不是配角,是基础设施。挂载、归档、喂狗、守护——四个脚本覆盖了工控设备最核心的运维自动化需求。写好这些脚本,设备才能在无人现场稳稳运行。