背景:我们有一个运行Busybox的嵌入式Linux系统(资源有限),我们有一个正在运行的进程,它通常会在控制台上发出大量信息(通过stdout / stderr)但是我们会喜欢暂时将命令重命名为syslog(使用syslogd / logger) - 无需重启过程或重新启动。
使用找到的代码here可以很好地工作,直到我们尝试停止/关闭记录器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我不清楚我们究竟能够如何实现这一点,如果可以“重新开启”或许是freopen()
stdout / stderr,而是作为一个也许最后可能会将nf
指向/dev/null/
,因此至少不会崩溃。
答案 0 :(得分:2)
您必须在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缓冲区中保留未写入的数据,并且你应该做得很好。
答案 1 :(得分:0)
Linux手册页很清楚dup2不会关闭oldfd
。别忘了也关闭nf
。