Solo estaba ejecutando algunos comandos en una terminal y comencé a preguntarme, ¿Unix / Linux toma atajos cuando ejecuta comandos canalizados?
Por ejemplo, supongamos que tengo un archivo con un millón de líneas, de las cuales las primeras 10 contienen hello world
. Si ejecuta el comando, grep "hello world" file | head
¿se detiene el primer comando tan pronto como encuentra 10 líneas, o continúa buscando primero todo el archivo?
command-line
pipe
utilities
efficiency
Cabra descontento
fuente
fuente
-m
argumento.Respuestas:
Más o menos. El shell no tiene idea de lo que harán los comandos que está ejecutando, solo conecta la salida de uno con la entrada del otro.
Si
grep
encuentra más de 10 líneas que dicen "hola mundo",head
tendrá las 10 líneas que desee y cierre la tubería. Esto provocará lagrep
muerte con un SIGPIPE, por lo que no es necesario que continúe escaneando un archivo muy grande.fuente
grep
que seguiría enviando la salida a un vacío, similar a/dev/null
Cuando un programa intenta escribir en una tubería y no hay una lectura de proceso de esa tubería, el programa escritor recibe una señal SIGPIPE . La acción predeterminada cuando un programa recibe SIGPIPE es terminar el programa. Un programa puede elegir ignorar la señal SIGPIPE, en cuyo caso la escritura devuelve un error (
EPIPE
).En su ejemplo, aquí hay una línea de tiempo de lo que sucede:
grep
y sehead
inician en paralelo.grep
lee alguna entrada, comienza a procesarla.grep
produce un primer fragmento de salida.head
lee ese primer fragmento y lo escribe.grep
podría terminar primero), finalmentehead
habrá impreso el número deseado de líneas. En este punto,head
salidas.grep
yhead
, esgrep
posible que haya acumulado algunos datos y aún no los haya impreso. En el momento en quehead
sale,grep
puede estar leyendo entradas o haciendo un procesamiento interno, en cuyo caso continuará haciéndolo.grep
escribiremos los datos que se procesan. En ese punto, recibirá un SIGPIPE y morirá.Es probable que
grep
procese un poco más de entrada de lo estrictamente necesario, pero generalmente solo unos pocos kilobytes:head
normalmente se lee en fragmentos de unos pocos kilobytes (porque eso es más eficiente que emitir unaread
llamada al sistema para cada byte; este comportamiento se llama almacenamiento en búfer), por lo que el resto del último fragmento después de que se descarta la última línea deseada.grep
puede haber acumulado algunos datos que están listos para convertirse en un fragmento de salida (almacenamiento en búfer de nuevo). Recibirá SIGPIPE cuando intente vaciar su búfer de salida.En general, el sistema está diseñado con precisión para que las utilidades de filtrado se comporten de manera eficiente de manera natural. Los programas que necesitan continuar cuando su canal de salida se extingue deben dar el paso de ignorar la señal SIGPIPE.
fuente
En cierto modo, la canalización funciona así: primero ejecuta el primer comando y luego el segundo comando en su caso.
Es decir, seamos
A|B
el comando dado. Entonces es incierto siA
oB
comienza primero. Pueden comenzar exactamente al mismo tiempo si hay varias CPU. Una tubería puede contener una cantidad de datos indefinida pero finita.Si B intenta leer desde la tubería, pero no hay datos disponibles,
B
esperará hasta que lleguen los datos. SiB
estaba leyendo desde un disco,B
podría tener el mismo problema y necesitar esperar hasta que termine la lectura de un disco. Una analogía más cercana sería leer desde un teclado. Allí,B
tendría que esperar a que un usuario escriba. Pero en todos estos casos, B ha comenzado una operación de "lectura" y debe esperar hasta que termine. Pero siB
es un comando de tal manera que solo necesita una salida parcial, SIGPIPE mataráA
después de cierto punto dondeB
se alcanza el nivel de entrada de s.A
Si
A
intenta escribir en la tubería y la tubería está llena,A
debe esperar a que quede espacio libre en la tubería.A
podría tener el mismo problema si estuviera escribiendo en una terminal. Una terminal tiene control de flujo y puede moderar el ritmo de los datos. En cualquier caso, aA
, ha comenzado una operación de "escritura" y esperará hasta que finalice la operación de escritura.A
yB
se comportan como coprocesos, aunque no todos los coprocesos se comunicarán con una tubería. Ninguno de los dos tiene el control total del otro.fuente
head
sale), se produce una señal SIGPIPE en el programa y el comportamiento predeterminado es salir.grep
no tiene control directo de la tubería (solo está recibiendo datos), y la tubería no tiene control directo degrep
(solo está enviando datos) ...Lo que
grep
, o cualquier otro programa hace, depende completamente de la lógica interna de ese programa. Si le indica agrep
través de las opciones de la línea de comandos que haga una salida temprana cuando se encuentre , entonces lo hará, de lo contrario, continuará hasta el final del archivo buscando el patrón ...La Terminal también está bastante desconectada del funcionamiento interno de
grep
lasshell
acciones de tuberías ... La Terminal es básicamente una plataforma de lanzamiento y una pantalla de salida ...fuente