Linux的非阻塞FIFO(按需记录) [英] Linux non-blocking fifo (on demand logging)

查看:333
本文介绍了Linux的非阻塞FIFO(按需记录)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我喜欢登录一个节目输出按需。例如。输出被记录到终端,但另一个方法可以在任何时候在电流输出钩。

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

它的行为类似于 T恤,但克隆的标准输入到标准输出和命名管道(目前的要求),而不会阻塞。这意味着,如果要记录这种方式,它可能发生,你会失去你的日志数据,但我想这是在您的方案可以接受。
关键是要阻止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:\n someprog 2>&1 | %s FIFO\n FIFO - path to a"
            " named pipe, required argument\n", 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!\n", 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

您可以快速运行例如验证:

You can quickly verify it by running e.g.:

$平www.google.com | ftee的/ tmp / mylog

$猫的/ tmp / mylog

另外请注意 - 这不是多路复用器。你只能有一次一个过程做 $猫的/ tmp / mylog

Also note - this is no multiplexer. You can only have one process doing $ cat /tmp/mylog at a time.

这篇关于Linux的非阻塞FIFO(按需记录)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆