Stdout, stderr and stdin

From Linuxintro
(Redirected from Stdout, stdin and stderr)

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.

See also