tail -f+sed+xargs组合命令挂起的原因及解决方法咨询
tail -f + sed + xargs 组合后无输出挂起的原因与解决方法
问题场景
有一个持续被追加内容的日志文件(示例文件为dummy_file.txt),内容如下:
Line 1a Line 2a Line 3a
需求是将文件每行中的单引号(')替换为双引号("),再将替换后的内容传递给xargs处理。单独执行以下两个命令均能正常工作:
tail -f dummy_file.txt | sed --expression="s/'/\"/g":实时将新增行的单引号替换为双引号tail -f dummy_file.txt | xargs -I {} echo "Hello {}":实时将新增行传递给echo并添加前缀Hello
但将两个命令组合后,程序出现挂起,无任何输出:
tail -f dummy_file.txt | sed --expression="s/'/\"/g" | xargs -I {} echo "Hello {}"
实际应用场景为:
tail -f /var/log/messages | sed --expression="s/'/"/g" | xargs -I {} echo "Hello {}" > new_file.sql
原因分析
- sed的缓冲机制:sed在管道环境中默认使用全缓冲模式,即会积累一定量的输出内容后才一次性发送到下一个管道,而非处理一行就输出一行。这导致下游的xargs始终无法接收到有效输入,处于等待状态。
- xargs的
-I选项行为:当使用-I指定替换字符串时,xargs会等待完整的输入行来执行替换操作。如果上游的sed没有实时输出行,xargs就会持续挂起等待。
解决方案
方法1:给sed启用无缓冲输出
使用sed的-u(或--unbuffered)选项,强制sed采用行缓冲模式,处理一行就输出一行:
tail -f dummy_file.txt | sed -u --expression="s/'/\"/g" | xargs -I {} echo "Hello {}"
方法2:用stdbuf调整缓冲策略
如果你的sed版本不支持-u选项,可以借助stdbuf命令强制sed将标准输出设置为行缓冲模式:
tail -f dummy_file.txt | stdbuf -oL sed --expression="s/'/\"/g" | xargs -I {} echo "Hello {}"
其中-oL表示将标准输出设置为行缓冲。
方法3:改用awk实现替换(可选)
awk默认采用行缓冲模式,同样可以完成单引号转双引号的需求,避免sed的缓冲问题:
tail -f dummy_file.txt | awk "gsub(/'/,\"\\\"\") {print}" | xargs -I {} echo "Hello {}"
内容的提问来源于stack exchange,提问作者Sergiu Velescu
相关产品推荐
相关产品推荐

