Linux环境CAN总线消息FIFO日志记录异常及优化方案咨询
问题原因解析
你遇到的核心问题是:当用candump -L can0 > test.log直接写入文件时,candump是基于文件的inode持续写入的。而sed -i '1d' test.log会创建新的临时文件处理内容,随后删除原文件并将临时文件重命名为test.log——这会导致原文件的inode被丢弃,但candump还在往旧inode写入,所以你看到的新test.log不再增长,实际数据写到了一个无主的隐藏文件里。
解决方案
1. 管道实时过滤(最简单的固定行数方案)
直接让candump的输出通过管道传给tail,只保留最近N行,日志文件始终是最新的记录,且写入不会中断:
# 保留最近1000条记录,可自行修改数字 candump -L can0 | tail -n 1000 > can_fifo.log
需要查看或复制最近记录时,直接读取can_fifo.log即可,tail会自动过滤掉超出行数的旧记录。
2. 后台脚本定时截断(保持原inode)
先启动candump后台记录:
nohup candump -L can0 >> can.log 2>&1 &
然后创建维护脚本maintain_can_log.sh,定时检查日志行数,超过阈值时用tail截取最后N行覆盖原文件(不替换文件,inode不变):
#!/bin/bash LOG_FILE="can.log" MAX_LINES=1000 # 自定义最大行数 while true; do current_lines=$(wc -l < "$LOG_FILE") if [ "$current_lines" -gt "$MAX_LINES" ]; then tail -n "$MAX_LINES" "$LOG_FILE" > "$LOG_FILE.tmp" cat "$LOG_FILE.tmp" > "$LOG_FILE" rm "$LOG_FILE.tmp" fi sleep 5 # 每5秒检查一次,可调整间隔 done
给脚本加执行权限并后台运行:
chmod +x maintain_can_log.sh nohup ./maintain_can_log.sh 2>&1 &
这种方式下candump始终往同一个inode写入,截断操作不会中断记录。
3. 用logrotate按大小管理(适合生产环境)
Linux自带的logrotate工具支持copytruncate选项——复制文件内容后截断原文件,保持inode不变,不会中断写入:
- 创建logrotate配置文件
/etc/logrotate.d/can_log:
/var/log/can.log { size 100k # 文件超过100k时触发截断 rotate 0 # 不保留历史日志 copytruncate # 核心:复制后截断原文件 missingok # 文件不存在时不报错 notifempty # 文件为空时不处理 }
- 启动
candump后台记录:
nohup candump -L can0 >> /var/log/can.log 2>&1 &
- 手动测试(或等待系统自动执行):
logrotate -f /etc/logrotate.d/can_log
4. 内存缓冲区方案(高效低IO)
用内存数组存储最近N条记录,定时写入磁盘,减少频繁磁盘操作:
#!/bin/bash MAX_LINES=1000 LOG_FILE="can_fifo.log" declare -a buffer # 内存缓冲区数组 candump -L can0 | while read -r line; do buffer+=("$line") # 超出最大行数时删除最旧记录 if [ "${#buffer[@]}" -gt "$MAX_LINES" ]; then buffer=("${buffer[@]:1}") fi # 每10条记录写入一次磁盘,可调整频率 if [ $(( ${#buffer[@]} % 10 )) -eq 0 ]; then printf "%s\n" "${buffer[@]}" > "$LOG_FILE" fi done
内容的提问来源于stack exchange,提问作者Jefferson Hui
相关产品推荐
相关产品推荐

