是否可以将终端中编写的所有内容重定向到进程?
例如,在启动过程之后,如果我在终端中编写“命令”,则应将其从我的过程或类似的东西重定向到管道。
答案 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
出现在另一个窗口中。