[英]Redirecting the output of a child process
There are several ways of redirecting the output of a child process: 有几种方法可以重定向子进程的输出:
freopen(3)
freopen(3)
dup(3)
dup(3)
popen(3)
popen(3)
What should one pick if all is wanted is to execute a child process and have it output saved in a given file, pretty much like the ls > files.txt
works? 如果只需要一个子程序,那就是执行一个子进程并将其输出保存在给定的文件中,就像
ls > files.txt
工作原理一样?
What is normally used by shells? 贝壳通常使用什么?
You can discover what your favorite shell uses by strace(1)
ing your shell. 您可以通过
strace(1)
shell来发现自己喜欢的shell使用的东西。
In one terminal: 在一个终端中:
echo $$
In another terminal: 在另一个终端:
strace -o /tmp/shell -f -p [PID from the first shell]
In the first terminal again: 再次在第一个终端中:
ls > files.txt
In the second terminal, ^C
your strace(1)
command and then edit the /tmp/shell
output file to see what system calls it made to do the redirection. 在第二个终端中,
^C
您的strace(1)
命令,然后编辑/tmp/shell
输出文件以查看进行重定向的系统调用。
freopen(3)
manipulates the C standard IO FILE*
pointers. freopen(3)
操作C标准IO FILE*
指针。 All this will be thrown away on the other side of the execve(2)
call, because it is maintained in user memory . 所有这些都将在
execve(2)
调用的另一端丢弃,因为它保存在用户内存中 。 You could use this after the execve(2)
call, but that would be awkward to use generically. 您可以在
execve(2)
调用之后使用它,但是一般使用会很尴尬。
popen(3)
opens a single unidirectional pipe(7)
. popen(3)
打开一个单向pipe(7)
。 This is useful, but extremely limited -- you get either the standard output descriptor or the standard input descriptor. 这很有用,但非常有限-您可以使用标准输出描述符或标准输入描述符。 This would fail for something like
ls | grep foo | sort
对于
ls | grep foo | sort
这样的操作将失败。 ls | grep foo | sort
ls | grep foo | sort
where both input and output must be redirected. ls | grep foo | sort
必须同时重定向输入和输出的位置。 So this is a poor choice. 因此,这是一个糟糕的选择。
dup2(2)
will manage file descriptors -- a kernel-implemented resource -- so it will persist across execve(2)
calls and you can set up as many file descriptors as you need, which is nice for ls > /tmp/output 2> /tmp/error
or handling both input and output: ls | sort | uniq
dup2(2)
将管理文件描述符(一种内核实现的资源),因此它将在execve(2)
调用之间持久存在, 并且您可以根据需要设置任意数量的文件描述符,这对于ls > /tmp/output 2> /tmp/error
或同时处理输入和输出: ls | sort | uniq
ls | sort | uniq
ls | sort | uniq
. ls | sort | uniq
。
There is another mechanism: pty(7)
handling. 还有另一种机制:
pty(7)
处理。 The forkpty(3)
, openpty(3)
, functions can manage a new pseudo-terminal device created specifically to handle another program. forkpty(3)
, openpty(3)
函数可以管理专门为处理另一个程序而创建的新伪终端设备。 The Advanced Programming in the Unix Environment, 2nd edition book has a very nice pty
example program in its source code, though if you're having trouble understanding why this would be useful, take a look at the script(1)
program -- it creates a new pseudo-terminal and uses it to record all input and output to and from programs and stores the transcript to a file for later playback or documentation. Unix环境下的Advanced Programming,第2版书的源代码中有一个非常漂亮的
pty
示例程序,尽管如果您无法理解为什么这样做有用,请看一下script(1)
程序-创建一个新的伪终端,并使用它来记录与程序之间的所有输入和输出,并将脚本存储到文件中以供以后播放或记录。 You can also use it to script actions in interactive programs, similar to expect(1)
. 您还可以使用它来编写交互式程序中的动作脚本,类似于
expect(1)
。
I would expect to find dup2()
used mainly. 我希望找到主要使用的
dup2()
。
Neither popen()
nor freopen()
is designed to handle redirections such as 3>&7
. popen()
和freopen()
都不用于处理重定向,例如3>&7
。 Up to a point, dup()
could be used, but the 3>&7
example shows where dup()
starts to creak; 到目前为止,可以使用
dup()
,但是3>&7
示例显示dup()
开始发出吱吱声; you'd have to ensure that file descriptors 4, 5, and 6 are open (and 7 is not) before it would handle what dup2()
would do without fuss. 您必须确保文件描述符4、5和6已打开(而7没有打开),然后它才能处理
dup2()
不会引起大惊小怪的事情。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.