C重定向终端描述符

时间:2018-10-27 16:53:28

标签: c redirect file-descriptor

是否可以将终端中编写的所有内容重定向到进程?

例如,在启动过程之后,如果我在终端中编写“命令”,则应将其从我的过程或类似的东西重定向到管道。

2 个答案:

答案 0 :(得分:0)

从子进程开始,否。您必须在父进程中进行设置,并使其向下传播给孩子(除非有某种疯狂的破解方法)。

您可以从外壳重定向。

exec >file

这会将标准输出重定向到file,并将应用于以后在Shell中运行的所有命令。如果愿意,可以将其变成一个函数。

答案 1 :(得分:0)

是的,在程序启动后,从程序(及其所有子进程)重定向所有终端输出应该是可行的。 Unix程序通常通过写入标准输出(stdout)来写入终端。对于所有进程,标准输出始终位于文件描述符编号1(C常数为STDOUT_FILENO)上。您可以使用dup2()系统调用将任何文件描述符号替换为另一个文件描述符。

因此您可以使用int fds[2]; pipe(fds);创建管道。然后fds[1]将是一个文件描述符号,可用于写入管道。如果执行dup2(fds[1], STDOUT_FILENO);,则标准输出也将写入管道。 (既然您现在可以使用stdout了,则可能以后不需要close(fds[1]);,因为您可能不需要它了。)

您还可以先通过fd = open("filename", O_WRONLY);然后是dup2(fd, STDOUT_FILENO);打开文件进行写入,以便所有写入stdout的内容都进入文件。

请注意,在执行任何可能写入标准输出的操作之前,您需要在程序的最开始处重定向标准输出。


上述技巧将使标准输出流向管道而不是终端。如果您希望输出到终端,请在文件管道中获取输出副本,这比较困难,但是也可以做到。您需要创建一个内部管道,然后创建dup2(that_pipe, STDOUT_FILENO);,以便stdout写入该管道。然后,您需要从该管道读取(可能先使用poll(),然后使用read()),然后将您得到的所有内容都写入1)终端和2)到另一个超出程序范围的管道或文件中。因此,如果要复制输出,则需要两个管道

tee命令从外壳执行此操作(将标准输出复制到文件)。


这种dup2()方法不是防弹的,因为Unix终端(即使使用GUI终端仿真器而不是硬件控制台)也是/dev中的设备。您可以在shell中键入tty或在C语言中使用ttyname(STDOUT_FILENO)来查看/dev中的哪个文件对应于stdout写入的终端。原则上,任何程序(在同一用户帐户下)都可以使用该文件名打开终端设备并对其进行写入,而无需征求任何其他程序的许可。您可以使用write程序从shell中轻松尝试以下操作:

echo hello world | write $(whoami) /dev/ttys123

其中/dev/ttys123是通过在其他终端窗口中键入tty得到的(名称在不同的操作系统(例如Linux和MacOS)上看起来有些不同)。您应该看到hello world出现在另一个窗口中。