什么是Linux上的stdin,stdout和stderr?
标准输入
, 标准输出
, 和 斯特德
启动Linux命令时创建的三个数据流。您可以使用它们来告诉您的脚本是通过管道传输还是重定向。我们向您展示如何。
流连接两点
一旦您开始了解Linux和类似Unix的操作系统,就会发现其中的术语 标准输入
, 标准输出
, 和 斯特德
。这是执行Linux命令时建立的三个标准流。在计算中,流是可以传输数据的东西。在这些流的情况下,该数据是文本。
数据流就像水流一样,有两个末端。他们有一个来源和一个流出。无论您使用哪种Linux命令,每个流的一端都会出现。另一端由启动命令的外壳程序确定。根据启动命令的命令行,该端将连接到终端窗口,连接到管道或重定向到文件或其他命令。
Linux标准流
在Linux中,标准输入
是标准输入流。这接受文本作为输入。从命令到外壳的文本输出是通过 标准输出
(标准输出)流。来自命令的错误消息通过 斯特德
(标准错误)流。
因此,您可以看到有两个输出流, 标准输出
和 斯特德
,以及一个输入流, 标准输入
。由于错误消息和正常输出各自具有将其携带到终端窗口的管道,因此可以彼此独立地进行处理。
流像文件一样处理
与几乎所有其他内容一样,Linux中的流被视为文件。您可以从文件中读取文本,也可以将文本写入文件中。这两个动作都涉及数据流。因此,将数据流作为文件处理的概念并不是一件容易的事。
与进程关联的每个文件都分配有一个唯一的编号以进行标识。这称为文件描述符。每当需要对文件执行操作时,都使用文件描述符来标识文件。
这些值始终用于 标准输入
, 标准输出
和 斯特德
:
- 0:标准输入
- 1:标准输出
- 2:stderr
对管道和重定向做出反应
为了使某人对某个主题的介绍更加轻松,一种常见的技术是讲授该主题的简化版本。例如,对于语法,我们被告知规则是“ E在E之前,C之后”。但是实际上,与遵守此规则的情况相比,此规则有更多的例外情况。
同样地,当谈论 标准输入
, 标准输出
, 和 斯特德
方便地淘汰既不知道也不关心进程的三个标准流在哪里终止的公认公理。进程是否应该关心其输出是发送到终端还是重定向到文件?它甚至可以判断其输入是来自键盘还是正从另一个进程通过管道输入?
实际上,如果软件作者决定添加该功能,则流程确实知道(或者至少可以找到,应该选择检查),并且可以相应地更改其行为。
我们可以很容易地看到这种行为上的变化。尝试以下两个命令:
ls
ls |猫
这 ls
如果命令的输出(标准输出
)正在通过管道传递到另一个命令中。这是ls
切换到单列输出,而不是由 猫
。和 ls
如果其输出被重定向,则会执行相同的操作:
ls> capture.txt
猫捕获.txt
重定向标准输出和标准错误
通过专用流传递错误消息是有好处的。这意味着我们可以重定向命令的输出(标准输出
)到文件,仍然看到任何错误消息(斯特德
)在终端窗口中。您可以根据需要对错误进行处理,以防发生错误。它还可以防止错误消息污染文件 标准输出
已被重定向到。
在编辑器中键入以下文本,然后将其保存到名为error.sh的文件中。
#!/ bin / bash echo“关于要尝试访问不存在的文件” cat bad-filename.txt
使用以下命令使脚本可执行:
chmod + x error.sh
脚本的第一行通过标准输出
溪流。第二行尝试访问不存在的文件。这将生成一条错误消息,该消息通过 斯特德
.
使用以下命令运行脚本:
./error.sh
我们可以看到两个输出流 标准输出
和 斯特德
,已显示在终端窗口中。
让我们尝试将输出重定向到文件:
./error.sh> capture.txt
通过以下方式传递的错误消息 斯特德
仍然发送到终端窗口。我们可以检查文件的内容,看看是否 标准输出
输出到文件。
猫捕获.txt
来自的输出 标准输入
被按预期重定向到文件。
这 >
重定向符号适用于 标准输出
默认。您可以使用数字文件描述符之一来指示要重定向的标准输出流。
显式重定向 标准输出
,请使用以下重定向指令:
1>
显式重定向 斯特德
,请使用以下重定向指令:
2>
让我们再次尝试测试,这次我们将使用 2>
:
./error.sh 2> capture.txt
错误消息被重定向,并且 标准输出
回声
消息发送到终端窗口:
我们来看一下capture.txt文件中的内容。
猫捕获.txt
这 斯特德
邮件按预期方式位于capture.txt中。
重定向stdout和stderr
当然,如果我们可以重定向 标准输出
或者 斯特德
到一个彼此独立的文件,我们应该能够同时将它们重定向到两个不同的文件?
我们可以。该命令将直接 标准输出
到一个名为capture.txt的文件,然后 斯特德
到名为error.txt的文件。
./error.sh 1> capture.txt 2> error.txt
因为输出流(标准输出和标准错误)都被重定向到文件,所以终端窗口中没有可见的输出。就像什么都没有发生一样,我们返回到命令行提示符。
让我们检查每个文件的内容:
猫捕获.txt
猫error.txt
将stdout和stderr重定向到同一文件
太好了,我们已经将每个标准输出流放入其自己的专用文件中。我们唯一可以做的其他组合就是同时发送 标准输出
和 斯特德
到同一文件。
我们可以使用以下命令来实现:
./error.sh> capture.txt 2>&1
让我们来分解一下。
- ./error.sh:启动error.sh脚本文件。
- > capture.txt:重定向
标准输出
流到capture.txt文件。>
是的简写1>
. - 2>&1:这使用&>重定向指令。此指令使您可以告诉Shell使一个流与另一个流到达相同的目的地。在这种情况下,我们说的是“重定向流2,
斯特德
,流到同一目的地,标准输出
,将被重定向到。”
没有可见的输出。令人鼓舞。
让我们检查capture.txt文件并查看其中的内容。
猫捕获.txt
这俩 标准输出
和 斯特德
流已重定向到单个目标文件。
要重定向并静默丢弃流的输出,请将输出定向到 / dev /空
.
在脚本中检测重定向
我们讨论了命令如何检测是否有任何流被重定向,并可以选择相应地更改其行为。我们可以在自己的脚本中完成此操作吗?我们可以。这是一种非常容易理解和使用的技术。
在编辑器中键入以下文本,并将其另存为input.sh。
#!/ bin / bash如果[-t 0];然后从键盘回显stdin,否则从管道或文件fi回显stdin
使用以下命令使其可执行:
chmod + x input.sh
聪明的部分是方括号内的测试。这 -t
如果与文件描述符关联的文件在终端窗口中终止,则(terminal)选项将返回true(0)。我们使用文件描述符0作为测试的参数,它表示标准输入
.
如果 标准输入
连接到终端窗口,测试将证明是正确的。如果 标准输入
连接到文件或管道,测试将失败。
我们可以使用任何方便的文本文件来生成脚本的输入。在这里,我们使用的是一个名为dummy.txt的文件。
./input.sh <虚拟文件.txt
输出结果表明脚本识别出输入不是来自键盘,而是来自文件。如果选择这样做,则可以相应地更改脚本的行为。
那是与文件重定向有关的,让我们通过管道进行尝试。
猫dummy.txt | ./input.sh
该脚本识别出其输入正在通过管道传递到其中。或者更确切地说,它再次认识到 标准输入
流未连接到终端窗口。
让我们既不使用管道也不使用重定向来运行脚本。
./input.sh
这 标准输入
流连接到终端窗口,并且脚本相应地报告此情况。
要在输出流中检查同一件事,我们需要一个新脚本。在编辑器中键入以下内容,并将其另存为output.sh。
#!/ bin / bash如果[-t 1];然后echo stdout将进入终端窗口,否则echo stdout将被重定向或通过管道传输到fi
使用以下命令使其可执行:
chmod + x input.sh
对该脚本的唯一重大更改是在方括号中的测试中。我们使用数字1表示以下文件的文件描述符 标准输出
.
让我们尝试一下。我们将通过管道输出 猫
.
./输出|猫
该脚本认识到其输出不会直接进入终端窗口。
我们还可以通过将输出重定向到文件来测试脚本。
./output.sh> capture.txt
没有输出到终端窗口,我们默默地返回到命令提示符。正如我们所期望的。
我们可以查看capture.txt文件内部,以查看捕获的内容。使用以下命令进行操作。
猫捕获
同样,脚本中的简单测试可以检测到 标准输出
流没有直接发送到终端窗口。
如果我们运行的脚本没有任何管道或重定向,它应该检测到 标准输出
被直接传送到终端窗口。
./output.sh
这就是我们所看到的。
意识流
知道如何判断您的脚本是连接到终端窗口还是管道,还是正在重定向,可以使您相应地调整其行为。
日志和诊断输出的详细程度可能有所不同,具体取决于它是进入屏幕还是进入文件。错误消息可以记录到与普通程序输出不同的文件中。
通常,更多的知识带来更多的选择。