通过 FIFO 记录,然后重定向到文件?

通过 FIFO 记录,然后重定向到文件?

我有一个必须记录每个事务的应用程序。每个日志消息都会被刷新,因为我们需要记录导致崩溃的事件。我和我的同事都很好奇如何实现缓冲的性能效果,同时保证日志消息已经离开进程。

我们的想法是:

  • 创建一个应用程序可以写入的 FIFO,并且
  • 通过将该 FIFO 的内容重定向到常规文件cat

也就是说,通常情况下是:

app --logfile logfile.txt

就是现在:

mkfifo logfifo
cat logfifo &> logfile.txt &
app --logfile logfifo

这种方法有什么缺陷吗?我们测试时它是起作用的,但我们希望绝对确保即使原始应用程序崩溃,消息也能找到重定向文件。

(我们没有该应用程序的源代码,因此编程解决方案是不可能的。此外,该应用程序不会写入stdout,因此直接通过管道传输到不同的命令是不可能的。所以这syslog是不可能的。)


更新:我已添加悬赏。被接受的答案将不是原因loggerlogger简单不是我问的是什么。正如最初的问题所述,我只是在寻找使用 FIFO 的陷阱。

答案1

请注意,在编程中,写入的数量可能超过读出的数量,因此通常需要使用 fifo。

因此,fifo 不会像您预期的那样完全顺利地工作,但会解决您的主要问题,同时引入另一个问题。

有三个可能的警告。

  1. 如果在初始化时没有任何东西读取另一端,那么对 fifo 的写入将被无限期阻止。
  2. fifo 具有固定的 64K 宽度,如果缓冲区在该点处已被填满,则进一步的写入将被阻止,直到读取器赶上为止。
  3. 如果读取器死亡或退出,管道写入器将通过 SIGPIPE 被杀死。

这意味着您的问题(在非缓冲写入上模拟缓冲 I/O)将得到解决。这是因为 FIFO 上的新“限制”实际上将成为任何实用程序将管道中的内容写入磁盘(可能为缓冲 I/O)的速度。

尽管如此,写入器还是依赖于日志读取器才能运行。如果读取器突然停止读取,写入器将阻塞。如果读取器突然退出(假设目标磁盘空间不足),写入器将发出 SIGPIPE 并可能退出。

另一点需要提到的是,如果服务器崩溃并且内核停止响应,您可能会丢失该缓冲区中的最多 64k 的数据。

解决此问题的另一种方法是将日志写入 tmpfs(Linux 上的 /dev/shm),并将输出尾随到固定磁盘位置。这样做对内存分配的限制较少(不是 64K,通常是 2G!)但如果写入器没有动态方式重新打开日志文件(您必须定期从 tmpfs 中清除日志),则可能对您不起作用。如果服务器使用此方法时出现崩溃,您可能会丢失更多数据。

答案2

mkfifo logfifo
cat logfifo &> logfile.txt &
app --logfile logfifo

cat logfifo如果您的进程终止了,有人意外地终止了它,或者有人意外地将它指向错误的位置,会发生什么?

我的经验是,它将app很快阻塞并挂起。我尝试过 Tomcat、Apache 和一些小型自制应用程序,并遇到了同样的问题。我从未深入调查,因为logger简单的 I/O 重定向就可以满足我的要求。我通常不需要日志记录的完整性,而这正是您所追求的。正如您所说,您不需要记录器。

关于这个问题有一些讨论Linux 非阻塞 fifo(按需记录)

答案3

该应用程序会限制您的选择,但您测试过的功能将会起作用。

我们用 varnish 和 varnishncsa 做了类似的事情,以便将日志发送到对我们有用的地方。我们有一个 fifo,只需使用 syslog-ng 从中读取并将其发送到我们需要的地方。我们处理了大约 50GB 的数据,到目前为止,这种方法还没有遇到任何问题

答案4

你写:

此外,该应用程序不会写入stdout...

您是否尝试过登录“文件” /dev/stdout?这可能使您能够执行以下操作:

app --logfile /dev/stdout | logger -t app

相关内容