Linux 上的标准输入、标准输出和标准错误是什么?

已发表: 2022-01-29
Linux 计算机上的终端窗口
Fatmawati Achmad Zaenuri/Shutterstock.com

stdinstdoutstderr是启动 Linux 命令时创建的三个数据流。 您可以使用它们来判断您的脚本是否正在通过管道传输或重定向。 我们向您展示如何。

流连接两个点

一旦您开始了解 Linux 和类 Unix 操作系统,您就会遇到术语stdinstdoutstederr 。 这是执行 Linux 命令时建立的三个标准流。 在计算中,流是可以传输数据的东西。 在这些流的情况下,该数据是文本。

数据流,就像水流一样,有两端。 他们有一个来源和一个流出。 无论您使用哪个 Linux 命令,都可以提供每个流的一端。 另一端由启动命令的 shell 决定。 根据启动命令的命令行,该端将连接到终端窗口、连接到管道或重定向到文件或其他命令。

Linux 标准流

在 Linux 中, stdin是标准输入流。 这接受文本作为其输入。 从命令到 shell 的文本输出通过stdout (标准输出)流传递。 命令中的错误消息通过stderr (标准错误)流发送。

因此,您可以看到有两个输出流stdoutstderr以及一个输入流stdin 。 因为错误消息和正常输出都有自己的管道将它们传送到终端窗口,所以它们可以相互独立地处理。

流像文件一样被处理

Linux 中的流——就像几乎所有其他东西一样——被视为文件。 您可以从文件中读取文本,也可以将文本写入文件。 这两个动作都涉及数据流。 因此,将数据流作为文件处理的概念并没有那么牵强。

广告

与进程关联的每个文件都分配有一个唯一编号来标识它。 这称为文件描述符。 每当需要对文件执行操作时,都会使用文件描述符来标识文件。

这些值始终用于stdinstdout,stderr

  • 0 :标准输入
  • 1 :标准输出
  • 2 :标准错误

对管道和重定向做出反应

为了简化某人对某个主题的介绍,一种常见的技术是教授该主题的简化版本。 例如,对于语法,我们被告知规则是“I 在 E 之前,C 之后除外”。 但实际上,这条规则的例外情况比遵守它的情况要多。

类似地,在谈论stdinstdoutstderr时,可以方便地提出一个公认的公理,即一个进程既不知道也不关心它的三个标准流在哪里终止。 进程是否应该关心它的输出是发送到终端还是被重定向到文件中? 它甚至可以判断它的输入是来自键盘还是从另一个进程通过管道输入?

实际上,一个进程确实知道——或者至少它可以发现,如果它选择检查的话——并且如果软件作者决定添加该功能,它可以相应地改变它的行为。

广告

我们可以很容易地看到这种行为变化。 试试这两个命令:

 ls 

 ls | 猫

如果ls命令的输出 ( stdout ) 被传送到另一个命令中,则 ls 命令的行为会有所不同。 是ls切换到单列输出,而不是cat执行的转换。 如果它的输出被重定向, ls也会做同样的事情:

 ls > 捕获.txt 

 猫捕获.txt 

重定向标准输出和标准错误

通过专用流传递错误消息是有好处的。 这意味着我们可以将命令的输出( stdout )重定向到文件,并且仍然在终端窗口中看到任何错误消息( stderr )。 如果需要,您可以在错误发生时对错误做出反应。 它还阻止错误消息污染stdout已重定向到的文件。

在编辑器中键入以下文本并将其保存到名为 error.sh 的文件中。

 #!/bin/bash

echo "即将尝试访问不存在的文件"
猫坏文件名.txt

使用以下命令使脚本可执行:

 chmod +x 错误.sh

脚本的第一行通过stdout流将文本回显到终端窗口。 第二行尝试访问一个不存在的文件。 这将生成通过stderr传递的错误消息。

使用以下命令运行脚本:

 ./error.sh 

我们可以看到,两个输出流stdoutstderr都已显示在终端窗口中。

让我们尝试将输出重定向到一个文件:

 ./error.sh > 捕获.txt 

广告

通过stderr传递的错误消息仍然发送到终端窗口。 我们可以检查文件的内容,看看stdout输出是否到了文件中。

 猫捕获.txt 

stdin的输出按预期重定向到文件。

>重定向符号默认与stdout一起使用。 您可以使用数字文件描述符之一来指示您希望重定向的标准输出流。

要显式重定向stdout ,请使用此重定向指令:

 1>

要显式重定向stderr ,请使用以下重定向指令:

 2>

让我们再次尝试测试,这次我们将使用2>

 ./error.sh 2> 捕获.txt 

错误消息被重定向, stdout echo显消息被发送到终端窗口:

让我们看看 capture.txt 文件中有什么。

 猫捕获.txt 

stderr消息按预期在 capture.txt 中。

重定向标准输出和标准错误

当然,如果我们可以将stdoutstderr重定向到彼此独立的文件,我们应该能够同时将它们重定向到两个不同的文件?

广告

我们可以。 该命令将stdout指向一个名为 capture.txt 的文件,并将stderr指向一个名为 error.txt 的文件。

 ./error.sh 1> 捕获.txt 2> 错误.txt 

因为输出流——标准输出和标准错误——都被重定向到文件,所以终端窗口中没有可见的输出。 我们返回到命令行提示符,就好像什么都没发生一样。

让我们检查每个文件的内容:

 猫捕获.txt
 猫错误.txt 

将 stdout 和 stderr 重定向到同一个文件

这很好,我们已经将每个标准输出流放到了它自己的专用文件中。 我们可以做的唯一其他组合是将stdoutstderr发送到同一个文件。

我们可以使用以下命令来实现:

 ./error.sh > capture.txt 2>&1

让我们分解一下。

  • ./error.sh :启动 error.sh 脚本文件。
  • > capture.txt :将stdout流重定向到 capture.txt 文件。 >1>的简写。
  • 2>&1 :这使用 &> 重定向指令。 该指令允许您告诉 shell 使一个流到达与另一个流相同的目的地。 在这种情况下,我们说“将流 2, stderr重定向到流 1, stdout被重定向到的同一目的地。”

没有可见的输出。 这是令人鼓舞的。

让我们检查一下 capture.txt 文件,看看里面有什么。

 猫捕获.txt 

stdoutstderr流都已重定向到单个目标文件。

要将流的输出重定向并静默丢弃,请将输出定向到/dev/null

检测脚本中的重定向

我们讨论了命令如何检测是否有任何流被重定向,并可以选择相应地改变其行为。 我们可以在自己的脚本中实现这一点吗? 我们可以。 这是一种非常容易理解和使用的技术。

广告

在编辑器中键入以下文本并将其保存为 input.sh。

 #!/bin/bash

如果 [ -t 0 ]; 然后

  来自键盘的 echo stdin
 
别的

  来自管道或文件的 echo 标准输入
 
菲

使用以下命令使其可执行:

 chmod +x 输入.sh

聪明的部分是方括号内的测试。 如果与文件描述符关联的文件在终端窗口中终止,则-t (终端)选项返回 true (0)。 我们使用文件描述符 0 作为测试的参数,它代表stdin

如果stdin连接到终端窗口,则测试将证明是正确的。 如果stdin连接到文件或管道,则测试将失败。

我们可以使用任何方便的文本文件来生成脚本的输入。 在这里,我们使用了一个名为 dummy.txt 的文件。

 ./input.sh < 虚拟.txt 

输出显示脚本识别出输入不是来自键盘,而是来自文件。 如果您选择这样做,您可以相应地改变脚本的行为。

广告

那是文件重定向,让我们用管道试试。

 猫假人.txt | ./input.sh 

该脚本识别出它的输入正在通过管道传递给它。 或者更准确地说,它再次识别出stdin流没有连接到终端窗口。

让我们在既不使用管道也不使用重定向的情况下运行脚本。

 ./input.sh 

stdin流连接到终端窗口,脚本会相应地报告这一点。

要检查输出流是否相同,我们需要一个新脚本。 在编辑器中输入以下内容并将其保存为 output.sh。

 #!/bin/bash

如果 [ -t 1 ]; 然后

echo stdout 将进入终端窗口
 
别的

echo stdout 正在被重定向或通过管道传输
 
菲

使用以下命令使其可执行:

 chmod +x 输入.sh

此脚本的唯一重大更改是方括号中的测试。 我们使用数字 1 来表示stdout的文件描述符。

让我们试试看。 我们将通过cat管道输出。

 ./输出 | 猫

广告

该脚本识别出它的输出不会直接进入终端窗口。

我们还可以通过将输出重定向到文件来测试脚本。

 ./output.sh > 捕获.txt 

终端窗口没有输出,我们默默地返回到命令提示符。 正如我们所料。

我们可以查看 capture.txt 文件以查看捕获的内容。 使用以下命令执行此操作。

 猫捕获.sh 

同样,我们脚本中的简单测试检测到stdout流没有直接发送到终端窗口。

广告

如果我们在没有任何管道或重定向的情况下运行脚本,它应该检测到stdout正在直接传递到终端窗口。

 ./output.sh 

这正是我们所看到的。

意识流

知道如何判断您的脚本是连接到终端窗口、管道还是被重定向,您可以相应地调整它们的行为。

日志和诊断输出可能或多或少详细,具体取决于它是进入屏幕还是进入文件。 错误消息可以记录到与正常程序输出不同的文件中。

通常情况下,更多的知识会带来更多的选择。

相关:适合开发人员和爱好者的最佳 Linux 笔记本电脑