重定向子进程的输出

时间:2011-12-19 01:33:04

标签: c shell unix io-redirection

有几种方法可以重定向子进程的输出:

  1. 使用freopen(3)
  2. 使用dup(3)
  3. 使用popen(3)
  4. ...
  5. 如果需要的话,应该选择什么才能执行子进程并将其输出保存在给定文件中,就像ls > files.txt的工作原理一样?

    贝壳通常使用什么?

2 个答案:

答案 0 :(得分:3)

您可以通过strace(1) shell发现您最喜欢的shell使用的内容。

在一个终端:

echo $$

在另一个终端:

strace -o /tmp/shell -f -p [PID from the first shell]

再次在第一个终端:

ls > files.txt

在第二个终端中,^C您的strace(1)命令,然后编辑/tmp/shell输出文件,以查看它进行重定向的系统调用。


freopen(3)操纵C标准IO FILE*指针。所有这些都将在execve(2)调用的另一端丢弃,因为它保存在用户内存中。您可以在 execve(2)调用之后使用此,但这通常会很难使用。

popen(3)会打开一个单向pipe(7)。这很有用,但非常有限 - 您可以获得标准输出描述符标准输入描述符。对于像ls | grep foo | sort这样的东西,输入和输出必须重定向都会失败。所以这是一个糟糕的选择。

dup2(2)将管理文件描述符 - 一个内核实现的资源 - 因此它将在execve(2)次调用之间保持不变,您可以设置与您一样多的文件描述符需要,这对于ls > /tmp/output 2> /tmp/error或处理输入输出很有用:ls | sort | uniq

还有另一种机制:pty(7)处理。 forkpty(3)openpty(3)函数可以管理专门为处理另一个程序而创建的新伪终端设备。 Advanced Programming in the Unix Environment, 2nd edition book在其源代码中有一个非常好的pty示例程序,但如果您无法理解为什么这会有用,请查看script(1)程序 - 它创建一个新的伪终端并使用它来记录程序的所有输入和输出,并将成绩单存储到文件中以供以后回放或记录。您还可以使用它来编写交互式程序中的操作脚本,类似于expect(1)

答案 1 :(得分:2)

我希望主要使用dup2()

popen()freopen()都不是为了处理重定向而设计的,例如3>&7。最多可以使用dup(),但3>&7示例显示dup()开始吱吱作响的地方;你必须确保文件描述符4,5和6是开放的(而7不是)才能处理dup2()没有大惊小怪的事情。