str*_*gee 6 io-redirection stdout stdin
在这个答案中,在最底部,Gilles 提到一个命令可以有多个输出或输入。
是的,有cat foo bar | something
, 用于将foo
和bar
作为输入,还有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
还有一个错误输出通道。
一个程序通常具有三个输入/输出通道,由它们的文件描述符编号标识:
文件描述符 0、1 和 2 的目的只是一个约定问题——没有任何东西强制程序不能尝试写入文件描述符 0 或从描述符 1 和 2 读取——但这是一个几乎普遍遵循的约定。
如果从终端运行程序,文件描述符 0、1 和 2 开始连接到该终端,除非它们已被重定向。其他文件描述符一开始是关闭的,如果程序打开其他文件,将使用它们。
特别是,所有命令都有两个输出:标准输出(对于命令的有效负载,“有用的”输出)和标准错误(对于错误或信息性消息)。
shell 中的管道 ( command1 | command2 | command3 | …
) 将每个命令的标准输出连接到下一个命令的标准输入。所有命令的标准错误都发送到终端(除非重定向)。
Shell 提供了重定向其他文件描述符的方法。您可能遇到过2>&1
或2>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)