一个命令怎么会有多个输出?

str*_*gee 6 io-redirection stdout stdin

这个答案中,在最底部,Gilles 提到一个命令可以有多个输出或输入。

是的,有cat foo bar | something, 用于将foobar作为输入,还有tee用于输出;但这似乎并不是他真正要说的。

一个程序怎么会有多个输入或输出?

Gil*_*il' 11

这个cat foo bar例子不是我的意思。这里一次cat只有一个输入和一个输出。

tee是一个例子:它同时输出到所有参数,加上它的标准输出。使用与我之前的答案相同类型的 ASCII 艺术图,这是tee foo bar它在终端中运行时的样子。

   +------------------+    
   |       tee        |    
===|<stdin            |         +------------+
?  |                  |         |  terminal  |
   |           stdout>|=========|<input      |
   |                  |   ? ##==|<           |
   |                  |     ||  +------------+
   |           stderr>|=====##
   |                  |   ?
   |                  |       +-------------+
   |                3>|=======|> file "foo" |
   |                  |   ?   +-------------+
   |                  |       +-------------+
   |                4>|=======|> file "bar" |
   |                  |   ?   +-------------+
   |                  |    
   +------------------+    
Run Code Online (Sandbox Code Playgroud)

在这个例子中,tee将“有用”的输出发送到三个通道:到终端(因为这是它的标准输出连接到的地方)和两个文件。此外,tee还有一个错误输出通道。

一个程序通常具有三个输入/输出通道,由它们的文件描述符编号标识:

  • 标准输入(简称stdin,文件描述符编号0);
  • 标准输出(简称stdout,文件描述符编号1);
  • 标准错误(简称 stderr,文件描述符编号为 2)。

文件描述符 0、1 和 2 的目的只是一个约定问题——没有任何东西强制程序不能尝试写入文件描述符 0 或从描述符 1 和 2 读取——但这是一个几乎普遍遵循的约定。

如果从终端运行程序,文件描述符 0、1 和 2 开始连接到该终端,除非它们已被重定向。其他文件描述符一开始是关闭的,如果程序打开其他文件,将使用它们。

特别是,所有命令都有两个输出:标准输出(对于命令的有效负载,“有用的”输出)和标准错误(对于错误或信息性消息)。

shell 中的管道 ( command1 | command2 | command3 | …) 将每个命令的标准输出连接到下一个命令的标准输入。所有命令的标准错误都发送到终端(除非重定向)。

Shell 提供了重定向其他文件描述符的方法。您可能遇到过2>&12>file重定向标准错误。请参阅 何时使用额外的文件描述符?和其他帖子链接到其他文件描述符的操作示例。

功能丰富的 shell 还提供进程替换,以将文件重定向概括为管道命令,因此您不受限于每个命令具有单个输入和单个输出的线性管道。

很少有命令尝试访问大于 2 的文件描述符,除非在它们打开文件之后(打开文件会选择一个空闲的文件描述符并将其编号返回给应用程序)。一个例子是 GnuPG,它期望读取数据以对其标准输入进行加密/解密/签名/验证,并将结果写入标准输出。可以告诉它使用该--passphrase-fd选项读取不同文件描述符上的密码。GnuPG 还具有报告其他文件描述符的状态数据的选项,因此您可以在 stdout 上输出负载,在 stderr 上有错误消息,在另一个文件描述符上有状态信息。这是一个将管道命令的输出用作密码短语的示例:

echo fjbeqsvfu | rot13 | gpg -d --passphrase-fd=3 3<&0 <file.encrypted >file.plaintext
Run Code Online (Sandbox Code Playgroud)