redirigir stdin, stdout y stderr en Unix/Linux

En todas las variantes de Unix tenemos tres flujos estándar que, a modo de canales, conectan la entrada y salida (I/O) de un comando/aplicación con la terminal/consola cuando se ejecuta, son los siguientes:

  • standard input (stdin)
  • standard output (stdout)
  • standard error (stderr)

Vamos a explicar los usos que podemos dar estos tres canales para enviar y recoger los datos que surgen de la ejecución de un script, comando o aplicación.

standard input (stdin)

Stdin, o standard input son los datos que son enviados al programa, quizás cara al usuario de terminal sea el menos utilizado ya que lo normal suele ser interpretar los datos que el programa o comando envía, y no al revés. Normalmente stdin es texto enviado por el usuario, vamos a ver un ejemplo.

En un script en perl, podemos solicitar la interacción del usuario mediante STDIN, por ejemplo en este caso recogemos mediante STDIN el valor de dos variables que el usuario escribe:

#!/usr/bin/perl
print "Introduce tu nombre:\n";
my $nombre = <STDIN>;
print "Introduce tu apellido:\n";
my $apellido = <STDIN>;

Otro ejemplo que se me ocurre es el que puse en la entrada de automatizar comandos FTP, en este caso a la conexión FTP le pasamos de antemano los comandos a ejecutar:

ftp -inv direccion_ip<<FINFTP
comando1
comando2
comando3
FINFTP

standard output (stdout)

A través de la salida estándar, «stdout» se reciben los datos que vuelca el comando o programa durante su ejecución, ejemplos sencillos de stdout serían por ejemplo el resultado de un «ls»,»cat» o cualquier otro comando de terminal. En cambio, hay otros comandos o programas que no muestran salida (a no ser que se especifique), como por ejemplo mover o copiar ficheros. Como ya sabemos cualquiera de estos flujos de datos se puede manipular, vamos a ver un ejemplo  para comprender sus posibilidades.

Si hicieramos un «ls» a una carpeta, la salida de datos (stdout) se muestra en nuestra terminal:

$ ls
backups  cpq    games  local  log   opt  spool  www
cache    crash  lib    lock   mail  run  tmp

Para manipular la salida estándar, utilizaremos el símbolo «>». Si por ejemplo quisieramos que stdout fuera redirigido a un fichero de texto, haríamos así:

$ ls > fichero.txt

Como podréis comprobar, por pantalla no aparece el resultado del comando, sino que se ha almacenado en el fichero indicado:

$ cat fichero.txt
backups  cpq    games  local  log   opt  spool  www
cache    crash  lib    lock   mail  run  tmp

standard error (stderr)

A través del canal stderr los programas o comandos suelen enviar el informe de error de la ejecución de un comando en caso de fallar. En nuestros scripts o comandos podemos combinar el uso de stdout y stderr para separar la salida estándar de los errores, almacenarlos en registros independientes o manipularlos por separado.

En el siguiente ejemplo vamos a ejecutar un «ls» con parámetros incorrectos, por defecto la salida de errores se volcará en pantalla (terminal):

$ ls -7
ls: opción incorrecta -- '7'
Pruebe `ls --help' para más información.

Si quisieramos almacenar los errores de la ejecución del comando en caso de suceder, podemos volcarlos usando en lugar del símbolo «>» el número 2 seguido de «>», «2>»:

$ ls -7 2> errores.log

Como podéis ver los errores ya no aparecen por pantalla, pero si abrimos el fichero de log tenemos el registro del fallo:

$ cat errores.log
ls: opción incorrecta -- '7'
Pruebe `ls --help' para más información.

Si quisieramos redirigir tanto el stdout como stderr al mismo sitio, en lugar de especificar dos veces el destino podemos hacerlo del siguiente modo «2>&1». Vamos a ver un ejemplo

Stdout y stderr a un fichero de log:

$ ls -3 > fichero.log 2>&1

Vamos a ver un ejemplo práctico de mysql. El comando mysqldump vuelca a stdout el dump de una base de datos, seguro que nos es más útil en un fichero que por pantalla, así mismo, si surge algún error nos conviene revisarlo así que lo volcamos a otro fichero distinto de log:

$ mysqldump test > test.sql 2> error.log

Otra opción es querer que tanto stdout como stderr vayan directamente a la basura (/dev/null):

$ ls -l > /dev/null 2>&1

Este es el uso más básico que podemos dar a estos tres importantes flujos estandar Unix, si tenéis cualquier duda podéis consultarla a través de los comentarios.

3 comentarios en “redirigir stdin, stdout y stderr en Unix/Linux

  1. Hola Alejandro,

    Estaba pensado hacer un artículo al respecto pero tú lo explicas tan bien, que lo voy a compartir ya mismo :)

    Por cierto, genial blog!

Comments are closed.