在C中,如何在进行execvp()或类似调用时将stdin/stdout/stderr重定向到文件?

Mat*_*att 22 c unix linux exec io-redirection

我有以下代码:

pid_t pid = fork();
if (pid == -1)
{
    // ...
}
else if (pid == 0)
{
    stdin = someopenfile;
    stdout = someotherfile;
    stderr = somethirdopenfile;
    execvp(args[0], args);
    // handle error ...
}
else
{
    // ...
}
Run Code Online (Sandbox Code Playgroud)

问题是,execvp()调用的输入/输出仍然是控制台,而不是文件.显然,我做错了什么,做这件事的正确方法是什么?

caf*_*caf 44

正确的方法是替换文件描述符STDIN_FILENO,STDOUT_FILENOSTDERR_FILENO使用打开的文件dup2().您还应该关闭子进程中的原始文件:

else if (pid == 0)
{
    dup2(fileno(someopenfile), STDIN_FILENO);
    dup2(fileno(someotherfile), STDOUT_FILENO);
    dup2(fileno(somethirdopenfile), STDERR_FILENO);
    fclose(someopenfile);
    fclose(someotheropenfile);
    fclose(somethirdopenfile);
    execvp(args[0], args);
    // handle error ...
}
Run Code Online (Sandbox Code Playgroud)

  • 大多数系统调用都可能失败.`dup2(2)`也不例外.特别是在达到文件描述符限制时可以使用`errno == EMFILE`失败(使用`ulimit` bash builtin或`setr​​limit(2)`syscall可以降低它).阅读http://www.kernel.org/doc/man-pages/online/pages/man2/dup2.2.html (4认同)
  • @rustyx:不,“dup2()”首先关闭目标文件描述符(如果它打开)。 (2认同)

Jac*_*ack 7

看看freopen功能.

我不得不做类似的事情stdout并编写了两个为我工作的函数:

static int fd;
static fpos_t pos;

void switchStdout(const char *newStream)
{
  fflush(stdout);
  fgetpos(stdout, &pos);
  fd = dup(fileno(stdout));
  freopen(newStream, "w", stdout);
}

void revertStdout()
{
  fflush(stdout);
  dup2(fd, fileno(stdout));
  close(fd);
  clearerr(stdout);
  fsetpos(stdout, &pos);
}
Run Code Online (Sandbox Code Playgroud)