Linux 非阻塞 fifo(按需日志记录) [英] Linux non-blocking fifo (on demand logging)
问题描述
我喜欢按需"记录程序输出.例如.输出记录到终端,但另一个进程可以随时挂接当前输出.
I like to log a programs output 'on demand'. Eg. the output is logged to the terminal, but another process can hook on the current output at any time.
经典的方法是:
myprogram 2>&1 | tee /tmp/mylog
和按需
tail /tmp/mylog
然而,即使在驱动器空间用完之前不使用,这也会创建一个不断增长的日志文件.所以我的尝试是:
However, this would create a ever growing log file even if not used until the drive runs out of space. So my attempt was:
mkfifo /tmp/mylog
myprogram 2>&1 | tee /tmp/mylog
和按需
cat /tmp/mylog
现在我可以随时阅读/tmp/mylog.但是,在读取/tmp/mylog 之前,任何输出都会阻止程序.我喜欢 fifo 刷新任何未读回的传入数据.怎么做?
Now I can read /tmp/mylog at any time. However, any output blocks the program until the /tmp/mylog is read. I like the fifo to flush any incoming data not read back. How to do that?
推荐答案
受到您问题的启发,我编写了一个简单的程序,可以让您做到这一点:
Inspired by your question I've written a simple program that will let you do this:
$ myprogram 2>&1 |ftee/tmp/mylog
它的行为与 tee
类似,但将 stdin 克隆到 stdout 和命名管道(目前需要)而不会阻塞.这意味着如果您想以这种方式记录日志,您可能会丢失日志数据,但我想这在您的场景中是可以接受的.诀窍是阻止 SIGPIPE
信号并忽略写入损坏的 fifo 时的错误.这个示例当然可以通过各种方式进行优化,但到目前为止,它做到了我猜是工作.
It behaves similarly to tee
but clones the stdin to stdout and to a named pipe (a requirement for now) without blocking. This means that if you want to log this way it may happen that you're gonna lose your log data, but I guess it's acceptable in your scenario.
The trick is to block SIGPIPE
signal and to ignore error on writing to a broken fifo. This sample may be optimized in various ways of course, but so far, it does the job I guess.
/* ftee - clone stdin to stdout and to a named pipe
(c) racic@stackoverflow
WTFPL Licence */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <signal.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
int readfd, writefd;
struct stat status;
char *fifonam;
char buffer[BUFSIZ];
ssize_t bytes;
signal(SIGPIPE, SIG_IGN);
if(2!=argc)
{
printf("Usage:
someprog 2>&1 | %s FIFO
FIFO - path to a"
" named pipe, required argument
", argv[0]);
exit(EXIT_FAILURE);
}
fifonam = argv[1];
readfd = open(fifonam, O_RDONLY | O_NONBLOCK);
if(-1==readfd)
{
perror("ftee: readfd: open()");
exit(EXIT_FAILURE);
}
if(-1==fstat(readfd, &status))
{
perror("ftee: fstat");
close(readfd);
exit(EXIT_FAILURE);
}
if(!S_ISFIFO(status.st_mode))
{
printf("ftee: %s in not a fifo!
", fifonam);
close(readfd);
exit(EXIT_FAILURE);
}
writefd = open(fifonam, O_WRONLY | O_NONBLOCK);
if(-1==writefd)
{
perror("ftee: writefd: open()");
close(readfd);
exit(EXIT_FAILURE);
}
close(readfd);
while(1)
{
bytes = read(STDIN_FILENO, buffer, sizeof(buffer));
if (bytes < 0 && errno == EINTR)
continue;
if (bytes <= 0)
break;
bytes = write(STDOUT_FILENO, buffer, bytes);
if(-1==bytes)
perror("ftee: writing to stdout");
bytes = write(writefd, buffer, bytes);
if(-1==bytes);//Ignoring the errors
}
close(writefd);
return(0);
}
你可以用这个标准命令编译它:
You can compile it with this standard command:
$ gcc ftee.c -o ftee
您可以通过运行例如:
$ ping www.google.com |ftee/tmp/mylog
$ cat/tmp/mylog
另请注意 - 这不是多路复用器.一次只能让一个进程执行 $ cat/tmp/mylog
.
Also note - this is no multiplexer. You can only have one process doing $ cat /tmp/mylog
at a time.
这篇关于Linux 非阻塞 fifo(按需日志记录)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!