通过FIFOlogin,然后redirect到一个文件?

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

我们想到的是:

  • 做一个应用程序可以写入的FIFO,
  • 通过cat将该FIFO的内容redirect到一个常规文件。

也就是说,通常是这样的:

 app --logfile logfile.txt 

就是现在:

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

这种方法有什么困难吗? 它在我们testing的时候起作用,但是我们要确保即使原始应用程序崩溃,这些消息也会findredirect文件的path。

(我们没有应用程序的源代码,所以编程解决scheme是不可能的,而且应用程序也不会写入stdout ,所以直接连接到不同的命令是不可能的,所以syslog不是一个可能性。)


更新:我已经添加了一个赏金。 被接受的答案不会涉及logger ,简单的原因是logger 不是我所问的。 正如原来的问题所述,我只是在寻找使用FIFO的问题。

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

因为这样的先遣队不会像你所期望的那样完全顺畅地工作,但是在引入另外一个的时候会解决你的主要问题。

有三个可能的警告。

  1. 如果在初始化时没有读到另一端,那么写入FIFO将被无限期地阻塞。
  2. fifo的固定宽度为64K,如果缓冲区被这个点填满,进一步写入将被阻塞,直到读者已经赶上。
  3. 如果阅读器死亡或退出,pipe道写入器将被SIGPIPE杀死。

这将意味着你的问题(仿真非缓冲写入的缓冲I / O)将被解决。 这是因为FIFO上的新“限制”实际上将成为写入磁盘中的内容的任何实用程序的速度(据推测这将是缓冲I / O)。

尽pipe如此,作者依赖于你的日志阅读器的function。 如果读者突然停止阅读,作者将会阻止。 如果读者突然退出(可以说你的目标磁盘空间不足),那么作者将SIGPIPE并可能退出。

还有一点需要提醒的是,如果服务器发生混乱,内核停止响应,则可能会丢失该缓冲区中的64k数据。

解决这个问题的另一种方法是将日志写入tmpfs(在Linux上的/ dev / shm),并将输出结尾到一个固定的磁盘位置。 如果写者没有dynamic的方式来重新打开日志文件(你将不得不周期性地从tmpfs中清除日志),那么对内存分配的限制就会less一些(不是64K,通常是2G! 如果服务器在这个方法中发生混乱,那么可能会丢失更多的数据。

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

当你的cat logfifo进程死亡,意外杀死它,或者有人不小心把它指向错误的位置,会发生什么?

我的经验是, app将迅速阻止和挂起。 我已经用Tomcat,Apache和一些小型的自制应用程序尝试了这个,并遇到了同样的问题。 我从来没有调查过很远,因为logger或简单的I / Oredirect做了我想要的。 我通常不需要logging完整性,这是你正在努力追求的。 正如你所说,你不需要logging器。

在Linux非阻塞FIFO(按需日志logging)上有一些关于这个问题的讨论。

你的select是相当有限的应用程序,但你已经testing将工作。

我们在varnish和varnishncsa上做了类似于我们所用的获取日志。 我们有一个fifo,只是用syslog-ng从它读取,然后发送到我们需要的地方。 我们处理大约50GB,到目前为止还没有遇到这种方法的问题

环境是CentOS,应用程序写入文件…

而不是发送到一个普通的文件,我会发送输出到系统日志,并确保系统日志消息发送到中央服务器以及本地。

你应该可以像这样使用shell脚本:

 logger -p daemon.notice -t app < fifo 

你也可以从cattail -finput(到logger )到pipe道中:

 tail -f fifo | logger ... cat fifo | logger ... 

唯一的问题是,它不基于日志消息的重要性(一切都注意 ),但至less它被logging,并也离线发送到中央服务器。

configuration系统日志取决于您正在使用的服务器。 有rsyslogsyslog-ng (都非常有能力)。

编辑 :从海报获得更多的信息后修改。

你写:

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

你有没有尝试login到“文件” /dev/stdout ? 这可能使您能够执行如下操作:

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

没有必要写入FIFO,然后让另一个进程写入文件。 只要直接写入文件,一旦write()返回,它就在内核的手中; 如果应用程序崩溃,它仍会将其写入磁盘。