Мне нравится регистрировать программы вывода «по запросу». Например. Выход зарегистрирован в терминал, но другой процесс может подключить к текущему выходу в любое время.
Классический способ будет:
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 не прочитаны. Мне нравится ФИФО, чтобы промыть любые входящие данные, не читающие обратно. Как это сделать?
Следовать в ноге 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
}