You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

监控dmesg匹配首条目标日志时sed/grep未及时触发问题

问题根因

阻塞问题和sed、grep的匹配逻辑无关,核心是管道场景下的默认块缓冲机制导致的:

  • dmesg -w是持续监听内核环形缓冲区的实时输出模式,当它的输出目标不是交互式终端(也就是通过管道传给sed/grep时),会默认启用大小通常为4KB的块缓冲——不会每生成一行日志就立刻写入管道,而是攒满整块缓冲区才会一次性把数据发给下游命令。
  • 你观察到的「第二条匹配日志才触发后续逻辑」是典型的缓冲未刷新表现:第一条包含protocol的日志生成后,数据一直滞留在dmesg的输出缓冲区里,sed/grep根本读不到这行内容;直到下一条任意日志写入,把缓冲区凑满触发刷新,下游命令才收到匹配内容、执行退出。如果第一条匹配日志之后一直没有新的内核日志输出,脚本就会永久阻塞。
  • 原脚本还有三个额外问题:一是两处eval完全没有必要,属于冗余写法还存在命令注入风险;二是下游sed/grep退出后,上游的dmesg -w进程不会立刻自动退出,会残留僵尸进程占用资源;三是sleep 1写在while判断位会导致脚本启动后先空等1秒才开始监听,存在日志漏报窗口。
修复方案

用stdbuf强制dmesg启用行缓冲,让每一行日志生成后立刻写入管道,同时给下游grep/sed也开启行缓冲避免二次阻塞,清理冗余逻辑和残留进程,修正后代码如下:

#!/bin/bash
# 提前一次性创建归档目录,无需每次循环重复执行
mkdir -p /home/user/dmesg/

while true; do
    # 强制dmesg行缓冲输出,grep匹配到第一行目标内容就立刻退出
    stdbuf -oL dmesg -w | grep -m 1 -q --line-buffered 'protocol'
    # 清理可能残留的dmesg监听进程,避免僵尸进程
    pkill -P $$ dmesg 2>/dev/null

    # 归档当前dmesg日志,文件名冒号替换为下划线,兼容各类文件系统
    dmesg -T > "/home/user/dmesg/dmesg-$(date +%d_%m_%Y-%H_%M).log"
    # 清空dmesg环形缓冲区
    dmesg -c >/dev/null
    # 强制终止目标进程
    pkill -x -9 programm

    # 完成一轮处理后等待1秒再开启下一轮监听,避免重复触发
    sleep 1
done
补充说明
  • 如果偏好sed实现匹配退出的逻辑,把管道行替换为以下写法即可,sed -u参数用于强制sed无缓冲:
    stdbuf -oL dmesg -w | sed -u '/protocol/Q'
    
  • 不建议在文件名中使用:字符,该字符在FAT/ExFAT等文件系统、部分备份工具、跨平台同步场景下会被判定为非法字符,替换为下划线通用性更强。

内容的提问来源于stack exchange,提问作者tilch

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 15:15:33