Terminal window on a Linux computer
Fatmawati Achmad Zaenuri/Shutterstock.com Fatmawati Achmad Zaenuri / Shutterstock.com

stdin, stdout, and stderr are three data streams created when you launch a Linux command. You can use them to tell if your scripts are being piped or redirected. We show you how.

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

流连接两点 (Streams Join Two Points)

As soon as you start to learn about Linux and Unix-like operating systems, you’ll come across the terms stdin, stdout, and stederr. These are three standard streams that are established when a Linux command is executed. In computing, a stream is something that can transfer data. In the case of these streams, that data is text.

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

Data streams, like water streams, have two ends. They have a source and an outflow. Whichever Linux command you’re using provides one end of each stream. The other end is determined by the shell that launched the command. That end will be connected to the terminal window, connected to a pipe, or redirected to a file or other command, according to the command line that launched the command.

数据流就像水流一样,有两个末端。 他们有一个来源和一个流出。 您所使用的任何Linux命令都提供每个流的一端。 另一端由启动命令的外壳程序确定。 根据启动命令的命令行,该端将连接到终端窗口,连接到管道或重定向到文件或其他命令。

Linux标准流 (The Linux Standard Streams)

In Linux, stdin is the standard input stream. This accepts text as its input. Text output from the command to the shell is delivered via the stdout (standard out) stream. Error messages from the command are sent through the stderr (standard error) stream.

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

So you can see that there are two output streams, stdout and stderr, and one input stream, stdin. Because error messages and normal output each have their own conduit to carry them to the terminal window, they can be handled independently of one another.

因此,您可以看到有两个输出流stdoutstderr ,以及一个输入流stdin 。 由于错误消息和正常输出各自具有将其携带到终端窗口的管道,因此可以彼此独立地进行处理。

流像文件一样处理 (Streams Are Handled Like Files)

Streams in Linux—like almost everything else—are treated as though they were files. You can read text from a file, and you can write text into a file. Both of these actions involve a stream of data. So the concept of handling a stream of data as a file isn’t that much of a stretch.

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

Each file associated with a process is allocated a unique number to identify it. This is known as the file descriptor. Whenever an action is required to be performed on a file, the file descriptor is used to identify the file.

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

These values are always used for stdin, stdout, and stderr:

这些值始终用于stdinstdout,stderr

  • 0: stdin

    0 :标准输入

  • 1: stdout

    1 :标准输出

  • 2: stderr

    2 :标准错误

对管道和重定向做出React (Reacting to Pipes and Redirects)

To ease someone’s introduction to a subject, a common technique is to teach a simplified version of the topic. For example, with grammar, we are told that the rule is “I before E, except after C.” But actually, there are more exceptions to this rule than there are cases that obey it.

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

In a similar vein, when talking about stdin, stdout, and stderr it is convenient to trot out the accepted axiom that a process neither knows nor cares where its three standard streams are terminated. Should a process care whether its output is going to the terminal or being redirected into a file? Can it even tell if its input is coming from the keyboard or is being piped into it from another process?

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

Actually, a process does know—or at least it can find out, should it choose to check—and it can change its behavior accordingly if the software author decided to add that functionality.

实际上,如果软件作者决定添加该功能,则该过程确实知道(或者至少可以找到,应该选择检查),并且可以相应地更改其行为。

We can see this change in behavior very easily. Try these two commands:

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

ls
ls in a terminal window
ls | cat
ls output in a terminal window

The ls command behaves differently if its output (stdout) is being piped into another command. It is ls that switches to a single column output, it isn’t a conversion performed by cat. And ls does the same thing if its output is being redirected:

如果将其输出( stdout )传递到另一个命令中,则ls命令的行为会有所不同。 是ls切换到单列输出,而不是cat进行的转换。 如果重定向其输出,则ls执行相同的操作:

ls > capture.txt
ls > capture.txt in a terminal window
cat capture.txt
cat capture.txt in a terminal window

重定向标准输出和标准错误 (Redirecting stdout and stderr)

There’s an advantage to having error messages delivered by a dedicated stream. It means we can redirect a command’s output (stdout) to a file and still see any error messages (stderr) in the terminal window. You can react to the errors if you need to, as they occur. It also stops the error messages from contaminating the file that stdout has been redirected into.

通过专用流传递错误消息有一个优势。 这意味着我们可以将命令的输出( stdout )重定向到文件,并且仍然可以在终端窗口中看到任何错误消息( stderr )。 您可以根据需要对错误进行处理,以防发生错误。 它还可以防止错误消息污染已将stdout重定向到的文件。

Type the following text into an editor and save it to a file called error.sh.

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

#!/bin/bash

echo "About to try to access a file that doesn't exist"
cat bad-filename.txt

Make the script executable with this command:

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

chmod +x error.sh

The first line of the script echoes text to the terminal window, via the stdout stream. The second line tries to access a file that doesn’t exist. This will generate an error message that is delivered via stderr.

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

Run the script with this command:

使用以下命令运行脚本:

./error.sh
./error.sh in a terminal window

We can see that both streams of output, stdout and stderr, have been displayed in the terminal windows.

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

output from error.sh script in a terminal window

Let’s try to redirect the output to a file:

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

./error.sh > capture.txt
./error.sh > capture.txt in a terminal window

The error message that is delivered via stderr is still sent to the terminal window. We can check the contents of the file to see whether the stdout output went to the file.

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

cat capture.txt
cat capture.txt in a terminal window

The output from stdin was redirected to the file as expected.

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

contents of capture.txt in a terminal window

The > redirection symbol works with stdout by default. You can use one of the numeric file descriptors to indicate which standard output stream you wish to redirect.

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

To explicitly redirect  stdout, use this redirection instruction:

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

1>

To explicitly redirect  stderr, use this redirection instruction:

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

2>

Let’s try to our test again, and this time we’ll use 2>:

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

./error.sh 2> capture.txt
./error.sh 2> capture.txt in a terminal window

The error message is redirected and the stdout echo message is sent to the terminal window:

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

output from ./error.sh 2> capture.txt in a terminal window

Let’s see what is in the capture.txt file.

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

cat capture.txt
cat capture.txt in a terminal window

The stderr message is in capture.txt as expected.

如预期的那样, stderr消息位于capture.txt中。

contents of capture.txt file in a terminal window

重定向stdout和stderr (Redirecting Both stdout and stderr)

Surely, if we can redirect either stdout or stderr to a file independently of one another, we ought to be able to redirect them both at the same time, to two different files?

当然,如果我们可以将stdoutstderr相互重定向到一个文件,那么我们应该能够同时将它们重定向到两个不同的文件吗?

Yes, we can. This command will direct stdout to a file called capture.txt and stderr to a file called error.txt.

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

./error.sh 1> capture.txt 2> error.txt
./error.sh 1> capture.txt 2> error.txt in a terminal window

Because both streams of output–standard output and standard error—are redirected to files, there is no visible output in the terminal window. We are returned to the command line prompt as though nothing has occurred.

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

./error.sh output in a terminal window

Let’s check the contents of each file:

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

cat capture.txt
cat error.txt
contents of capture.txt and error.txt in a terminal window

将stdout和stderr重定向到同一文件 (Redirecting stdout and stderr to the Same File)

That’s neat, we’ve got each of the standard output streams going to its own dedicated file. The only other combination we can do is to send both stdout and stderr to the same file.

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

We can achieve this with the following command:

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

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

Let’s break that down.

让我们分解一下。

  • ./error.sh: Launches the error.sh script file.

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

  • > capture.txt: Redirects the stdout stream to the capture.txt file. > is shorthand for 1>.

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

  • 2>&1: This uses the &> redirect instruction. This instruction allows you to tell the shell to make one stream got to the same destination as another stream. In this case, we’re saying “redirect stream 2, stderr, to the same destination that stream 1, stdout, is being redirected to.”

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

./error.sh > capture.txt 2&>1 in a terminal window

There is no visible output. That’s encouraging.

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

output of ./error.sh in a terminal window

Let’s check the capture.txt file and see what’s in it.

让我们检查capture.txt文件并查看其中的内容。

cat capture.txt
contents of capture.txt in a terminal window

Both the stdout and stderr streams have been redirected to a single destination file.

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

To have the output of a stream redirected and silently thrown away, direct the output to /dev/null.

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

在脚本中检测重定向 (Detecting Redirection Within a Script)

We discussed how a command can detect if any of the streams are being redirected, and can choose to alter its behavior accordingly. Can we accomplish this in our own scripts? Yes, we can. And it is a very easy technique to understand and employ.

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

Type the following text into an editor and save it as input.sh.

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

#!/bin/bash

if [ -t 0 ]; then

  echo stdin coming from keyboard
 
else

  echo stdin coming from a pipe or a file
 
fi

Use the following command to make it executable:

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

chmod +x input.sh

The clever part is the test within the square brackets. The -t (terminal) option returns true (0) if the file associated with the file descriptor terminates in the terminal window. We’ve used the file descriptor 0 as the argument to the test, which represents  stdin.

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

If stdin is connected to a terminal window the test will prove true. If stdin is connected to a file or a pipe, the test will fail.

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

We can use any convenient text file to generate input to the script. Here we’re using one called dummy.txt.

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

./input.sh < dummy.txt
./input.sh < dummy.txt in a terminal window

The output shows that the script recognizes that the input isn’t coming from a keyboard, it is coming from a file. If you chose to, you could vary your script’s behavior accordingly.

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

output from script in a terminal window

That was with a file redirection, let’s try it with a pipe.

那是与文件重定向有关的,让我们通过管道进行尝试。

cat dummy.txt | ./input.sh
cat dummy.txt | ./input.sh in a terminal window

The script recognizes that its input is being piped into it. Or more precisely, it recognizes once more that the stdin stream is not connected to a terminal window.

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

output of script in a terminal window

Let’s run the script with neither pipes nor redirects.

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

./input.sh
./input.sh in a terminal window

The stdin stream is connected to the terminal window, and the script reports this accordingly.

stdin流已连接到终端窗口,脚本相应地对此进行报告。

To check the same thing with the output stream, we need a new script. Type the following into an editor and save it as output.sh.

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

#!/bin/bash

if [ -t 1 ]; then

echo stdout is going to the terminal window
 
else

echo stdout is being redirected or piped
 
fi

Use the following command to make it executable:

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

chmod +x input.sh

The only significant change to this script is in the test in the square brackets. We’re using the digit 1 to represent the file descriptor for stdout.

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

Let’s try it out. We’ll pipe the output through cat.

让我们尝试一下。 我们将通过cat传递输出。

./output | cat
./output | cat in a terminal window

The script recognizes that its output is no going directly to a terminal window.

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

script output in a terminal window

We can also test the script by redirecting the output to a file.

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

./output.sh > capture.txt
./output.sh > capture.txt in a terminal window

There is no output to the terminal window, we are silently returned to the command prompt. As we’d expect.

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

script output in a terminal window

We can look inside the capture.txt file to see what was captured. Use the following command to do so.

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

cat capture.sh
cat capture.sh in a terminal window

Again, the simple test in our script detects that the stdout stream is not being sent directly to a terminal window.

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

If we run the script without any pipes or redirections, it should detect that stdout is being delivered directly to the terminal window.

如果我们运行脚本时没有任何管道或重定向,它应该检测到stdout是否直接传递到终端窗口。

./output.sh
./output.sh in a terminal window

And that’s exactly what we see.

这就是我们所看到的。

script output in a terminal window

意识流 (Streams Of Consciousness)

Knowing how to tell if your scripts are connected to the terminal window, or a pipe, or are being redirected, allows you to adjust their behavior accordingly.

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

Logging and diagnostic output can be more or less detailed, depending on whether it is going to the screen or to a file. Error messages can be logged to a different file than the normal program output.

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

As is usually the case, more knowledge brings more options.

通常,更多的知识带来更多的选择。

翻译自: https://www.howtogeek.com/435903/what-are-stdin-stdout-and-stderr-on-linux/

Logo

更多推荐