Apache使用tee日志到持久化文件与Docker stdout时重复输出问题
问题描述
尝试通过tee工具将Apache错误日志同时输出到两个位置:持久化存储文件和Docker标准输出(stdout),VirtualHost配置中的错误日志行如下:
ErrorLog "|/usr/bin/tee -a /var/log/apache/error.log /proc/1/fd/1"
实际运行发现,错误信息在/proc/1/fd/1(即docker logs显示的内容)中重复输出两次,但仅在/var/log/apache/error.log中记录一次。
在命令行单独测试tee时行为正常:
echo 123 | /usr/bin/tee -a /tmp/test /proc/1/fd/1
该命令能将内容各输出一次到文件和标准输出,无重复。
原因分析
核心问题出在Apache的管道日志机制与Docker日志收集的交互上:
- 当Apache配置
ErrorLog "|command"时,会启动子进程执行指定命令,并将日志内容写入该子进程的标准输入(stdin)。 tee读取stdin内容后,会将其写入目标文件和自身的标准输出(stdout)。此时tee的stdout默认关联到Apache父进程的标准错误(stderr)。- 在Docker环境中,容器主进程(pid 1)的stdout和stderr都会被
docker logs捕获收集。因此,tee直接写入的/proc/1/fd/1会被收集一次,而tee输出到Apache stderr的内容又会被Apache转发到容器的stderr,再次被docker logs收集,最终导致重复输出。
而命令行测试时,tee的stdout直接输出到终端,没有额外进程将其转发到其他日志收集通道,因此不会出现重复。
解决方案
修改ErrorLog配置,将tee自身的stdout重定向到/dev/null,避免Apache捕获并转发这部分内容:
ErrorLog "|/usr/bin/tee -a /var/log/apache/error.log /proc/1/fd/1 > /dev/null"
这样tee仅将日志内容写入指定文件和Docker stdout,自身的stdout被丢弃,不会产生额外的重复输出。
内容的提问来源于stack exchange,提问作者R.P
相关产品推荐
相关产品推荐

