What Are stdin, stdout, and stderr on Linux?

Terminal window on a Linux computerFatmawati Achmad Zaenuri / Shutterstock.com

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

Feeds join two points

As soon as you begin to become familiar with Linux and Unix operating systems, you will encounter the terms stdin, stdout, and stederr. These are three standard streams which are established when a Linux command is executed. In computing, a stream is something that can transfer data. In the case of these flows, these data are text.

Data flows, like water flows, have two ends. They have a source and an exit. Whichever Linux command you use provides one end of each stream. The other end is determined by the shell that launched the command. This end will be connected to the terminal window, connected to a pipe, or redirected to a file or other command, depending on the command line that initiated the command.

The standard Linux streams

On Linux, stdin is the standard input stream. This accepts the text as input. The text output from the command to the shell is passed via the stdout stream. Error messages from the command are sent via the stderr stream (standard error).

So you can see that there are two output streams, stdout and stderr, and an input stream, stdin. Because error messages and normal output each have their own leads to route them to the terminal window, they can be processed independently of each other.

Feeds are treated as files

Streams in Linux – like almost everything else – are treated as if it were files. You can read the text of a file and you can write it to a file. These two actions involve a data flow. Thus, the concept of managing a data stream as a file is not so exaggerated.

Each file associated with a process is assigned a unique number to identify it. This is known as the file descriptor. Whenever an action needs 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:

0: stdin
1: stdout
2: stderr

React to pipes and redirects

To facilitate the introduction of a person to a subject, a common technique is to teach a simplified version of the subject. For example, with grammar, we are told that the rule is "I before E, except after C." But in reality, he there are more exceptions to this rule that there are cases that obey him.

In the same vein, when we talk about stdin, stdout, and stderr, we need to find the accepted axiom that a process does not know or care about where its three standard streams are terminated. Should a process be concerned about whether its output goes to the terminal or is redirected to a file? Can he even know if his input comes from the keyboard or is routed to another process?

In fact, a process is aware – or at least he can know if he chooses to check it – and he can change his behavior accordingly if the author of the software decides to add this feature .

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

ls

ls in a terminal window

ls | cat

ls exit in a terminal window

The ls command behaves differently if its output (stdout) is transferred to another command. It is the one that switches to a single column output, it is not a conversion made by cat. And it does the same thing if its output is redirected:

ls> capture.txt

ls> capture.txt in a terminal window

cat capture.txt

cat capture.txt in a terminal window

Stdout and stderr redirection

It is advantageous to receive error messages by a dedicated stream. This means that we can redirect the output of a command (stdout) to a file while displaying any error messages (stderr) in the terminal window. You can react to errors if you need them. This also prevents error messages from contaminating the file in which stdout has been redirected.

Type the following text in an editor and save it to a file named error.sh.

#! / bin / bash

echo "About trying to access a file that does not exist"
cat bad-filename.txt

Make the script executable with this command:

chmod + x error.sh

The first line of the script returns the text to the terminal window, via the stdout stream. The second line tries to access a file that does not exist. This will generate an error message that will be sent via stderr.

Run the script with this command:

./error.sh

./error.sh in a terminal window

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

exit the 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 sent via stderr is always sent to the terminal window. We can check the contents of the file to see if the stdout output went into the file.

cat capture.txt

cat capture.txt in a terminal window

The stdin output has been redirected to the file as expected.

capture.txt content in a terminal window

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

To explicitly redirect stdout, use this redirect statement:

1>

To explicitly redirect stderr, use this redirect statement:

2>

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

./error.sh 2> capture.txt

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

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

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

Let's see what's in the capture.txt file.

cat capture.txt

cat capture.txt in a terminal window

The stderr message is in capture.txt as expected.

contents of the capture.txt file in a terminal window

Stdout and stderr redirection

If we can redirect stdout or stderr independently of one another, we should be able to redirect them simultaneously, to two different files.

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

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

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

Since both output streams (standard output and standard error) are redirected to files, no visible output is in the terminal window. We are returned to the command line prompt as if nothing had happened.

Output ./error.sh in a terminal window

Let's check the contents of each file:

cat capture.txt
cat error.txt

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

Stdout and stderr redirection to the same file

It's great, each of the standard output streams is directed to its own dedicated file. The only other combination we can do is to send stdout and stderr in the same file.

We can do this with the following command:

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

Let us break that down.

./error.sh: Launches the error.sh script file.
> capture.txt: redirects the stdout stream to the capture.txt file. > is a shortcut for 1>.
2> & 1: This uses the &> redirect statement. This statement allows you to tell the shell to create a stream at the same destination as another stream. In this case, we say "redirect stream 2, stderr, to the same destination as stream 1, stdout, is redirected to".

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

There is no visible exit. It's encouraging.

exit from ./error.sh in a terminal window

Let's see the capture.txt file and see what it contains.

cat capture.txt

capture.txt content in a terminal window

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

For the output of a stream to be redirected and discarded silently, direct the output to / dev / null.

Detection of redirection in a script

We explained how a command can detect if one of the streams is redirected and can choose to modify its behavior accordingly. Can we accomplish this in our own scripts? Yes we can. And it's a very easy technique to understand and use.

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

#! / bin / bash

if [ -t 0 ]; then

echo stdin coming from the keyboard

other

echo stdin coming from a pipe or from a file

Fi

Use the following command to make it executable:

chmod + x input.sh

The smart part is the test in square brackets. The -t (terminal) option returns true (0) if the file descriptor file ends in the terminal window. We used file descriptor 0 as the test argument, which represents stdin.

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

We can use any convenient text file to generate entries in the script. Here we use a file called dummy.txt.

./input.sh <dummy.txt

<img class = "full-size alignnone wp-image-436383" data-pagespeed-lazy-src = "https://www.howtogeek.com/wp-content/uploads/2019/08/26.png.pagespeed. ce.5XMrToSxQ5.png "alt =" ./ input.sh

The output shows that the script recognizes that the input does not come from a keyboard, but from a file. If you want, you can change the behavior of your script accordingly.

exit the script in a terminal window

It was with a file redirection, let's try with a tube.

dummy.txt chat | ./input.sh

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

The script recognizes that its entry is routed to it. Or more precisely, it recognizes once again that the stdin stream is not connected to a terminal window.

exit the script in a terminal window

Let's run the script without tubes or redirects.

./input.sh

./input.sh in a terminal window

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

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

#! / bin / bash

if [ -t 1 ]; then

echo stdout goes to the terminal window

other

echo stdout is redirected or redirected

Fi

Use the following command to make it executable:

chmod + x input.sh

The only significant change in this script is the square brackets test. We use the number 1 to represent the file descriptor for stdout.

Let's try it. We will route the output via cat.

./output | cat

./output | chat in a terminal window

The script recognizes that its output does not enter directly into 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 in the terminal window, we are silently returned to the command prompt. As we could expect.

script output in a terminal window

We can look inside the capture.txt file to see what has been captured. Use the following command to do this.

cat capture.sh

cat capture.sh in a terminal window

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

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

./output.sh

./output.sh in a terminal window

And that's exactly what we see.

script output in a terminal window

Currents of consciousness

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

The results of logging and diagnosis can be more or less detailed, depending on whether they go on screen or in a file. Error messages may be logged in a file different from the normal program output.

As usual, more knowledge brings more options.

Advertisements

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.