当一个命令以什么方式或以什么格式通过管道传输到另一个命令时,管道输出存在/被发送?是临时文件吗?是字符串吗?接收管道输出的命令如何解码/读取该输出?
例子:
echo "Someone string" | ./program | tail
程序“ ”是否接收文件形式program
的输出?echo
程序将如何读取该输入?
答案1
管道是一种重定向形式(将标准输出传输到其他目的地),用于 Linux 和其他类 Unix 操作系统中,将一个命令/程序/进程的输出发送到另一个命令/程序/进程以进行进一步处理。 Unix/Linux 系统允许一个命令的 stdout 连接到另一个命令的 stdin。您可以使用管道字符“|”来实现此目的。
管道用于组合两个或多个命令,其中一个命令的输出充当另一个命令的输入,并且该命令的输出可以充当下一个命令的输入,依此类推。它也可以被视为两个或多个命令/程序/进程之间的临时连接。进行进一步处理的命令行程序称为过滤器。
命令/程序/进程之间的这种直接连接允许它们同时运行,并允许数据在它们之间连续传输,而不必通过临时文本文件或通过显示屏传递数据。管道是单向的,即数据从左到右流过管道。
句法 :
command_1 | command_2 | command_3 | .... | command_N
示例:列出所有文件和目录并将其作为 more 命令的输入。
$ ls -l | more
该more
命令将 的输出ls -l
作为其输入。此命令的最终效果是ls -l
一次显示一屏的输出。管道充当容器,接收输出ls -l
并将其more
作为输入。该命令不使用磁盘将 的标准输出连接到ls -l
的标准输入,more
因为管道是在主内存中实现的。就 I/O 重定向运算符而言,上述命令等效于以下命令序列。
$ ls -l -> temp
more -> temp (or more temp)
[contents of temp]
rm temp
答案2
./program
echo
接收作为文件的输出,即标准流文件/dev/stdin
。演示:
echo foo | wc -c
echo foo | wc -c /dev/stdin
输出:
4
4 /dev/stdin
注意:流文件与存储在磁盘上的文件有些不同。我们可以随机访问数据在常规文件中,但不在流媒体文件。这就像 CD 播放器和收音机播放歌曲的区别一样。在 CD 播放器上我们可以快退、快进、搜索和跳过歌曲。收音机仅输出(或流式传输)广播公司发送的任何内容现在。
流存储在哪里?操作系统将其存储在临时的数据缓冲区,其大小因操作系统而异。看管道缓冲区有多大?
在较低级别上,操作系统使用文件描述符,不是文件名。文件描述符只是一堆数字,其中每个进程标识符有自己的堆栈。 Linux 还允许访问/dev/stdin
流(始终是文件描述符“0”), 那样:
echo foo | wc -c /proc/self/fd/0
输出:
4 /proc/self/fd/0
通过 util 可以看到另一种 Linux 抽象realpath
:
realpath /dev/stdin /proc/self/fd/0
输出(在我系统的当前终端上):
/dev/pts/2
/dev/pts/2
这些字母pts
代表磷塞乌多时间终端s。最后一个2
数字在终端之间总是会有所不同,因此它不是一个可靠的名称,但这些数字可用于以下技巧:如何在不创建任何新管道或文件的情况下将输出从一个终端发送到另一个终端。