LinuxParty
En nuestra búsqueda para examinar todo el desorden ( &
, |
, ;
, >
, <
, {
, [
, (
,), ]
, }
, etc.) que está salpicado a lo largo de la mayoría de los comandos Bash encadenados, hemos estado observando de cerca en el símbolo ampersand ( &
) .
La última vez, vimos cómo puede usar &
para impulsar procesos que pueden tardar mucho tiempo en completarse en segundo plano . Pero, el &, en combinación con los soportes de ángulo, también se puede utilizar para canalizar la salida y la entrada en otros lugares.
En los tutoriales anteriores sobre corchetes angulares , vio cómo usar >
así:
ls> list.txt
para canalizar la salida de ls
al archivo list.txt .
Ahora vemos que esto es realmente una taquigrafía para
ls 1> list.txt
Y ese 1
, en este contexto, es un descriptor de archivo que apunta a la salida estándar ( stdout
).
De manera similar, 2
puntos al error estándar ( stderr
), y en el siguiente comando:
ls 2> error.log
todos los mensajes de error se canalizan al archivo error.log .
Para recapitular: 1>
es la salida estándar ( stdout
) y 2>
la salida de error estándar ( stderr
).
Hay un tercer descriptor de archivo estándar, 0<
, la entrada estándar ( stdin
). Puede ver que es una entrada porque la flecha ( <
) apunta hacia el 0
, mientras que para 1
y 2
, las flechas ( >
) apuntan hacia afuera.
¿Para qué sirven los descriptores de archivos estándar?
Si está siguiendo esta serie en orden, ya ha usado la salida estándar ( 1>
) varias veces en su forma abreviada: >
.
Las cosas como stderr
( 2
) también son útiles cuando, por ejemplo, usted sabe que su comando emitirá un error, pero Bash le informa que no es útil y que no necesita verlo. Si desea hacer un directorio en su directorio de inicio , por ejemplo:
mkdir newdir
y si newdir / ya existe, mkdir
mostrará un error. Pero ¿por qué te importa? (Ok, existen algunas circunstancias en las que puede importarte, pero no siempre). Al final del día, newdir estará allí de una forma u otra para que te llenes de cosas. Puedes eliminar el mensaje de error empujándolo en el vacío, que es / dev / null :
mkdir newdir 2> / dev / null
Esto no es solo una cuestión de " no mostrar mensajes de error feos e irrelevantes porque son molestos " , ya que puede haber circunstancias en las que un mensaje de error pueda causar una cascada de errores en otros lugares. Digamos, por ejemplo, que desea encontrar todos los archivos de servicio en / etc. Podrías hacer esto:
encuentra / etc -iname "* .service"
Pero resulta que en la mayoría de los sistemas, muchas de las líneas se escupen al find
errores de visualización porque un usuario normal no tiene derechos de acceso de lectura a algunas de las carpetas en / etc. Hace que leer la salida correcta sea engorroso y, si la find
es parte de un script más grande, podría hacer que el siguiente comando en la línea bork.
En su lugar, puede hacer esto:
encuentre / etc -iname "* .service" 2> / dev / null
Y solo obtiene los resultados que busca.
Una introducción a los descriptores de archivos
Sin embargo, hay algunas advertencias de tener descriptores de archivo separados para stdout
y stderr
. Si desea almacenar la salida en un archivo, haga esto:
encuentre / etc -iname "* .service" 1> services.txt
funcionaría bien porque 1>
significa " enviar salida estándar, y solo salida estándar (NO error estándar) en alguna parte ".
Pero aquí radica el problema: ¿qué sucede si * desea * mantener un registro dentro del archivo de los errores junto con los resultados no erróneos? La instrucción anterior no lo hará porque SOLO escribe los resultados correctos de la find
, y
encuentre / etc -iname "* .service" 2> services.txt
SOLO escribirá los errores.
¿Cómo conseguimos ambos? Pruebe el siguiente comando:
encuentre / etc -iname "* .service" &> services.txt
... y saluda &
otra vez!
Hemos estado diciendo todo el tiempo que stdin
( 0
), stdout
( 1
) y stderr
( 2
) son descriptores de archivo . Un descriptor de archivo es una construcción especial que apunta a un canal a un archivo, ya sea para leer, escribir, o ambos. Esto viene de la antigua filosofía de UNIX de tratar todo como un archivo. ¿Quieres escribir en un dispositivo? Trátela como un archivo. ¿Quieres escribir en un socket y enviar datos a través de una red? Trátela como un archivo. ¿Quieres leer y escribir en un archivo? Bueno, obviamente, tratarlo como un archivo.
Por lo tanto, al administrar dónde van los resultados y los errores de un comando, trate el destino como un archivo. Por lo tanto, cuando los abre para leerlos y escribirlos, todos obtienen descriptores de archivos.
Esto tiene efectos interesantes. Puede, por ejemplo, canalizar el contenido de un descriptor de archivo a otro:
encuentre / etc -iname "* .service" 1> services.txt 2> & 1
Esta canalización stderr
a stdout
y stdout
se canaliza a un archivo, services.txt .
Y ahí está otra vez: el &
, señalando a Bash que 1
es el descriptor del archivo de destino.
Otra cosa con los descriptores de archivo estándar es que, cuando se canaliza de uno a otro, el orden en el que lo hace es un poco contradictorio. Tome el comando de arriba, por ejemplo. Parece que ha sido escrito al revés. Puede leerlo así: " canalice la salida a un archivo y luego canalice los errores a la salida estándar " . Parece que la salida de error llega tarde y se envía cuando 1
ya está hecho.
Pero no es así como funcionan los descriptores de archivos. Un descriptor de archivo no es un marcador de posición para el archivo, sino para el canal de entrada y / o salida del archivo. En este caso, cuando hace 1> services.txt
, está diciendo " abrir un canal de escritura a services.txt y dejarlo abierto ". 1
es el nombre del canal que va a utilizar y permanece abierto hasta el final de la línea.
Si aún crees que es al revés, prueba esto:
encuentre / etc -iname "* .service" 2> & 1 1> services.txt
Y note cómo no funciona; observe cómo se canalizan los errores al terminal y solo la salida no errónea (es decir, la salida stdout
) se transfiere a services.txt
.
Esto se debe a que Bash procesa todos los resultados de la find
de izquierda a derecha. Piénselo así: cuando Bash llega a 2>&1
, stdout
( 1
) sigue siendo un canal que apunta al terminal. Si el resultado que find
Bash contiene un error, se coloca en 2
, se transfiere a 1
y, ¡se va al terminal!
Luego, al final del comando, Bash ve que desea abrir stdout
como un canal para el archivo services.txt . Si no se ha producido ningún error, el resultado pasa a través de 1
en el archivo.
Por el contrario, en
encuentre / etc -iname "* .service" 1> services.txt 2> & 1
1
apunta a services.txt
desde el principio, por lo que todo lo que aparece en 2
se canaliza a través de 1
, que ya apunta al lugar de descanso final en services.txt
, y es por eso que funciona.
En cualquier caso, como se mencionó anteriormente &>
es una abreviatura de " salida estándar y error estándar ", es decir, 2>&1
.
Probablemente esto sea demasiado, pero no te preocupes por eso. El redireccionamiento de descriptores de archivos aquí y allá es un lugar común en las líneas de comandos y scripts de Bash. Y, aprenderá más sobre los descriptores de archivos a medida que avanzamos en esta serie.
-
Documentación
- Los alemanes denuncian la influencia del inglés mientras el "apóstrofe del idiota" obtiene la aprobación oficial
- Explora la Historia Hispánica con este Mapa Interactivo de la Real Academia de Historia
- ¿CÓMO SE INVENTÓ LA RUEDA?
- ¿Estamos en el 'Antropoceno', la era humana? Los científicos dicen: no
- Quemadores de Hidrógeno Verde para una Producción de Asfalto Sostenible
- Jericó: Un Viaje a Través de los Milenios en la Ciudad más Antigua del Mundo
- La Generación Z recurre a los libros y bibliotecas físicos
- El Trágico Declive de la Biblioteca de Alejandría: Una Epopeya Perdida en Llamas
- Los Neandertales fueron los primeros homínidos en controlar el fuego, y no los sapiens, sugiere un estudio
- Un grupo de Hóminidos Eurosiáticos podrían poner en duda todo lo que sebe sobre el del Homo Sapiens, hasta la fecha
- Descubre la Iglesia de San Antonio de los Alemanes: Un Tesoro Arquitectónico en el Corazón de Madrid
- La Asombrosa Reconstrucción de una Mujer Prehistórica Después de 4 Mil Años
- Descubren nuevo fósil de hace 8.7 millones de años en Turquía que desafía la historia sobre el origen de la humanidad
- Los arqueólogos descubren una lengua secreta perdida de hace 3.000 años
- La Queja Más Antigua del Mundo: La Historia Detrás de una Antigua Carta de Cliente Insatisfecho