Stdout, stderr and stdin
Every process on Linux has 3 streams: input (0), standard output (1) and error output (2). Each one can be redirected. Stdin reads "by default" from keyboard and both stdout as well as stderr print to the console. Take for example the ls command:
# ls .config INBOX.msf boot etc lib lost+found mnt proc run selinux sys usr .readahead bin dev home lib64 media opt root sbin srv tmp var
it prints to console but this can easily be redirected to a file:
# ls >/tmp/file1 #
or, synonymously:
# ls 1>/tmp/file1 #
All output is redirected to the file, but not the error messages:
# ls nothere > /tmp/file1 ls: cannot access nothere: No such file or directory #
To redirect the error messages you use the 2> operator:
# ls nothere 2> /tmp/file1 #
To redirect as well error messages as output to a file use a command like this:
# ls nothere > /tmp/file1 2>&1 #
To see where a command has been redirected to use its process ID and look up its file descriptors, in this case for the command cat:
# cat >/tmp/file1 & [5] 31469 [5]+ Stopped cat > /tmp/file1 # ll /proc/31469/fd total 0 lrwx------ 1 root root 64 Jan 27 15:22 0 -> /dev/pts/19 l-wx------ 1 root root 64 Jan 27 15:22 1 -> /tmp/file1 lrwx------ 1 root root 64 Jan 27 15:22 2 -> /dev/pts/19
Piping
Piping is a famous concept in Unix that describes the handling of input and output of running processes. Think of a process that asks for your name. You enter your name by using the keyboard. But instead of reading from the keyboard, the process could also read from the standard input stream. And by default, the standard input stream could be fed by the keyboard. You can then exchange the keyboard against the output of another process.
I mean the following. Here you start a process that asks you for your name and greets you then:
tweedleburg:~ # (echo -n "how is your name? "; read name; echo "hallo $name") how is your name? Thorsten hallo Thorsten tweedleburg:~ #
You type in the name on the keyboard and the command reads from standard input which comes from the keyboard.
Now comes the trick. You can also use the output of another process to be the standard input (stdin) for this process. Instead of writing to the console, the process writes to the input of the next process. You do this with a pipe:
tweedleburg:~ # echo "process number $$" | (echo -n "how is your name? "; read name; echo "hallo $name") how is your name? hallo process number 16939 tweedleburg:~ #
Here, the echo process writes "process number 16939". Normally, it would write to console, but the pipe ("|") redirects the output to the input of the next process (enclosed in parentheses). This process would normally read from keyboard, but there is already another stream coming from standard input. So it reads "process number 16939" just as if you had entered it on the keyboard.