灵感来自于你的问题,我写了一个简单的程序,让你这样做:
$ myprogram 2>& 1 | ftee / tmp / mylog
它与T恤类似,但是将stdin标记为stdout和命名管道(现在的要求),而不会阻塞。这意味着如果您想以这种方式登录,可能会发生这种情况,您将会丢失日志数据,但我猜想您的方案是可以接受的。
诀窍是阻止SIGPIPE信号,并忽略写入破碎的fifo时的错误。当然这个样本可能会以各种不同的方式进行优化,但到目前为止,我完成了这项工作。
/* ftee - clone stdin to stdout and to a named pipe
(c) racic@stackoverflow
WTFPL Licence */
#include
#include
#include
#include
#include
#include
#include
#include
#include
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);
}
您可以使用此标准命令编译它:
$ gcc ftee.c -o ftee
您可以通过运行例如:
$ ping www.google.com | ftee / tmp / mylog
$ cat / tmp / mylog
还要注意 – 这不是多路复用器。一次只能有一个进程执行$ cat / tmp / mylog。