Linux上的stdin,stdout和stderr是什么?
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命令的输出(stdout)传送到另一个命令,则ls命令的行为会有所不同。它是ls切换到单列输出,它不是cat执行的转换。如果输出被重定向,ls会做同样的事情:
ls> 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
我们可以看到两个输出流stdout和stderr都已显示在终端窗口中。
让我们尝试将输出重定向到文件:
./error.sh> capture.txt
通过stderr传递的错误消息仍会发送到终端窗口。我们可以检查文件的内容,看看stdout输出是否转到了文件。
cat capture.txt
stdin的输出按预期重定向到文件。
默认情况下,>重定向符号与stdout一起使用。您可以使用其中一个数字文件描述符来指示要重定向的标准输出流。
要显式重定向stdout,请使用此重定向指令:
1>
要显式重定向stderr,请使用此重定向指令:
2>
让我们再次尝试我们的测试,这次我们将使用2>:
./error.sh 2> capture.txt
重定向错误消息,并将stdout echo消息发送到终端窗口:
让我们看看capture.txt文件中的内容。
cat capture.txt
stderr消息按预期在capture.txt中。
重定向stdout和stderr
当然,如果我们可以将stdout或stderr重定向到彼此独立的文件,我们应该能够将它们同时重定向到两个不同的文件吗?
我们可以。此命令将stdout指向名为capture.txt的文件,将stderr指向名为error.txt的文件。
./error.sh 1> capture.txt 2> error.txt
由于输出标准输出和标准错误的两个流都被重定向到文件,因此终端窗口中没有可见的输出。我们返回到命令行提示符,好像什么都没发生一样。
让我们检查每个文件的内容:
cat capture.txt
cat 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被重定向到的同一目的地。”
没有可见的输出。这令人鼓舞。
让我们检查一下capture.txt文件,看看里面有什么。
cat 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 该脚本识别出其输入正在通过管道输入。或者更准确地说,它再次识别出stdin流没有连接到终端窗口。 让我们运行脚本既不管道也不重定向。 ./input.sh stdin流连接到终端窗口,脚本相应地报告。 要使用输出流检查相同的内容,我们需要一个新脚本。在编辑器中键入以下内容并将其另存为output.sh。 #/斌/庆典 if(-t 1);然后 echo stdout将进入终端窗口 echo stdout正在被重定向或管道传输 使用以下命令使其可执行: chmod + x input.sh 对此脚本的唯一重大更改是在方括号中的测试中。我们使用数字1来表示stdout的文件描述符。 我们来试试吧。我们将通过cat管道输出。 ./output |猫 该脚本识别出其输出不会直接进入终端窗口。 我们还可以通过将输出重定向到文件来测试脚本。 ./output.sh> capture.txt 终端窗口没有输出,我们默默地返回到命令提示符。正如我们所期望的那样。 我们可以查看capture.txt文件以查看捕获的内容。使用以下命令执行此操作。 猫capture.sh 同样,我们脚本中的简单测试检测到stdout流没有直接发送到终端窗口。 如果我们在没有任何管道或重定向的情况下运行脚本,它应该检测到stdout正在直接传递到终端窗口。 ./output.sh 而这正是我们所看到的。 意识流 知道如何判断脚本是否已连接到终端窗口,管道或正在重定向,您可以相应地调整其行为。 记录和诊断输出可以或多或少地详细,具体取决于它是进入屏幕还是文件。错误消息可以记录到与正常程序输出不同的文件中。 通常情况下,更多知识带来更多选择。 请阅读下一步
其他
科幻