Bash 如何获取执行程序的输出?

Bash 如何获取执行程序的输出?

当我执行一个程序时重击,例如,[ls][2],它将其输出发送到标准输出( fd &1)。并且执行程序的输出显示在终端中。 Bash/terminal 如何获取ls命令的输出?

答案1

作为shell的子进程,ls继承shell的打开文件描述符。标准文件描述符(stdin、stdout、stderr(或 0、1、2))连接到伪终端,由终端仿真器处理。

例如(在 Linux 系统上):

$ ls /proc/$$/fd -l
total 0
lrwx------ 1 muru muru 64 Dec 10 16:15 0 -> /dev/pts/3
lrwx------ 1 muru muru 64 Dec 10 16:15 1 -> /dev/pts/3
lrwx------ 1 muru muru 64 Dec 10 16:15 2 -> /dev/pts/3
lrwx------ 1 muru muru 64 Dec 10 16:15 255 -> /dev/pts/3
$ ls /proc/$(pgrep terminator -f)/fd -l | grep pts/3
lrwx------ 1 muru muru 64 Dec 10 16:15 26 -> /dev/pts/3

也就是说, 的输出ls,或者 shell 本身,不是由 shell 处理的,而是由终端仿真器(GNOME Terminal、terminator、xterm 等)处理的。


你可以测试一下:

pts在 Linux 上,找到终端仿真器(例如 GNOME 终端)使用的伪终端 ( ):

$ ls -l /proc/$(pgrep -n gnome-terminal)/fd | grep pts
lrwx------ 1 muru muru 64 Dec 10 18:00 1 -> /dev/pts/1
lrwx------ 1 muru muru 64 Dec 10 18:00 15 -> /dev/pts/20
lrwx------ 1 muru muru 64 Dec 10 18:00 2 -> /dev/pts/1

现在,它会使用 的非标准 fd(0、1、2 以外的 fd)gnome-terminal为 shell 提供输入和输出。终端仿真器读取发送到该 PTS 的数据,并(经过一些处理,例如颜色等)将其显示在屏幕上。在本例中,即15, 连接到pts/20。如果我向该点写一些东西,我可以期望它出现在该终端中:

在此输入图像描述

进一步阅读:


另一种情况,我做的事情如下:

echo $(ls)
a=$(date)
vim `command -v some_script`

叫做命令替换。在命令替换中,命令的输出由 shell 本身捕获,并且永远不会到达终端,除非您将其打印出来(例如,echo $(ls))。此案处理于豪克·拉金的回答

答案2

事实证明,我在命令替换的意义上误解了这个问题。只有在这种情况下,shell 才会参与输出处理。

希望这也引起人们的兴趣...

strace -p 2140在我运行echo $(/bin/echo foo)这个ll之前,我附加到一个shell 。这是结果的一部分:

pipe([3, 4])
pipe([5, 6])
...
read(3, "foo\n", 128)

这是子进程中发生的情况:

dup2(4, 1)
close(4)
close(3)
...
execve("/bin/echo", ...

shell 连接文件描述符 3 和 4,然后分叉。子进程stdout在运行新程序之前将 fd 设为 4。因此,子进程写入的所有内容都stdout可以由父 shell 在其 fd 3 上读取。

相关内容