Vamos a tratar de explicar el control sobre el flujo de datos STDERR y STDOUT.

STDOUT representa el flujo de salida de comandos, ficheros … etc …

STDERR representa el flujo de salida de errores.

Básicamente, STDERR es lo mismo que STDOUT, la diferencia es que contiene posibles errores que el programa reporta por pantalla al usuario.

En el siguiente ejemplo vamos a utilizar un error producido por «cat» (lee ficheros) y lo vamos a guardar en un fichero utilizando «>» (STDOUT)

$cat mi_fichero.txt > mi_log.log

En este caso, mi_fichero.txt no existe. Dado que «>» es utilizado sólo para STDOUT, el fichero mi_log.log será creado, pero está vacío.
En cambio, podremos ver en la consola el error devuelto por STDERR:

cat: mi_fichero.txt: No such file or directory

Si queremos capturar este mensaje de error en un fichero mi_log.err tendremos que añadir el número «2» a «>» (STDERR):

cat mi_fichero.txt 2> mi_log.err

Aquí le estamos indicando a Bash que capture el descriptor número 2 (STDERR) y lo envié al fichero. Recordemos que STDIN es 0 y STDOUT es 1.

De igual manera se puede mezclar STDOUT y STDERR. La utilidad de esto la encontramos cuando queremos ejecutar algún programa de forma automática (utilizando cron, por ejemplo) o desde un script y deseamos capturar toda la información posible en algún fichero al que podamos acceder posteriormente.

Entonces, el tema es bastante sencillo. Vamos a hacer un «tail» (lee el final de un fichero) de dos ficheros «/var/log/dmesg» y «mi_fichero.txt» y todas las salidas vamos a enviarlas a dos ficheros mi_log.out y mi_log.err.

$tail /var/log/dmesg mi_fichero.txt >mi_log.out 2> mi_log.err

dmesg sabemos que existe, por lo tanto las ultimas líneas devueltas por «tail» serán capturadas por el STDOUT al fichero mi_log.out. En cambio el error devuelto al no encontrar el fichero mi_log.txt será enviado por STDERR a mi_log.err:

tail: cannot open mi_fichero.txt for reading: No such file or directory

También podemos enviar las dos salidas a un único fichero e incluso encauzarlas como STDIN para otro programa.
Para capturar las dos salidas vamos a utilizar «2>&1» lo cual vamos a ver en muchos scripts.

$tail /var/log/dmesg mi_fichero.txt > mi_log.log 2>&1

La mejor manera de silenciar a un programa para que no perturbe la ejecución de nuestro script es enviar todas las salidas a /dev/null.

$tail /var/log/dmesg mi_fichero.txt > /dev/null 2>&1

Si nuestro script necesita ejecutar otro programa y necesita tan sólo de su «exit status», el usuario que ejecuta el script no verá que programas estamos utilizando y no recibirá los posibles errores que de otra manera aparecerían en pantalla.
En segundo lugar, podemos realizar otro tipo de comprobaciones dirigiendo STDERR y STDOUT como STDIN de otro programa.
Supongamos que creamos un script que sólo funciona con OpenSSH. Para comprobar que la versión que está instalada en el sistema es OpenSSH podemos utilizar lo siguiente:

$/usr/bin/ssh -v 2>&1 | grep -q OpenSSH ; echo $?
0

Si nuestro cliente de SSH no fuera el OpenSSH obtendriamos lo siguiente:

$/usr/bin/ssh -v 2>&1 | grep -q OpenSSH ; echo $?
1

En el caso de que nuestra versión de «grep» no tenga la opción «q quiet» volvemos a utilizar /dev/null

ssh -v 2>&1 | grep OpenSSH >/dev/null 2>&1 ; echo $?
0

Donde $? es una variable que contiene el «exit status» del último comando ejecutado, en este ejemplo es grep.

Basado en : http://monocaffe.blogspot.com/