Redireccionar stdout y stderr

Cada vez que ejecutamos un programa en un terminal éste suele mostrarnos una serie de mensajes. Por una parte están los mensajes normales que nos indican las acciones que se han llevado a cabo (tantos archivos copiados, se han encontrado x elementos, etc.). Por otro lado están los mensajes de error que pueden producirse.

Estamos acostumbrados a que ambos mensajes se muestren en la pantalla así que no los diferenciamos.

Sin embarglo, los mensajes “normales” se envían a lo que se llama el dispositivo de salida estándar. A éste se le conoce como stdout (standard out).

Los mensajes de error se envían (o deberían enviarse) al dispositivo de salida de error: stderr (standard error).

Lo que sucede es que, por defecto, ambos dispositivos de salida se envían a la pantalla.

Pero esto no tiene por qué ser así. Por ejemplo, es posible que queramos que los mensajes de error se guarden en un fichero o se envíen por email en lugar de mostrarse en la pantalla. O puede que queramos hacer eso con los mensajes normales.

Hay un tercer dispositivo: el de entrada estándar. Este, normalmente, es el teclado. También podemos redirigirlo de tal forma que un programa puede leer la entrada desde un fichero en lugar desde el teclado.

Numeración de stdin, stdout, stderr

A cada uno de estos dispositivos se le ha asignado un número que les identifica:

  • 0 stdin Standard input
  • 1 stdout Standard output
  • 2 stderr Standard error

Ejemplo

Para ver cómo funcionan las redirecciones vamos a usar un sencillo ejemplo:

#!/bin/bash
echo “Hola”
comando_inexistente

Guarda este script en un archivo llamado “prueba” y dale permisos de ejecución:

$ chmod +x prueba

Este comando al ejecutarlo muestra el siguiente resultado:

$ ./prueba
Hola
./prueba: line 3: comando_inexistente: command not found

En este caso stdout y stderr son la pantalla y se nos muestran ambos mensajes juntos.

Redirigir stdout a un fichero

Para redirigir la salida de un comando a un fichero podemos ejecutarlo así:

$ ./prueba 1> prueba.log
./prueba: line 3: comando_inexistente: command not found

Puedes ver que solo aparece el mensaje de error, “Hola” ya no aparece. Eso es porque lo hemos redirigido al fichero prueba.log.

Vamos a ver el contenido de prueba.log:

$ more prueba.log
Hola

La forma de redirigir stdsout al fichero prueba.log es usando 1>. El 1 se refiere a stdout y el símbolo '>' indica que queremos redirigirlo al fichero que se indica a continuación.

En el caso de stdout también podemos usar el símbolo “mayor que” sin el 1:

$ ./prueba > prueba.log
./prueba: line 3: comando_inexistente: command not found

Descartar los mensajes de stdout

También podemos descartar todos los mensajes “normales” enviándolos a /dev/null. Este es un fichero especial inexistente. Todo lo que metamos en /dev/null se va al “limbo”:

$ ./prueba 1> /dev/null
./prueba: line 3: comando_inexistente: command not found

Redirigir stderr a un fichero

De igual forma podemos redirigir los mensajes que se envían a la salida de error estándar a un fichero:

$ ./prueba 2> prueba.log
Hola

Para ver el contenido del fichero:

$ more prueba.log
./prueba: line 3: comando_inexistente: command not found

Esto suele venir muy bien, por ejemplo, para ver cuál es el resultado de un cron.

Por supuesto podemos descartar los errores enviándolos a /dev/null:

$ ./prueba 2> /dev/null
Hola

Redirigir stdout y stderr a un fichero

También podemos redirigir tanto la salida normal como los errores a un fichero:

$ ./prueba2 &> prueba.log

Podemos comprobar que ambas han sido redirigidas:

$ more prueba.log
Hola
./prueba2: line 2: comando_inexistente: command not found

Redirigir stderr a stdout

También puede interesarnos redirigir stderr a stdout. Esto podemos hacerlo así:

./prueba > prueba.log 2>&1

Aquí estamos redirigiendo la salida del programa a prueba.log. Luego redirigimos la salida stderr a la salida estándar. Y dado que la salida estándar está redirigida a un fichero todo se va a guardar en dicho fichero.

¿Qué significa 2>&1 ?

¿A qué viene esta forma tan rara? ¿Por qué el ampersand ese? (y añado ¿Por qué Bash es tan feo?).

Si hiciésemos:

2>1

Aquí estaríamos redirigiendo stderr a un fichero llamado '1'. La forma de indicar que queremos redirigir a una de las otras salidas estándar es anteponiendo el '&'.

Autor:
Nivel: Principiante
Palabras clave:
Fecha publicado:
Fecha actualizado: 17-08-2016

Otros capítulos de la misma serie

Este capítulo es parte de la serie: Introducción a Bash.

Y muchos más en preparación.

Disponible en los planes: Laravel hero PHP a tope