stdin、stdout和stderr是在启动Linux命令时创建的三个数据流。您可以使用它们来判断您的脚本是被管道传输还是被重定向。我们教你怎么做。
一旦您开始学习Linux和类Unix操作系统,就会遇到stdin、stdout和stederr这些术语。这是在执行Linux命令时建立的三个标准流。在计算中,流是可以传输数据的东西。对于这些流,该数据是文本。
数据流和水流一样,有两端。它们有一个来源和一个流出。无论您使用哪个Linux命令,都会提供每个流的一端。另一端由启动命令的shell决定。根据启动命令的命令行,该端将连接到终端窗口、连接到管道或重定向到文件或其他命令。
在Linux中,stdin是标准的输入流。它接受文本作为输入。从命令到shell的文本输出通过stdout(标准输出)流传递。来自命令的错误消息通过stderr(标准错误)流发送。
所以您可以看到有两个输出流,stdout和stderr,以及一个输入流stdin。因为错误消息和正常输出都有自己的管道将它们传输到终端窗口,所以它们可以彼此独立地处理。
Linux中的流和其他几乎所有东西一样,都被当作文件来对待。可以从文件中读取文本,也可以将文本写入文件。这两个动作都涉及一个数据流。因此,将数据流作为文件进行处理的概念并不是那么简单。
与进程关联的每个文件都分配了一个唯一的编号来标识它。这称为文件描述符。每当需要对文件执行操作时,都会使用文件描述符来标识文件。
这些值始终用于stdin、stdout和stderr:
为了便于某人对某一主题的介绍,一种常见的技巧是教授该主题的简化版本。例如,关于语法,我们被告知规则是“E之前的I,C之后的除外”。但实际上,这个规则的例外情况比遵守它的情况要多。
同样,在讨论stdin、stdout和stderr时,可以方便地提出一个公认的公理,即进程既不知道也不关心它的三个标准流在哪里终止。进程是否应该关心其输出是发送到终端还是被重定向到文件中?它甚至能分辨出它的输入是来自键盘还是从另一个进程传入的吗?
实际上,一个进程确实知道或者至少它可以发现,如果它选择检查,并且如果软件作者决定添加这个功能,它可以相应地改变它的行为。
我们可以很容易地看到这种行为的变化。请尝试以下两个命令:
lsls | cat如果ls命令的输出(stdout)通过管道传输到另一个命令中,则ls命令的行为不同。切换到单列输出的是ls,而不是cat执行的转换。如果ls的输出被重定向,它也会执行相同的操作:
ls > capture.txtcat capture.txt由专用流传递错误消息有一个好处。这意味着我们可以将命令的输出(stdout)重定向到一个文件,并且仍然可以在终端窗口中看到任何错误消息(stderr)。如果需要,您可以在错误发生时对其作出反应。它还阻止错误消息污染stdout重定向到的文件。
在编辑器中键入以下文本并将其保存到名为错误.sh.
#!/bin/bash echo "About to try to access a file that doesn't exist" cat bad-filename.txt使用以下命令使脚本可执行:
chmod +x error.sh脚本的第一行通过stdout流将文本回显到终端窗口。第二行尝试访问不存在的文件。这将生成通过stderr传递的错误消息。
使用以下命令运行脚本:
./error.sh我们可以看到输出流stdout和stderr都显示在终端窗口中。
让我们尝试将输出重定向到一个文件:
./error.sh > capture.txt通过stderr传递的错误消息仍然发送到终端窗口。我们可以检查文件的内容,看看stdout输出是否进入了该文件。
cat capture.txtstdin的输出按预期重定向到文件。
默认情况下,>;重定向符号与标准输出一起工作。可以使用其中一个数字文件描述符来指示要重定向的标准输出流。
要显式重定向stdout,请使用以下重定向指令:
1>要显式重定向stderr,请使用以下重定向指令:
2>让我们再次尝试测试,这次我们将使用2>;:
./error.sh 2> capture.txt错误消息被重定向,标准输出回显消息被发送到终端窗口:
让我们看看里面有什么捕获.txt文件。
cat capture.txtstderr消息在捕获.txt一如预期。
当然,如果我们可以将stdout或stderr重定向到一个彼此独立的文件,我们应该能够同时将它们重定向到两个不同的文件?
是的,我们可以。此命令将stdout指向一个名为捕获.txt和一个名为错误表.
./error.sh 1> capture.txt 2> error.txt因为输出流–标准输出和标准错误都被重定向到文件,所以终端窗口中没有可见的输出。我们返回到命令行提示符,好像什么都没有发生。
让我们检查每个文件的内容:
cat capture.txt cat error.txt这很好,我们将每个标准输出流都放到了自己的专用文件中。我们唯一能做的其他组合是将stdout和stderr发送到同一个文件。
我们可以通过以下命令来实现这一点:
./error.sh > capture.txt 2>&1我们把它分解一下。
没有可见的输出。这是令人鼓舞的。
让我们检查一下捕获.txt归档看看里面有什么。
cat capture.txtstdout和stderr流都已重定向到单个目标文件。
要重定向流的输出并将其静默地丢弃,请将输出定向到/dev/null。
我们讨论了命令如何检测是否有任何流被重定向,以及如何选择相应地改变其行为。我们能用自己的脚本来完成吗?是的,我们可以。这是一个很容易理解和运用的技巧。
在编辑器中键入以下文本并将其另存为输入.sh.
#!/bin/bash if [ -t 0 ]; then echo stdin coming from keyboard else echo stdin coming from a pipe or a file fi使用以下命令使其可执行:
chmod +x input.sh聪明的部分是方括号内的测试。如果与文件描述符关联的文件在终端窗口中终止,-t(terminal)选项将返回true(0)。我们使用文件描述符0作为测试的参数,它表示stdin。
如果stdin连接到终端窗口,测试将被证明是正确的。如果stdin连接到文件或管道,测试将失败。
我们可以使用任何方便的文本文件来生成脚本的输入。我们用的是一个叫做虚拟.txt.
./input.sh < dummy.txt输出显示脚本识别出输入不是来自键盘,而是来自文件。如果您选择这样做,您可以相应地改变脚本的行为。
那是一个文件重定向,让我们用管道试试。
cat dummy.txt | ./input.sh脚本识别出它的输入正在通过管道传输到其中。或者更准确地说,它再次识别stdin流没有连接到终端窗口。
让我们既不使用管道也不使用重定向来运行脚本。
./input.shstdin流连接到终端窗口,脚本相应地报告这一点。
为了在输出流中检查同样的内容,我们需要一个新的脚本。在编辑器中键入以下内容并将其另存为输出.sh.
#!/bin/bash if [ -t 1 ]; then echo stdout is going to the terminal window else echo stdout is being redirected or piped fi使用以下命令使其可执行:
chmod +x input.sh这个脚本唯一重要的变化是方括号中的测试。我们使用数字1来表示stdout的文件描述符。
让我们试试看。我们将通过cat传输输出。
./output | cat脚本识别出它的输出不会直接发送到终端窗口。
我们还可以通过将输出重定向到文件来测试脚本。
./output.sh > capture.txt没有输出到终端窗口,我们将静默地返回到命令提示符。如我们所料。
我们可以看看里面捕获.txt查看捕获的内容。使用以下命令执行此操作。
cat capture.sh同样,我们脚本中的简单测试检测到stdout流没有被直接发送到终端窗口。
如果我们在没有任何管道或重定向的情况下运行脚本,它应该会检测到stdout正被直接传递到终端窗口。
./output.sh这正是我们看到的。
知道如何判断脚本是否连接到终端窗口、管道或正在重定向,可以相应地调整它们的行为。
日志记录和诊断输出可以更详细,也可以更详细,这取决于它是进入屏幕还是进入文件。错误消息可以记录到与正常程序输出不同的文件中。
通常情况下,更多的知识带来更多的选择。
...讨论这两个函数之间的区别。 目录 1. 概述和主要区别 2. 什么是getc 3. 什么是getchar 4. getc和getchar的相似性 5. 并列比较-表格形式的getc与getchar 6. 摘要 什么是getc公司(getc)? 它是一个函数,用于从输入流(如文件或键盘)中读取字...
...用johnnyfive文档中提供的一段示例代码,它允许使用键盘上的箭头键控制伺服。完整的代码可在约翰尼-五.io,但我们将在这里详细介绍,以充分了解它的工作原理。 ...
...这是标记,表示标记中的标题。数字符号(#)必须是行上的第一个字符,后跟空格。 name部分包含一个快捷的单行,其中包括命令的名称、空格、连字符(-)、空格,然后是命令所做的非常简短的描述。 简介 概要包含命令行可...
...所以在大多数情况下,您不会收到电子邮件。 相关:Linux上的stdin、stdout和stderr是什么? 现在,是时候在中键入命令了。对于本例,我们将使用一个名为扫描.sh删除*.bak、*.tmp和*.o文件。键入命令的路径,如下所示,然后按Enter键...
...我们日期戳和时间戳都添加到了日志文件中。 相关:Linux上的stdin、stdout和stderr是什么? 那是echo的剧目 一个简单的命令,但不可或缺。如果它不存在,我们就得发明它。 毕竟,宙斯的恶作剧有一些好处。
...法: wc doesntexist.txt 2> errors.txt cat errors.txt 相关:Linux上的stdin、stdout和stderr是什么? |管道 “管道”将命令链接在一起。它接受一个命令的输出并将其作为输入提供给下一个命令。管道命令的数量(链的长度)是任意的。 在...
...捕获常规输出(stdin)和错误消息(stderr)。 相关:Linux上的stdin、stdout和stderr是什么? 命令可以包含环境变量。以下命令将列出主目录的内容: ls $HOME 这在目录树中的任何位置都有效。 如果所有这些输入的想法仍然困扰着你...
...联的数据流。它们是标准输入流(stdin)、标准输出流(stdout)和标准错误流(stderr)。 这些流处理文本。我们使用文本向命令发送输入(stdin),响应(stdout)作为文本写入终端窗口。错误消息也作为文本(stderr)写入终端窗...
...件名)。 注意,我们使用-作为文件名,这会导致tar使用stdout,并将其输出写入终端窗口。我们看不到这个输出,因为它是通过pv管道传输的。 归档文件的实际名称将是我们将pv的输出导入的文件名。在这种情况下,它是“帮助...
...像拨号上网发出的刺耳声音一样,那么,如今cat还能做些什么呢?实际上很多。 显示文本文件 要让cat在终端窗口中列出文本文件的内容,请使用以下命令。 确保该文件是文本文件。如果您试图在终端窗口中列出二进制文件的内...