Linux上的stdin,stdout和stderr是什么?

Linux计算机上的终端窗口Fatmawati Achmad Zaenuri / Shutterstock.com

stdin,stdout和stderr是启动Linux命令时创建的三个数据流。您可以使用它们来判断脚本是通过管道传输还是重定向。我们告诉你如何。

Streams加入两点

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

数据流,如水流,有两个目的。他们有来源和外流。无论您使用哪种Linux命令,都会提供每个流的一端。另一端由启动命令的shell确定。根据启动命令的命令行,该端将连接到终端窗口,连接到管道,或重定向到文件或其他命令。

Linux标准流

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

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

流处理文件

Linux中几乎所有其他内容的流都被视为文件。您可以从文件中读取文本,也可以将文本写入文件。这两个动作都涉及数据流。因此,将数据流作为文件处理的概念并不是那么容易。

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

这些值始终用于stdin,stdout和stderr:

  • 0:stdin

  • 1:标准输出

  • 2:stderr

对管道和重定向做出反应

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

类似地,在讨论stdin,stdout和stderr时,可以方便地推出一个公认的过程,即一个过程既不知道也不关心其三个标准流的终止位置。进程是否应该关心其输出是转到终端还是重定向到文件中?它甚至可以判断它的输入是来自键盘还是从另一个进程输入?

实际上,如果软件作者决定添加该功能,那么一个进程确实知道 – 或者至少它可以找到它,如果它选择检查 – 它可以相应地改变它的行为。

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

LS

在终端窗口

ls |猫

ls在终端窗口中输出

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

ls> capture.txt

ls data-lazy-src=

cat capture.txt

cat capture.txt在终端窗口中

重定向stdout和stderr

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

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

#/斌/庆典

echo“关于尝试访问不存在的文件”
cat bad-filename.txt

使用此命令使脚本可执行:

chmod + x error.sh

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

使用以下命令运行脚本:

./error.sh

./error.sh在终端窗口中

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

在终端窗口中输出error.sh脚本

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

./error.sh> capture.txt

./error.sh data-lazy-src=

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

cat capture.txt

cat capture.txt在终端窗口中

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

终端窗口中capture.txt的内容

默认情况下,>重定向符号与stdout一起使用。您可以使用其中一个数字文件描述符来指示要重定向的标准输出流。

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

1>

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

2>

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

./error.sh 2> capture.txt

./error.sh 2 data-lazy-src=

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

在终端窗口中输出./error.sh 2 data-lazy-src=

让我们看看capture.txt文件中的内容。

cat capture.txt

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

终端窗口中capture.txt文件的内容

重定向stdout和stderr

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

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

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

终端窗口中的./error.sh 1 data-lazy-src=

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

./error.sh在终端窗口中输出

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

cat capture.txt

cat error.txt

终端窗口中的capture.txt和error.txt的内容

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

这很简洁,我们已经将每个标准输出流转到它自己的专用文件。我们可以做的唯一其他组合是将stdout和stderr发送到同一个文件。

我们可以使用以下命令实现此目的:

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

让我们打破它。

  • ./error.sh:启动error.sh脚本文件。

  • > capture.txt:将stdout流重定向到capture.txt文件。 >是1>的简写。

  • 2>&1:这使用&>重定向指令。此指令允许您告诉shell使一个流与另一个流到达同一目的地。在这种情况下,我们说“将流2,stderr重定向到流1,stdout被重定向到的同一目的地。”

./error.sh data-lazy-src=

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

终端窗口中输出./error.sh

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

cat capture.txt

终端窗口中capture.txt的内容

stdout和stderr流都已重定向到单个目标文件。

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

检测脚本中的重定向

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

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

#/斌/庆典

if(-t 0);然后

  来自键盘的echo stdin
 
其他

  echo stdin来自管道或文件
 
科幻

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

chmod + x input.sh

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

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

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

./input.sh

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

从终端窗口中的脚本输出

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

cat dummy.txt | ./input.sh

cat dummy.txt | ./input.sh在终端窗口中

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

终端窗口中的脚本输出

让我们运行脚本既不管道也不重定向。

./input.sh

./input.sh在终端窗口中

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

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

#/斌/庆典

if(-t 1);然后

echo stdout将进入终端窗口
 
其他

echo stdout正在被重定向或管道传输
 
科幻

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

chmod + x input.sh

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

我们来试试吧。我们将通过cat管道输出。

./output |猫

./output |猫在终端窗口

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

脚本输出在终端窗口中

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

./output.sh> capture.txt

./output.sh data-lazy-src=

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

脚本输出在终端窗口中

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

猫capture.sh

cat capture.sh在终端窗口中

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

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

./output.sh

./output.sh在终端窗口中

而这正是我们所看到的。

脚本输出在终端窗口中

意识流

知道如何判断脚本是否已连接到终端窗口,管道或正在重定向,您可以相应地调整其行为。

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

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

请阅读下一步

  • >如何申请Apple Card
  • >该原生应用程序可能只是一个旧的Web浏览器
  • >如何在Windows 10上的Internet Explorer中打开旧网页
  • >“Yeet”是什么意思,你如何使用它?
  • >如何在Windows 10上轻松创建桌面快捷方式

资讯来源:由0x资讯编译自HOWTOGEEK。版权归作者Dave McKay所有,未经许可,不得转载
提示:投资有风险,入市需谨慎,本资讯不作为投资理财建议。请理性投资,切实提高风险防范意识;如有发现的违法犯罪线索,可积极向有关部门举报反映。
你可能还喜欢