Ayer leí este comentario SO que dice que en el shell (al menos bash
) >&-
"tiene el mismo resultado que" >/dev/null
.
Ese comentario en realidad se refiere a la guía de ABS como la fuente de su información. Pero esa fuente dice que la >&-
sintaxis "cierra los descriptores de archivo".
No me queda claro si las dos acciones de cerrar un descriptor de archivo y redirigirlo al dispositivo nulo son totalmente equivalentes. Entonces mi pregunta es: ¿lo son?
A primera vista, parece que cerrar un descriptor es como cerrar una puerta, pero redirigirlo a un dispositivo nulo es abrir una puerta al limbo. Los dos no me parecen exactamente iguales porque si veo una puerta cerrada, no intentaré arrojar nada, pero si veo una puerta abierta, supondré que puedo.
En otras palabras, siempre me he preguntado si >/dev/null
significa que cat mybigfile >/dev/null
realmente procesaría cada byte del archivo y lo escribiría para /dev/null
olvidarlo. Por otro lado, si la cáscara se encuentra con un descriptor de archivo cerrado tiendo a pensar (pero no estoy seguro) que simplemente no escribirá nada, aunque la cuestión sigue siendo si cat
todavía se lee cada byte.
Este comentario dice >&-
y >/dev/null
" debería " ser el mismo, pero no es una respuesta tan contundente para mí. Me gustaría tener una respuesta más autorizada con alguna referencia al núcleo estándar o fuente o no ...
fuente
Respuestas:
No, ciertamente no desea cerrar los descriptores de archivo 0, 1 y 2.
Si lo hace, la primera vez que la aplicación abra un archivo, se convertirá en stdin / stdout / stderr ...
Por ejemplo, si haces:
Cuando
tee
(al menos algunas implementaciones, como busybox ') abre el archivo para escribir, se abrirá en el descriptor de archivo 1 (stdout). Entoncestee
escribiremostext
dos veces enfile
:Se sabe que causa vulnerabilidades de seguridad. Por ejemplo:
Y
chsh
(una aplicación setuid) puede terminar escribiendo mensajes de error/etc/passwd
.Algunas herramientas e incluso algunas bibliotecas intentan protegerse contra eso. Por ejemplo, GNU
tee
moverá el descriptor de archivo a uno arriba de 2 si los archivos que abre para escribir se asignan 0, 1, 2 mientras que busyboxtee
no lo hará.La mayoría de las herramientas, si no pueden escribir en stdout (porque, por ejemplo, no está abierto), informarán un mensaje de error en stderr (en el idioma del usuario, lo que significa un procesamiento adicional para abrir y analizar archivos de localización ...). será significativamente menos eficiente y posiblemente haga que el programa falle.
En cualquier caso, no será más eficiente. El programa seguirá haciendo una
write()
llamada al sistema. Solo puede ser más eficiente si el programa deja de escribir en stdout / stderr después de la primerawrite()
llamada fallida del sistema, pero los programas generalmente no lo hacen. Generalmente salen con un error o siguen intentándolo.fuente
No es una respuesta completa a su pregunta, pero sí, lo anterior es cómo funciona.
cat
lee los archivos con nombre, o la entrada estándar si no se nombra ningún archivo, y envía a su salida estándar el contenido de esos hasta que encuentra un EOF en (último ingreso estándar) el último archivo nombrado. Ese es su trabajo.Al agregar
>/dev/null
, está redirigiendo la salida estándar a / dev / null. Ese es un archivo especial (un nodo de dispositivo) que arroja todo lo escrito en él (e inmediatamente devuelve EOF en la lectura). Tenga en cuenta que la redirección de E / S es una característica proporcionada por el shell, no por cada aplicación individual, y que no hay nada mágico en el nombre / dev / null, solo lo que existe allí en la mayoría de los sistemas tipo Unix .También es importante tener en cuenta que la mecánica específica de los nodos de dispositivo varía de un sistema operativo a otro, pero cat (que, en un sistema GNU, significa coreutils) es multiplataforma (el mismo código fuente debe ejecutarse al menos en Linux y Hurd) y, por lo tanto, no puede tomar dependencias de núcleos específicos del sistema operativo. Además, aún funciona si crea un alias / dev / null (en Linux, esto significa un nodo de dispositivo con el mismo número de dispositivo mayor / menor) con otro nombre. Y siempre existe el caso de escribir en otro lugar que se comporte efectivamente igual (digamos, / dev / zero).
De ello se deduce que
cat
desconoce las propiedades especiales de / dev / null, y de hecho es probable que desconozca la redirección en primer lugar, pero aún necesita realizar exactamente el mismo trabajo: lee los archivos nombrados y genera el contenido de el / esos archivo (s) a su salida estándar. Que la salida estándar decat
pase a un vacío no es algo encat
sí mismo.fuente
cat mybigfile > /dev/null
harácat
que lea cada byte debigfile
memoria. Y, por cadan
bytes, llamaráwrite(1, buffer, n)
. Sin el conocimiento delcat
programa,write
no hará absolutamente nada (excepto tal vez por una contabilidad trivial). Escribir en/dev/null
no requiere procesar cada byte.cat
ocp
de que trabajaría pormmap
ing grandes trozos de archivo de origen en la memoria, a continuación, llamarwrite()
en la región asignada. Si estuviera escribiendo/dev/null
, lawrite()
llamada volvería de inmediato sin fallar en las páginas del archivo fuente, por lo que en realidad nunca se leería desde el disco.cat
se ejecuta en muchas plataformas, pero una mirada casual al código fuente mostrará muchos#ifdef
s: no es literalmente el mismo código que se ejecuta en todas las plataformas, y hay muchas secciones dependientes del sistema.