将未命名的管道输出重定向到 c 中的日志文件
redirect unnamed pipe output to log file in c
我想将未命名管道的输出重定向到用 c 语言打开的日志文件,但我似乎做不到,我的代码如下所示:
close(fildes[1]);
FILE * file = fopen(logfile, "w");
int fd = fileno(file);
if (fd == -1) {
bail_out(EXIT_FAILURE, strerror(errno));
}
/* if (dup2(fd, fildes[0]) == -1) {
bail_out(EXIT_FAILURE, strerror(errno));
} */
/* for testing purposes */
char reading_buf[3];
while(read(fildes[0], reading_buf, 3) > 0) {
write(fd, reading_buf, 1);
}
(void)wait(&status);
close(fildes[0]);
break;
管道被填满,我已经用底部的 while 循环测试过了。但是当我注释掉 dup2 调用时,没有任何内容被重定向到该文件。我想我不完全理解 dup2 和管道。
另外:如果我 dup2 管道的读取端然后关闭原始 fildes[0],管道会关闭吗?或者它只是被关闭的 FD。也不完全应该这样..
要将输出从管道重定向到文件,需要有人从管道的读取端读取并写入文件的文件描述符。这不能仅通过复制文件描述符来完成。
例如,假设你有一个管道
int filedes[2];
pipe (filedes);
和一个文件
FILE *logfile = fopen (logfile_path, "w");
int logfd = fileno (logfile);
您可以使用 cat
命令启动子进程来进行重定向
int child = fork ();
if (child == 0) {
// close the write end of the pipe
close (filedes[1]);
// make STDOUT point to the log file
dup2 (logfd, STDOUT_FILENO);
// make STDIN point to the read end of the pipe
dup2 (filedes[0], STDIN_FILENO);
// launch cat
execlp ("cat", "cat", (char*) NULL);
// in case of error
exit (1);
}
现在,无论写入父级管道的写入端,都将由执行 cat 的子级读取并写入文件。
// close the read end of the pipe, it's not needed in the parent
close (filedes[0]);
// write something
const char *msg = "Hello World!\n";
write (filedes[1], msg, strlen (msg));
// close the write end of the pipe, this will make the child read EOF
close (filedes[1]);
别忘了收集僵尸
wait (&status);
并关闭文件
fclose (logfile);
关于你的最后一个问题,当一个文件描述符被欺骗时,会有两个指向同一个底层打开文件。因此,当其中一个关闭时,文件保持打开状态,因为它可以通过其他描述符访问。
这在 close
手册页中有解释:
If fd is the last file descriptor referring to the underlying open file
description (see open(2)), the resources associated with the open file
description are freed;
我想将未命名管道的输出重定向到用 c 语言打开的日志文件,但我似乎做不到,我的代码如下所示:
close(fildes[1]);
FILE * file = fopen(logfile, "w");
int fd = fileno(file);
if (fd == -1) {
bail_out(EXIT_FAILURE, strerror(errno));
}
/* if (dup2(fd, fildes[0]) == -1) {
bail_out(EXIT_FAILURE, strerror(errno));
} */
/* for testing purposes */
char reading_buf[3];
while(read(fildes[0], reading_buf, 3) > 0) {
write(fd, reading_buf, 1);
}
(void)wait(&status);
close(fildes[0]);
break;
管道被填满,我已经用底部的 while 循环测试过了。但是当我注释掉 dup2 调用时,没有任何内容被重定向到该文件。我想我不完全理解 dup2 和管道。
另外:如果我 dup2 管道的读取端然后关闭原始 fildes[0],管道会关闭吗?或者它只是被关闭的 FD。也不完全应该这样..
要将输出从管道重定向到文件,需要有人从管道的读取端读取并写入文件的文件描述符。这不能仅通过复制文件描述符来完成。
例如,假设你有一个管道
int filedes[2];
pipe (filedes);
和一个文件
FILE *logfile = fopen (logfile_path, "w");
int logfd = fileno (logfile);
您可以使用 cat
命令启动子进程来进行重定向
int child = fork ();
if (child == 0) {
// close the write end of the pipe
close (filedes[1]);
// make STDOUT point to the log file
dup2 (logfd, STDOUT_FILENO);
// make STDIN point to the read end of the pipe
dup2 (filedes[0], STDIN_FILENO);
// launch cat
execlp ("cat", "cat", (char*) NULL);
// in case of error
exit (1);
}
现在,无论写入父级管道的写入端,都将由执行 cat 的子级读取并写入文件。
// close the read end of the pipe, it's not needed in the parent
close (filedes[0]);
// write something
const char *msg = "Hello World!\n";
write (filedes[1], msg, strlen (msg));
// close the write end of the pipe, this will make the child read EOF
close (filedes[1]);
别忘了收集僵尸
wait (&status);
并关闭文件
fclose (logfile);
关于你的最后一个问题,当一个文件描述符被欺骗时,会有两个指向同一个底层打开文件。因此,当其中一个关闭时,文件保持打开状态,因为它可以通过其他描述符访问。
这在 close
手册页中有解释:
If fd is the last file descriptor referring to the underlying open file description (see open(2)), the resources associated with the open file description are freed;