Linux下监控多minicom日志文件,触发脚本遇fswatch循环问题求助
监控多串口日志文件,仅在完整数据包写入时触发脚本
场景说明
- Linux系统运行4个minicom实例,分别读取4台设备的串口数据,日志保存到对应文本文件中
- 物理事件触发的数据包格式如下:
[timestamp] header [timestamp] data ... [timestamp] data [timestamp] footer [timestamp] header ...
核心需求
监控4个日志文件,仅当文件被修改且末尾出现footer行时,运行指定脚本
之前尝试遇到的问题
- 串口数据行速率约6~7毫秒/行,不希望每新增一行就触发通知,仅需每个完整数据包触发一次
- 每个数据包的行数(耗时)随机,无法通过固定
fswatch的latency参数实现单包单通知
失败的尝试方案
方案1:fswatch触发后检查最后一行
用fswatch监控文件,每次触发后执行tail -n 1 logfile对比footer,但无法解决频繁触发的问题
方案2:fswatch + 脚本检测
执行命令:
fswatch -0 logfile.log | xargs -0 -I {} script.sh
配套script.sh代码:
#!/bin/sh footer='packet end' newline=$(tail -n 1 $HOME/slave.log | grep "$footer") if [ "$newline" != "" ]; then echo "found" fi
问题:一旦日志末尾是footer行,fswatch会持续触发通知,导致脚本无限循环打印"found"
可行解决方案
核心思路
跟踪每个日志文件已处理的行号,每次监控触发时仅检查新增行,找到footer后更新行号,避免重复触发。
单文件监控脚本示例
#!/bin/bash LOG_FILE="$HOME/slave.log" LAST_LINE_FILE="$HOME/slave.log.lastline" FOOTER='packet end' TARGET_SCRIPT='/path/to/your/target/script.sh' # 初始化行号记录文件 if [ ! -f "$LAST_LINE_FILE" ]; then wc -l "$LOG_FILE" | awk '{print $1}' > "$LAST_LINE_FILE" fi while true; do # 监听文件修改事件 inotifywait -q -e modify "$LOG_FILE" # 获取当前总行数与已处理行号 current_lines=$(wc -l "$LOG_FILE" | awk '{print $1}') last_lines=$(cat "$LAST_LINE_FILE") # 检查新增行中是否包含footer if [ "$current_lines" -gt "$last_lines" ]; then tail -n $((current_lines - last_lines)) "$LOG_FILE" | grep -q "$FOOTER" if [ $? -eq 0 ]; then # 执行目标脚本 "$TARGET_SCRIPT" # 更新已处理行号 echo "$current_lines" > "$LAST_LINE_FILE" fi fi done
多文件扩展方案
将监控逻辑封装为函数,为4个日志文件分别启动后台监控进程:
#!/bin/bash monitor_log() { local LOG_FILE="$1" local LAST_LINE_FILE="${LOG_FILE}.lastline" local FOOTER="$2" local TARGET_SCRIPT="$3" # 初始化行号记录 if [ ! -f "$LAST_LINE_FILE" ]; then wc -l "$LOG_FILE" | awk '{print $1}' > "$LAST_LINE_FILE" fi while true; do inotifywait -q -e modify "$LOG_FILE" current_lines=$(wc -l "$LOG_FILE" | awk '{print $1}') last_lines=$(cat "$LAST_LINE_FILE") if [ "$current_lines" -gt "$last_lines" ]; then tail -n $((current_lines - last_lines)) "$LOG_FILE" | grep -q "$FOOTER" if [ $? -eq 0 ]; then "$TARGET_SCRIPT" "$LOG_FILE" # 可将日志路径传给目标脚本 echo "$current_lines" > "$LAST_LINE_FILE" fi fi done } # 启动4个后台监控进程 monitor_log "/path/to/log1.log" "packet end" "/path/to/target.sh" & monitor_log "/path/to/log2.log" "packet end" "/path/to/target.sh" & monitor_log "/path/to/log3.log" "packet end" "/path/to/target.sh" & monitor_log "/path/to/log4.log" "packet end" "/path/to/target.sh" & wait
方案优势
- 用
inotifywait精准监听文件修改,避免fswatch的重复触发问题 - 通过行号记录,仅处理新增内容,不会重复检测已处理过的footer
- 适配数据包行数随机的场景,只要新增行中出现footer就触发一次脚本
内容的提问来源于stack exchange,提问作者mehdi
相关产品推荐
相关产品推荐

