Linux безблокировав FIFO (по каналам спроса)

Мне нравится регистрировать программы вывода «по запросу». Например. Выход зарегистрирован в терминал, но другой процесс может подключить к текущему выходу в любое время.

Классический способ будет:

myprogram 2>&1 | tee /tmp/mylog

и по требованию

tail /tmp/mylog

, однако, это создало бы постоянно растущий файл журнала, даже если он не используется, пока привод не выполнит не выходить из места. Итак, моя попытка была:

mkfifo /tmp/mylog
myprogram 2>&1 | tee /tmp/mylog

и по требованию

cat /tmp/mylog

Теперь я могу прочитать / TMP / MyLog в любое время. Тем не менее, любой вывод блокирует программу до тех пор, пока / tmp / mylog не прочитаны. Мне нравится ФИФО, чтобы промыть любые входящие данные, не читающие обратно. Как это сделать?

32
задан dronus 9 September 2011 в 10:45
поделиться

1 ответ

Следовать в ноге Fabraxias ступает, я собираюсь совместно использовать свою маленькую модификацию кода racic. В одном из моих вариантов использования я должен был подавить записи к STDOUT, таким образом, я добавил другой параметр: swallow_stdout. Если это будет не 0, то произведенный к STDOUT будет выключен.

, Так как я не C кодер, я добавил комментарии при чтении кода, возможно, они полезны для других.

/* ftee - clone stdin to stdout and to a named pipe 
(c) racic@stackoverflow
WTFPL Licence */

// gcc /tmp/ftee.c -o /usr/local/bin/ftee

#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;        // read & write file descriptors
    struct stat status;         // read file descriptor status
    char *fifonam;              // name of the pipe
    int swallow_stdout;         // 0 = write to STDOUT
    char buffer[BUFSIZ];        // read/write buffer
    ssize_t bytes;              // bytes read/written

    signal(SIGPIPE, SIG_IGN);   

    if(3!=argc)
    {
        printf("Usage:\n someprog 2>&1 | %s [FIFO] [swallow_stdout] \n" 
            "FIFO           - path to a named pipe (created beforehand with mkfifo), required argument\n"
            "swallow_stdout - 0 = output to PIPE and STDOUT, 1 = output to PIPE only, required argument\n", argv[0]);
        exit(EXIT_FAILURE);
    }
    fifonam = argv[1];
    swallow_stdout = atoi(argv[2]);

    readfd = open(fifonam, O_RDONLY | O_NONBLOCK);  // open read file descriptor in non-blocking mode

    if(-1==readfd)  // read descriptor error!
    {
        perror("ftee: readfd: open()");
        exit(EXIT_FAILURE);
    }

    if(-1==fstat(readfd, &status)) // read descriptor status error! (?)
    {
        perror("ftee: fstat");
        close(readfd);
        exit(EXIT_FAILURE);
    }

    if(!S_ISFIFO(status.st_mode)) // read descriptor is not a FIFO error!
    {
        printf("ftee: %s in not a fifo!\n", fifonam);
        close(readfd);
        exit(EXIT_FAILURE);
    }

    writefd = open(fifonam, O_WRONLY | O_NONBLOCK); // open write file descriptor non-blocking
    if(-1==writefd) // write file descriptor error!
    {
        perror("ftee: writefd: open()");
        close(readfd);
        exit(EXIT_FAILURE);
    }

    close(readfd); // reading complete, close read file descriptor

    while(1) // infinite loop
    {
        bytes = read(STDIN_FILENO, buffer, sizeof(buffer)); // read STDIN into buffer
        if (bytes < 0 && errno == EINTR)
            continue;   // skip over errors

        if (bytes <= 0) 
            break; // no more data coming in or uncaught error, let's quit since we can't write anything

        if (swallow_stdout == 0)
            bytes = write(STDOUT_FILENO, buffer, bytes); // write buffer to STDOUT
        if(-1==bytes) // write error!
            perror("ftee: writing to stdout");
        bytes = write(writefd, buffer, bytes); // write a copy of the buffer to the write file descriptor
        if(-1==bytes);// ignore errors
    }
    close(writefd); // close write file descriptor
    return(0); // return exit code 0
}
0
ответ дан 27 November 2019 в 20:02
поделиться
Другие вопросы по тегам:

Похожие вопросы: