将程序输出重定向到旋转文件

8
我正在尝试将一个持续运行的程序的输出重定向到一个名为error_log的文件中。我的命令如下,其中myprogram.sh持续运行并生成数据并写入/var/log/httpd/error_logmyprogram.sh >> /var/log/httpd/error_log 现在我正在使用logrotate按小时旋转此文件。我在logrotate中使用create命令来重命名原始文件并创建新文件。 logrotate配置如下:
/var/log/httpd/error_log {
# copytruncate
 create
 rotate 4
 dateext
 missingok
 ifempty
 .
 .
 .
}

但是在这里重定向失败了。我想要的是,无论 error_log 文件是否被 logrotate 旋转,myprogram.sh 都能将数据写入到该文件中,显然是写入到新生成的 error_log 文件。
您有什么办法可以使重定向基于文件名而不是描述符工作吗?
或者,还有其他用 bash 解决的方法吗?

我不明白问题。当进行输出重定向时,它使用文件名而不是描述符。你可以展示一下你的脚本吗? - Barmar
是的,您能否展示您使用的整个“logrotate”命令? - Jamil Said
1
为什么你不使用copytruncate,这样我的程序脚本myprogram.sh就可以继续写入(追加)到之前的日志文件中。这样你就不会遇到创建问题(就像mv操作)。 - V. Michel
1个回答

7

如果我理解你的问题,一种解决方案(不需要修改 myprogram.sh)可能是:

$ myprogram.sh | while true; do head -10 >> /var/log/httpd/error_log; done

解释:

  • myprogram.sh 输出到标准输出流
  • 我们通过管道符 | 把输出重定向到 while 命令
  • while true 是一个无限循环,即使 myprogram.sh 结束也不会停止,这应该会中断管道。
  • 在每个循环中,会调用 head 命令将从管道读取的前10行附加到当前的 /var/log/httpd/error_log 文件末尾(由于 logrotate 的原因,可能与上一个循环所写入的文件不同)。

(您可以更改每个循环中要写入的行数)

另一种方法是:

$ myprogram.sh | while read line; do echo "$line" >> /var/log/httpd/error_log; done
  • 这个跟第一个非常相似,但是当 myprogram.sh 结束或关闭它的 stdout 时,它会结束循环。
  • 它逐行处理而不是分组处理。

1
这种方法会有明显的减速吗?听说读取速度非常慢? - StevenWernerCS
2
这将取决于您的需求。假设myprogram.sh每秒向stdout写入几MB,那么我发布的任何一种替代方案都不够快,管道将被阻塞(管道的最大容量约为~64KB,具体取决于系统),但如果程序每秒只写入几行(通常是日志),那么两种替代方案都应该能胜任,并且您可能不会感到它们之间有任何明显的差异。 - Wilfredo Pomier

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接