两个相似Linux脚本日志写入混乱问题求助
日志文件混入其他设备数据的排查与解决
问题根源
你的两个脚本共用了同一个硬编码的临时文件名temp,这是导致数据混乱的核心原因:
当两个不同周期(15分钟/30分钟)的脚本同时执行时,会触发竞争条件:
- 脚本A刚把新采集的数据+原有日志写入
temp文件 - 脚本B随即覆盖了这个
temp文件,写入自己的采集内容 - 最终其中一个脚本执行
mv temp $log时,会把属于另一个设备的数据错误写入目标日志
另外,脚本末尾的| sed -n '1,192p' $log完全无效:mv命令没有输出内容,sed没有输入源,且这个操作也没实现“保留最新192行日志”的预期逻辑。
修复方案
1. 为每个脚本使用唯一临时文件
抛弃硬编码的temp,改用与日志文件绑定的临时文件名,或者用mktemp生成安全的临时文件。以第一个脚本为例,修改日志写入部分:
# 生成与日志文件名关联的临时文件,避免冲突 tempfile="/scripts/temp_$(basename $log)" # 写入新行+原有日志的前191行(确保总日志行数为192) (echo "$line"; head -n 191 "$log") > "$tempfile" # 原子替换目标日志文件 mv "$tempfile" "$log"
第二个脚本同理,此时两个脚本的临时文件名会分别是temp_cellar.log和temp_gh.log,彻底避免互相覆盖。
2. 修复日志截断逻辑
上面的代码直接在写入临时文件时完成截断:新行+原有日志的前191行,刚好保留最新的192行日志,替代原来无效的sed操作。
额外优化建议
用jq替代cut解析JSON
当前用cut提取温度值的方式非常脆弱,一旦JSON结构有微小变化(比如新增带[的字段)就会解析失败。改用jq(需先安装:apt install jq):
# 可靠提取Data数组的第一个元素 celsius=$(echo "$json" | jq -r '.Data[0]')
脚本细节优化
- 用
$()替代反引号:now=$(date +%a,%m/%d/%Y@%I:%M%p),可读性更强且支持嵌套 - 给变量加双引号,避免空格等特殊字符导致的异常:比如
echo "$line"而非echo $line - 可以删除
touch "$log"的判断,head和echo写入时会自动创建不存在的文件
修复后的完整脚本示例(第一个脚本)
#!/bin/bash log="/scripts/cellar.log" now=$(date +%a,%m/%d/%Y@%I:%M%p) json=$(curl -m 3 --user *****:***** "http://192.168.1.146/monitorjson" --silent --stderr -) celsius=$(echo "$json" | jq -r '.Data[0]') temp=$(echo "scale=4; $celsius*1.8 + 32" | bc) line="$now : $temp" echo "$line" tempfile="/scripts/temp_$(basename $log)" (echo "$line"; head -n 191 "$log" 2>/dev/null) > "$tempfile" mv "$tempfile" "$log"
异常日志示例(混入其他设备数据):
Mon,11/28/2022@03:30AM : 44.96 Mon,11/28/2022@03:00AM : 44.96 Mon,11/28/2022@02:30AM : 44.96 Tue,11/29/2022@02:15AM : 60.62 Tue,11/29/2022@02:00AM : 60.98 Tue,11/29/2022@01:45AM : 60.98
内容的提问来源于stack exchange,提问作者John Styles
相关产品推荐
相关产品推荐

