Input, Output, redirections and PIPEs.
Every program in Linux can get, process and finally output some data. Among others, data sources could be files or pipes.
For example, command cat /etc/passwd uses file /etc/passwd as it’s data source and our terminal screen is used as an output destination also known as standard output (stdout). Also, programs may produce error messages which are also printed out in our terminal screen but via another channel, known as standard error (stderr).
One program’s output (stdout/stderr) could be transferred to another program’s standard input (stdin) for further processing.
Particularly, any program has two different outputs: stdout and stderr and one input channel: standard input (stdin)
It is possible to redirect stdout of a command to a file using > (greater-than) sign. And the opposite, get file contents to command’s standard input (stdin) by using < (less-than) sign.
cat /etc/passwd > /tmp/outputdata instead of printing file contents on our terminal screen, we redirect stdout to the file /tmp/outputdata, as result it will create a destination file with stdout’s contents.
As opposite example:
base64 < /etc/passwd as result /etc/passwd contents are redirected to the stdin of base64 command.
All these streams stdin, stdout, stderr have appropriate file descriptor numbers, which could be used in specific channel redirection.
stdin = 0
stdout = 1
stderr = 2
Let’s produce some error message:
After issuing this command we will see an error on our terminal screen:
id: ‘nosuchuser’: no such user
If we’ll execute id nosuchuser > /tmp/outputdata, output file will be empty because id command will use stderr for it’s output stream.
But, id nosuchuser 2>/tmp/outputdata will successfully redirect stderr stream.
By searching the internet for some commands, you may notice redirections like 2>&1 or 2>/dev/null and I don't want you to be confused:
2>&1 is a redirection of stderr to stdout.
/dev/null is a device that will throw to trash all data that was sent to it.
So it is possible to suppress (ignore) any chosen output by redirecting to /dev/null
some_command >/dev/null 2>/dev/null
>/dev/null suppresses stdout
2>/dev/null suppresses stderr
And finally, 2>&1 will redirect stderr stream to the stdout stream, which could be saved in one file:
id nosuchuser 2>&1 >/tmp/outputdata
/tmp/outputdata will contain both stdout and stderr content, while there will be no output at all on our terminal screen.
To transfer output of one program to another we should use PIPE. Pipe is some kind of a virtual connector between one channel to another. To make that work, one end of the PIPE must have a sender, and other receiver. It is not possible to send data to the PIPE without a receiver on the other side.
For piping data from one program (command) to another, we use special character | (vertical bar) between the two commands:
cat /etc/passwd | grep root
In this example, `stdout` of the `cat /etc/passwd` is transferred to the `stdin` of the `grep root` command, which by itself outputs on our terminal screen (stdout) one line containing the ‘root’ string.
It is possible to construct a very long and complex command chain, while each piped command’s output is being catched and processed by another command stdin.
For example, getting login shell of the root user:
cat /etc/passwd | grep root | cut -d ':' -f7