LinuxParty

Inicio desactivadoInicio desactivadoInicio desactivadoInicio desactivadoInicio desactivado
 

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.

Pin It

Escribir un comentario


Código de seguridad
Refescar



Redes:



 

Suscribete / Newsletter

Suscribete a nuestras Newsletter y periódicamente recibirás un resumen de las noticias publicadas.

Donar a LinuxParty

Probablemente te niegues, pero.. ¿Podrías ayudarnos con una donación?


Tutorial de Linux

Nos obligan a moslestarte con la obviedad de que este sitio utiliza Cookies. Ver política