关于linux:在C语言中,当执行execvp()或类似调用时,如何将stdin / stdout / stderr重定向到文件?

In C how do you redirect stdin/stdout/stderr to files when making an execvp() or similar call?

我有以下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
pid_t pid = fork();
if (pid == -1)
{
    // ...
}
else if (pid == 0)
{
    stdin = someopenfile;
    stdout = someotherfile;
    stderr = somethirdopenfile;
    execvp(args[0], args);
    // handle error ...
}
else
{
    // ...
}

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


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

1
2
3
4
5
6
7
8
9
10
11
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 ...
}


看一下freopen函数。

我必须对stdout做类似的事情,并编写了两个对我有用的函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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);
}


您可以在stdin,stdout,stderr处于终端状态时使用此命令

1
2
3
4
5
6
7
8
9
10
11
//change stdin,stdout,stderr
    freopen("new_stdin","r",stdin);
    freopen("new_stdout","r",stdout);
    freopen("new_stderr","r",stderr);

    //----do something;

//reset stdin,stdout,stderr
     freopen("/dev/tty","r",stdin);
     freopen("/dev/tty","r",stdout);
     freopen("/dev/tty","r",stderr);