有几种方法可以重定向子进程的输出:
freopen(3)
dup(3)
popen(3)
如果需要的话,应该选择什么才能执行子进程并将其输出保存在给定文件中,就像ls > files.txt
的工作原理一样?
贝壳通常使用什么?
答案 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()
没有大惊小怪的事情。