Fatmawati Ahmad Zaenuri / Shutterstock.com

stdin , stdout and stderr are the three data streams created when the Linux command was run. You can use them to find out if your scripts are being piped or redirected. We’ll show you how.

Flows join two points

Once you start learning Linux and Unix-like operating systems, you will come across terms stdin , stdout and stederr . These are the three standard streams that are set when a Linux command is executed. In computing, a stream is something that can transfer data. In the case of these streams, this data is textual.

Data streams, like water streams, have two ends. They have a source and an outflow. Whichever Linux command you use, it provides one end to each thread. The other end is determined by the shell that ran the command. This end will be linked to a terminal window, connected to a pipe, or redirected to a file or other command, according to the command line that launched the command.

Standard Linux Threads

On Linux, standard input is standard input. This takes text as input. The output of text from the command to the shell is carried out through the stream stdout (standard out). Error messages from a command are sent via a stream stderr (standard error).

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

Streams are treated like files

Streams in Linux — like pretty much everything else — are treated like files. You can read text from a file, and you can write text to a file. Both of these activities are related to data flow. Thus, the concept of processing a data stream as a file is not that difficult.

Each file associated with a process is assigned a unique number to identify it. This is called a file descriptor. Whenever an action is required on a file, the file descriptor is used to identify the file.

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

  • 0 : standard
  • one : standard output
  • 2 : stderr

React pipes and redirects

To facilitate someone’s familiarity with the subject, a common method is to teach a simplified version of the topic. For example, in grammar we are told that the rule is «I before E except C». But in fact, there are more exceptions to this rule than cases that obey it.

Similarly, when it comes to stdin , stdout and stderr it is convenient to advance the accepted axiom that a process does not know or care where its three standard threads terminate. Should the process care if its output goes to the terminal or is redirected to a file? Can it even tell if its input is coming from the keyboard or is being fed into it from another process?

In fact, the process knows — or at least can know if it will choose to check — and can change its behavior accordingly if the software author decides to add this feature.

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

  Ls 

ls in a terminal window

  ls |  Кот 

output to terminal window

Team ls behaves differently if its output ( stdout ) is passed to another team. Exactly ls switches to single column output, this is not a conversion performed cat . And ls does the same if its output is redirected:

  ls> capture.txt 

ls> capture.txt in terminal window» width=»646″ height=»57″ src=»https://gadgetshelp.com/wp-content/uploads/images/htg/content/uploads/2019/08/x41.png.pagespeed.gp+jp+jw+pj+ws+js+rj+rp+rw+ ri+cp+md.ic.hyUFiptU3o.png»></p>
<p><noscript><img class=

Redirecting stdout and stderr

There is an advantage that error messages are delivered on a dedicated thread. This means that we can redirect the output of a command ( stdout ) to the file and still see any error messages ( stderr ) in a terminal window. You can react to errors if you need to, as they occur. It also prevents the error messages from polluting the file to which the standard was redirected. stdout .

Enter the following text into the editor and save it to a file named error.sh.

  #! / Bin / Баш

 echo "О попытке получить доступ к файлу, который не существует"
 cat bad-filename.txt 

Make the script executable with this command:

  chmod + x error.sh 

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

Run the script with this command:

  ./error.sh 

./error.sh in terminal window

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

output from error.sh script in terminal window

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

  ./error.sh> capture.txt 

./error.sh> capture.txt in terminal window» width=»646″ height=»57″ src=»https://gadgetshelp.com/wp-content/uploads/images/htg/content/uploads/2019/08/x3.png.pagespeed.gp+jp+jw+pj+ws+js+rj+rp+rw+ ri+cp+md.ic.EqpbNlGg0r.png»></p>
<p><noscript><img class=

Conclusion from stdin was redirected to a file as expected.

contents of capture.txt in terminal window

redirect symbol > work with stdout default. You can use one of the numeric file descriptors to specify which standard output you want to redirect.

To explicitly redirect the standard 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 terminal window» width=»646″ height=»57″ src=»https://gadgetshelp.com/wp-content/uploads/images/htg/content/uploads/2019/08/x17.png.pagespeed.gp+jp+jw+pj+ws+js+rj+rp+rw+ ri+cp+md.ic.JgI_SRjATy.png»></p>
<p><noscript><img class=

Message stderr is in capture.txt as expected.

content of capture.txt file in terminal window

Redirecting both stdout and stderr

Of course, if we can redirect either stdout or stderr to a file independently, should we be able to redirect them simultaneously to two different files?

Yes we can. This command will send a standard stdout to a file called capture.txt, and the standard stderr — to a file named error.txt.

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

./error.sh 1> capture.txt 2> error.txt in a terminal window» width=»646″ height=»57″ src=»https://gadgetshelp.com/wp-content/uploads/images/htg/content/uploads/2019/08/x20.png.pagespeed.gp+jp+jw+pj+ws+js+rj+rp+rw+ ri+cp+md.ic.tfJGMMFL3p.png»></p>
<p><noscript><img class=

Let’s check the contents of each file:

  кошка capture.txt 
  cat error.txt 

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

Redirecting stdout and stderr to the same file

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

We can achieve this with the following command:

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

Let’s deal with this.

  • ./error.sh : runs the script file error.sh.
  • > capture.txt : redirects the stream stdout to capture.txt file. > is an abbreviation for 1> .
  • 2>&1 : The &> redirection instruction is used here. This instruction allows you to tell the shell to send one thread to the same destination as another thread. In this case, we say «redirect stream 2, stderr to the same location where stream 1 is redirected, stdout «.

./error.sh> capture.txt 2 &> 1 in terminal window» width=»646″ height=»57″ src=»https://gadgetshelp.com/wp-content/uploads/images/htg/content/uploads/2019/08/x23.png.pagespeed.gp+jp+jw+pj+ws+js+rj+rp+rw+ ri+cp+md.ic.E9Im1_c4LS.png»></p>
<p><noscript><img class=

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

  кошка capture.txt 

contents of capture.txt in terminal window

streams stdout and stderr were redirected to a single destination file.

To redirect the output of a data stream and silently discard it, pipe the output to /dev/null .

Redirect detection in script

We discussed how a command can detect if any of the streams are being redirected and can change its behavior accordingly. Can we do this in our own scripts? Yes we can. And it is a very simple technique to understand and apply.

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

  #! / Bin / Баш

 если [-t 0];  тогда

   эхо ввода с клавиатуры
 
 еще

   эхо стандартного ввода из трубы или файла
 
 фи 

Use the following command to make it executable:

  chmod + x input.sh 

The smart part is the check in square brackets. Option -t (terminal) returns true (0) if the file associated with the file descriptor ends in a terminal window. We have used file descriptor 0 as the test argument, which represents the standard stdin .

If a stdin connected to a terminal window, the test will be confirmed. If a stdin connected to a file or pipe, the test failed.

We can use any convenient text file to generate input to the script. Here we are using a file called dummy.txt.

  ./input.sh  

./input.sh <dummy.txt в окне терминала

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

output from a script in a terminal window

It was with a file redirect, let’s try it with a pipe.

  кот dummy.txt |  ./input.sh 

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

The script recognizes that its input is being piped. More precisely, he once again recognizes that the flow stdin not connected to a terminal window.

script output in terminal window

Let’s run the script without channels and redirects.

  ./input.sh 

./input.sh in terminal window

Flow stdin connected to the terminal window and the script reports it accordingly.

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

  #! / Bin / Баш

 если [-t 1];  тогда

 echo stdout собирается в окно терминала
 
 еще

 echo stdout перенаправляется или передается по каналу
 
 фи 

Use the following command to make it executable:

  chmod + x input.sh 

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

Let’s try this. We will pass the output through cat .

  ./output |  Кот 

./output |  cat in terminal window

The script recognizes that its output does not go directly to the terminal window.

script output in terminal window

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

  ./output.sh> capture.txt 

./output.sh> capture.txt in terminal window» width=»646″ height=»57″ src=»https://gadgetshelp.com/wp-content/uploads/images/htg/content/uploads/2019/08/x34.png.pagespeed.gp+jp+jw+pj+ws+js+rj+rp+rw+ ri+cp+md.ic.df5fttcFac.png»></p>
<p><noscript><img class=

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

  кошка захват.ш 

cat capture.sh in terminal window

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

If we run the script without any pipes or redirects, it should find that the standard stdout delivered directly to the terminal window.

  ./output.sh 

./output.sh in terminal window

And that’s exactly what we see.

script output in terminal window

Streams of Consciousness

Knowing how to determine if your scripts are connected to a terminal window, a channel, or redirected allows you to customize their behavior accordingly.

Logging and diagnostic output can be more or less verbose, depending on whether it’s a screen or a file. Error messages may be written to a file other than the program’s normal output.

As usual, more knowledge brings more options.

Похожие записи