使用 dup2 重定向 stdout/stderr,然后重新声明
Redirect stdout/stderr using dup2, then resinstate later
背景:我们有一个嵌入式linux系统运行 Busybox(资源有限),我们有一个进程运行通常会吐在控制台上输出大量信息(通过 stdout / stderr),但我们希望 暂时 根据命令将其重定向到系统日志(使用 syslogd / logger) - 无需重新启动进程或重新启动。
使用找到的代码 here 效果很好,直到我们尝试 stop/close 记录器 fd,此时写入 stdout/stderr 失败并且一切都中断了。下面的示例:
int main()
{
// Got command to direct all output to syslog:
FILE *fl;
fl = popen("logger","w");
if(fl == NULL)
return 1;
fprintf(fl,"logger test new"); // This goes to syslogd
int nf;
nf = fileno(fl);
dup2(nf,STDOUT_FILENO);
dup2(nf,STDERR_FILENO);
fprintf(stdout,"Written in stdout\n");
fprintf(stderr,"Written in stderr\n");
// ...some time later when we've logged enough things:
pclose(fl);
fprintf(stdout,"This will fail\n");
fprintf(stderr,"Catch fire and die\n");
}
所以问题是,(如何)我们可以在完成日志记录后恢复原始状态?
在 dup()
和 dup2()
上使用 RTFM 我不清楚我们如何才能实现这一目标,如果有可能 "reopen" 或者 freopen()
stdout/stderr,但作为最后的手段,也许将 nf
指向 /dev/null/
是可以接受的,这样至少不会崩溃。
您必须在 dup2 之前复制初始文件描述符,否则 dup2 将关闭它们并且无法恢复它们。
int stdout_copy = dup(STDOUT_FILENO);
dup2(nf, STDOUT_FILENO);
/* do something with stdout */
dup2(stdout_copy, STDOUT_FILENO);
close(stdout_copy);
引入错误处理,添加 fflush
调用以确保您不会在 stdlib 缓冲区中留下未写入的数据,您应该做好。
Linux 手册页明确指出 dup2 不会关闭 oldfd
。不要忘记也关闭 nf
.
背景:我们有一个嵌入式linux系统运行 Busybox(资源有限),我们有一个进程运行通常会吐在控制台上输出大量信息(通过 stdout / stderr),但我们希望 暂时 根据命令将其重定向到系统日志(使用 syslogd / logger) - 无需重新启动进程或重新启动。
使用找到的代码 here 效果很好,直到我们尝试 stop/close 记录器 fd,此时写入 stdout/stderr 失败并且一切都中断了。下面的示例:
int main()
{
// Got command to direct all output to syslog:
FILE *fl;
fl = popen("logger","w");
if(fl == NULL)
return 1;
fprintf(fl,"logger test new"); // This goes to syslogd
int nf;
nf = fileno(fl);
dup2(nf,STDOUT_FILENO);
dup2(nf,STDERR_FILENO);
fprintf(stdout,"Written in stdout\n");
fprintf(stderr,"Written in stderr\n");
// ...some time later when we've logged enough things:
pclose(fl);
fprintf(stdout,"This will fail\n");
fprintf(stderr,"Catch fire and die\n");
}
所以问题是,(如何)我们可以在完成日志记录后恢复原始状态?
在 dup()
和 dup2()
上使用 RTFM 我不清楚我们如何才能实现这一目标,如果有可能 "reopen" 或者 freopen()
stdout/stderr,但作为最后的手段,也许将 nf
指向 /dev/null/
是可以接受的,这样至少不会崩溃。
您必须在 dup2 之前复制初始文件描述符,否则 dup2 将关闭它们并且无法恢复它们。
int stdout_copy = dup(STDOUT_FILENO);
dup2(nf, STDOUT_FILENO);
/* do something with stdout */
dup2(stdout_copy, STDOUT_FILENO);
close(stdout_copy);
引入错误处理,添加 fflush
调用以确保您不会在 stdlib 缓冲区中留下未写入的数据,您应该做好。
Linux 手册页明确指出 dup2 不会关闭 oldfd
。不要忘记也关闭 nf
.