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 | Кот
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
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
We see that both output streams, stdout
and stderr
were displayed in the terminal windows.
Let’s try to redirect the output to a file:
./error.sh> capture.txt
Conclusion from stdin
was redirected to a file as expected.
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
Message stderr
is in capture.txt as expected.
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
Let’s check the contents of each file:
кошка capture.txt
cat error.txt
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 for1>
. - 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
«.
Let’s check the capture.txt file and see what’s in it.
кошка capture.txt
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
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.
It was with a file redirect, let’s try it with a pipe.
кот dummy.txt | ./input.sh
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.
Let’s run the script without channels and redirects.
./input.sh
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: