在Linux上,我有一些C ++代码,我想要执行另一个应用程序。该程序将一些数据输出到stderr。因此,我通过使用stderr作为流参数调用freopen()来重定向stderr。问题是,我想将stderr重定向到另一个运行的进程。
以下是我正在使用的方案。我fork()当前的进程;在子进程中,我重定向了stderr;然后我execv()运行单独的应用程序。
首先,我设置了一个Sentry来重定向stderr输出。这是代码:
class StderrSentry {
public:
StderrSentry() {
freopen( "NUL", "wt", stderr );
}
~StderrSentry() {
fclose( stderr );
}
};
然后在代码中:
pid_t pid = fork();
int retval=-1;
if( pid < 0 ) {
success = false;
}
else if( ! pid ) { // child process
StderrSentry stdErrSentry; // REDIRECTING STDERR HERE!
pid_t chid = setsid();
if (chid == -1 ) {
exit(-1);
}
else {
// HERE IS THE execv() call:
if( execv(command[0].c_str(), const_cast<char**>(&c_args[0])) < 0 ) {
exit( -1 );
}
}
}
// ... else etc...
一旦execv()调用用指定的一个替换当前进程,stderr重定向在技术上是否仍然有效?
这实际上是按照我的意愿行事,但它是侥幸,还是这样做的?
我无法激活execv中运行的应用程序中的stderr重定向,因为它不是我的代码。
感谢您提供任何相关信息。
答案 0 :(得分:2)
使用操作文件描述符(open,close,dup2)的操作系统原语比使用freopen和朋友更通常更安全,但是,这应该可行,并且是shell管道的实现方式。 execve将所有打开的文件打开,除非它们已被标记为F_CLOEXEC。
答案 1 :(得分:1)
如果文件描述符没有O_CLOEXEC标志(参见man 2 open),它们应该持久存在于exec中。此标志仅在内核2.6.23及更高版本中可用,因此如果您使用的是较旧的发行版,则该标记将不可用。
答案 2 :(得分:0)
重定向非常有效。 execv调用会更改过程映像,但文件描述符保持不变。