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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14543443/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 18:49:01  来源:igfitidea点击:

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

clinuxunixexecio-redirection

提问by Matt

I have the following code:

我有以下代码:

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

The problem is, the input/output of the execvp()call is still the console, rather than the files. Clearly I am doing something wrong, what is the right way to do this?

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

采纳答案by caf

The right way to do it is to replace the file descriptors STDIN_FILENO, STDOUT_FILENOand STDERR_FILENOwith the opened files using dup2(). You should also then close the original files in the child process:

正确的做法是替换文件描述符STDIN_FILENOSTDOUT_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 ...
}

回答by Hyman

Take a look at freopenfunction.

看看freopen功能。

I had to do something similar with stdoutand wrote two functions that do the work for me:

我不得不做类似的事情,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);
}

回答by alhelal

You can use this when stdin , stdout , stderr are terminal-

当 stdin 、 stdout 、 stderr 是终端时,您可以使用它

//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);