2012-04-05 12 views
17

Este es un comando canalizado para generar 10 caracteres de la contraseña al azar:¿Por qué termina esta tubería?

cat /dev/urandom | base64 | head -c 10 

Mi pregunta es cat /dev/urandom | base64 es un flujo de salida infinito que no se detendrá por sí mismo. ¿Pero por qué anexar head -c 10 termina toda la tubería? Supongo que cat, base64 y head son 3 procesos separados, ¿cómo puede head terminar el cat?

Respuesta

11

Después de base64 salidas 10 bytes, head obtiene suficientes entradas y salidas. Cuando el primero intente generar más bytes, recibirá SIGPIPE signal y, por lo tanto, también saldrá. Por el mismo motivo, cat saldrá por turno.

23

head cierra el archivo de entrada después de leer la cantidad requerida. cuando una tubería se cierra desde un lado, el otro lado recibe errores de escritura; esto hace que base64 se cierre, lo que a su vez hace que cat se cierre.

+7

Probablemente valga la pena mencionar que la única razón por la cual 'head' recibe alguna entrada es que' base64' escribe la salida después de obtener una cierta cantidad de entrada, es decir, cuando su buffer está lleno. Si fuera a leer hasta EOF, estaría leyendo para siempre, y 'head 'nunca conseguiría una grieta en nada de eso. Entonces, un canal similar, como 'cat/dev/urandom | suma | head -c 10' se comportaría de manera diferente, ya que 'sum' espera EOF. –

+3

s/recibe errores de escritura/recibe SIGPIPE/ –

+1

El comentario de Rob es * extremadamente * relevante. Si el proceso hereda un controlador SIGPIPE o ignora SIGPIPE (p. Ej., Si se ejecuta en el subproceso de intérpretes python más antiguo) y no verifica los errores de escritura, no finalizará. Hay una * gran * diferencia entre un error de escritura y recibir un SIGPIPE, y los programas que ignoran ambos problemas son propensos a ejecutarse indefinidamente. –

4

Piping funciona mediante la conexión de la salida de un proceso de A a la entrada de B. La conexión puede romperse, cuando

  • A cierra su salida. B obtendrá EOF.
  • B cierra su entrada. A obtendrá un error que indica que la salida ya no está disponible cuando intenta escribir el siguiente byte.

Dado que estos dos casos son muy comunes, el manejo se ha movido a la libra estándar C.

+0

Gracias, pero ¿qué significa "el manejo se ha movido a la libra estándar C" significa? ¿A y B terminan en shell en lugar de que detecten el cierre de entrada/salida y se detengan? – Dagang

+0

Cuando B cierra su lado de la tubería, A recibirá una señal. El código en las rutinas de E/S de la biblioteca estándar c.lib ('fprintf()', 'open()', 'read()', ...) maneja la señal y la función devolverá el error EPIPE = "Tubo roto". –

+1

@ AaronDigulla, no estoy de acuerdo. No conozco ninguna biblioteca C que instale un controlador SIGPIPE, ni mis experimentos lo sugieren. De hecho, se entrega SIGPIPE, lo que hace que cualquier programa que no haya instalado un controlador (es decir, el 99% de todos los programas) salga. –

Cuestiones relacionadas