重定向子进程的输出

3

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

  1. 使用 freopen(3)
  2. 使用 dup(3)
  3. 使用 popen(3)
  4. ...

如果想要执行一个子进程,并将其输出保存在给定的文件中,就像 ls > files.txt 的工作方式一样,应该选择哪种方法?

通常Shell使用什么方法?

2个回答

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)可以管理一个新的伪终端设备,专门用于处理另一个程序。Unix环境高级编程第二版书中有一个非常好的pty示例程序在其源代码中,如果您不理解为什么这很有用,请看看script(1)程序——它创建一个新的伪终端并使用它来记录所有输入和输出到程序以及从程序中存储的副本以供以后播放或文档化。您也可以使用它来脚本化交互式程序中的操作,类似于expect(1)


2

我希望主要使用dup2()

popen()freopen()都不适用于处理诸如3>&7这样的重定向。在某种程度上,可以使用dup(),但是3>&7的示例显示了dup()开始出现问题;您必须确保文件描述符4、5和6已打开(而且7没有打开),然后它才能处理dup2()轻松处理的内容。


我刚刚检查了strace输出,遵循@sarnold的建议,bash使用dup2()。所以你似乎是正确的!+1 - Roman Byshko

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接