Los scripts de shell brindan una función muy poderosa: la capacidad de redirigir y enviar la salida de comandos y scripts a archivos, dispositivos o incluso como entrada a otros comandos o scripts.
Este artículo se centra en la salida de comandos y secuencias de comandos.
Tipo de salida
Los comandos y scripts en el shell pueden generar dos tipos básicos de salida:
- Salida estándar: Salida normal del comando/secuencia de comandos (descriptor de archivo 1)
- Error estándar: Salida de error del comando/secuencia de comandos (descriptor de archivo 2)
De forma predeterminada, STDOUT y STDERR se envían a la pantalla de su terminal.
En términos de entrada, entrada estándar La entrada se lee desde el teclado de forma predeterminada (descriptor de archivo 0). Un descriptor de archivo es un identificador único para un archivo u otro recurso de E/S.
Cómo redirigir la salida de shell
Hay varias formas de redirigir la salida de los scripts y comandos de shell.
1. Redirigir STDOUT
Para los siguientes ejemplos, usaré este conjunto simple de archivos:
$ls -la file*
-rw-r--r--. 1 admin2 admin2 7 Mar 27 15:34 file1.txt
-rw-r--r--. 1 admin2 admin2 10 Mar 27 15:34 file2.txt
-rw-r--r--. 1 admin2 admin2 13 Mar 27 15:34 file3.txt
estoy ejecutando un simple ls
comando para ilustrar STDOUT vs STDERR, pero los mismos principios se aplican a la mayoría de los comandos que ejecuta desde el shell.
Puedo redirigir stdout a un archivo usando ls file* > my_stdout.txt
:
$ls file* > my_stdout.txt
$ cat my_stdout.txt
file1.txt
file2.txt
file3.txt
A continuación, ejecuto un comando similar, pero usando 1
delantero >
Usar redirección >
La señal es lo mismo que usar 1>
Haciendo esto: le digo al shell que redirija STDOUT a este archivo. Si omito el descriptor de archivo, STDOUT se usa de forma predeterminada.puedo correr sdiff
El comando muestra la salida de ambos comandos uno al lado del otro:
$ls file* 1> my_other_stdout.txt
$sdiff my_stdout.txt my_other_stdout.txt
file1.txt file1.txt
file2.txt file2.txt
file3.txt file3.txt
Como puede ver, ambas salidas tienen el mismo contenido.
2. Redirigir STDERR
Ahora, ¿qué tiene de especial STDERR?Para demostrarlo, introduciré una condición de error en el ejemplo anterior. ls file* non-existing-file* > my_normal_output.txt
:
El resultado es el siguiente:
Aquí hay algunas observaciones de la prueba anterior:
- La salida de los archivos existentes se enviará correctamente al archivo de destino.
- Se envía a la pantalla un error (que se muestra cuando intento enumerar algo que no existe). Aquí es donde se envían los errores de forma predeterminada, a menos que los redirija.
[ Download a Bash Shell Scripting Cheat Sheet. ]
A continuación, redirigiré la salida de error haciendo referencia explícita al descriptor de archivo 2 ls file* non-existing-file* > my_normal_output.txt 2> my_error_output.txt:
En el ejemplo anterior:
- este
ls
Los comandos no muestran mensajes de error en la pantalla como antes. - La salida normal contiene lo que esperaría.
- Los mensajes de error se envían a
my_error_output.txt
documento.
3. Enviar STDOUT y STDERR al mismo archivo
Otra situación común es enviar STDOUT y STDERR a idéntico documento:
$ls file* non-existing-file* > my_consolidated_output.txt 2>&1
$ cat my_consolidated_output.txt
ls: cannot access 'non-existing-file*': No such file or directory
file1.txt
file2.txt
file3.txt
En este ejemplo, toda la salida (normal y de error) se envía al mismo archivo.
este 2>&1
medios de construcción»Envía STDERR al mismo lugar que enviaste STDOUT. «
4. Redirigir la salida, pero agregar archivos
En todos los ejemplos anteriores, cada vez que redirijo alguna salida, uso un >
el significado es»Envíe algo a este archivo e inicie el archivo desde cero.» Entonces, si el archivo de destino existe, se sobrescribirá.
Si yo quiero adicional a un archivo existente, necesito usar >>
El archivo se crea si aún no existe:
$echo "Adding stuff to the end of a file" >> my_output.txt
$cat my_output.txt
file1.txt
file2.txt
file3.txt
Adding stuff to the end of a file
5. Redirigir a otro proceso o a ninguna parte
El ejemplo anterior cubre la redirección de la salida a un archivo, pero también puede redirigir la salida a otros procesos o dev/null
.
Enviar resultados a otros procesos es una de las características más poderosas del shell.Para esta tarea, utilice |
(tubería), que envía la salida de un comando a la entrada del siguiente comando:
ps -ef | grep chrome | grep -v grep | wc -l
21
El ejemplo anterior enumera mis procesos, filtrando cualquier proceso que contenga la cadena Aleación de cromoignora la linea sobre mi grep
y cuente las filas resultantes.Si quiero enviar la salida a un archivo, agrego >
y nombre de archivo hasta el final de la cadena.
Finalmente, aquí hay un ejemplo en el que quiero ignorar uno de los STDERR de salida:
$tar cvf my_files.tar file* more-non-existing*
file1.txt
file2.txt
file3.txt
tar: more-non-existing*: Cannot stat: No such file or directory
tar: Exiting with failure status due to previous errors
porque tar
El comando no encontró ningún archivo cuyo nombre comience con more-non-existing
y finalmente se muestran algunos mensajes de error.
Supongamos que creo algunos scripts y no me importa ver o detectar estos errores (lo sé, en la vida real, debe prevenir y manejar los errores, no solo ignorarlos):
$tar cvf my_files.tar file* more-non-existing* 2> /dev/null
file1.txt
file2.txt
file3.txt
este /dev/null
es un archivo de dispositivo especial, como un «agujero negro»: lo que envías allí desaparece.
[ Download this guide to installing applications on Linux. ]
6. Uso de redireccionamientos en scripts
=== SUMMARY OF INVESTIGATION OF chrome ===
Date/Time of the execution: 2022-03-25 18:05:50
Number of processes found.: 5
PIDs:
1245475
1249558
1316941
1382460
1384452
Este script muy simple hace lo siguiente:
- Línea 3: el comando se ejecuta en el sistema operativo y se guarda en la variable DATE_TIME.
- Línea 6: Ejecutar
ps
ordenar y redirigir agrep
y un archivo.- En lugar de enviar la salida a un archivo, podría enviar la salida a una variable (como la línea 3), pero en este caso quiero ejecutar otras operaciones con la misma salida, así que la capturo. En una situación más realista, tener ese archivo también es útil durante el desarrollo o la resolución de problemas para que pueda investigar más fácilmente lo que genera el comando.
- Línea 8: Ejecute el comando adicional, redirigiendo la salida a
wc
y asigne el resultado a una variable. - Línea 9: Propósito
awk
Seleccione solo la columna 2 de la salida y ordénela en orden descendente (solo para agregar otra tubería).
envolver
Estos son algunos ejemplos de redireccionamiento de STDOUT y STDERR. Póngalo todo junto y se dará cuenta del poder de la redirección. Al encadenar comandos individuales, manipular su salida y usar el resultado como entrada para el siguiente comando, puede realizar tareas que, de lo contrario, podrían requerir que desarrolle un script o un programa. También puede incorporar esta técnica en otros scripts, usando todo como bloques de construcción.