Docker日志多进程管道异常:sed无法接收egrep输出
问题原因与解决方法
核心问题是管道进程的缓冲机制:
- 当
egrep的输入来自管道(而非终端)时,默认会启用全缓冲——也就是攒够一定大小的缓冲区(通常是4KB)才会把数据输出到下一个管道。而docker logs的输出要么是逐行缓慢产生,要么单条日志量太小,根本填不满egrep的缓冲区,导致sed一直拿不到输入,自然没有输出。 - 用
echo测试时,因为echo一次性输出所有内容,直接填满了egrep的缓冲区,所以能立刻输出给sed,看起来一切正常。
解决办法
1. 给egrep启用行缓冲
给egrep加上--line-buffered参数,强制它每处理完一行就立刻输出:
docker logs 87b7826c2828 2>&1 | egrep --line-buffered -ai "EventLogger" | sed "s/EventLogger/Transform/"
(GNU和BSD版本的grep/egrep都支持--line-buffered参数,Linux和macOS环境通用)
2. 用stdbuf强制修改缓冲行为
如果遇到egrep不支持--line-buffered的极端情况,可以用stdbuf命令强制设置行缓冲:
docker logs 87b7826c2828 2>&1 | stdbuf -oL egrep -ai "EventLogger" | sed "s/EventLogger/Transform/"
-oL表示给标准输出设置行缓冲。
额外提示
如果使用docker logs -f实时跟踪日志,这个缓冲问题会更明显,必须加行缓冲参数才能让sed实时拿到输出。
内容的提问来源于stack exchange,提问作者donnie
相关产品推荐
相关产品推荐

