bash: echo: error de escritura: llamada interrumpida del sistema

9

Quiero generar una lista ordenada con todos los números de 8 dígitos, desde 00000000 hasta 99999999. Escribí en el shell:

f() {
 while IFS="" read -r line; do
   for i in {0..9}; do 
       echo "$line$i";
   done;
 done
}

echo | f | f | f | f | f | f | f | f | tee result.txt | wc -l

la respuesta es

bash: echo: write error: Interrupted system call
bash: echo: write error: Interrupted system call
bash: echo: write error: Interrupted system call
99998890

¿Por qué obtuve estos tres errores y result.txt con formato incorrecto?

yo suelo

GNU bash, versión 4.4.12 (1) -release (x86_64-pc-linux-gnu)

Debian GNU / Linux 9.6 (estiramiento)

Kernel de Linux: 4.19.0 # 2 SMP jue 1 de noviembre 15:31:34 EET 2018 x86_64 GNU / Linux

cariño
fuente
2
No puedo evitar sentir que esta forma de hacerlo no sería más eficiente que seq -w 0 99999999.
Kusalananda
1
Entonces la pregunta está incompleta / incorrecta / mal escrita u otra cosa. Porque el script (cuando se completa con }) funciona correctamente. @ GAD3R
Isaac
1
Nota: Puedo activar estos errores casi a pedido. A menudo aparecen cuando cambio el tamaño de mi konsoleventana. Tal cambio de tamaño es casi suficiente en mi caso, pero no es necesario.
Kamil Maciorowski
Puedo eliminar el | tee result.txty aún obtener el error.
ctrl-alt-delor
Otra nota: el ejecutable externo ( /bin/echoen mi caso) en lugar de echoincorporado hace que la función sea inmune (o al menos menos propensa) a este problema.
Kamil Maciorowski

Respuestas:

6

El write error: Interrupted system callerror específico se genera cuando se cambia el tamaño de la ventana de la consola mientras se ejecuta el script.

Haciendo un:

 trap '' SIGWINCH

Lo evitaré.

Tenga en cuenta que un

 seq 99999999 >result.txt; wc -l <result.txt

Será a la vez más rápido y evitará el SIGWINCHproblema.

Isaac
fuente
55
Entonces, ¿qué está pasando ?, ¿por qué no he visto esto antes ?, ¿por qué es un error de escritura, lo correcto?
ctrl-alt-delor
4

Esto es en realidad un error [1] en bash, y esto no sucede sólo en SIGWINCH, sino también en cualquier señal para la que se estableció una trampa:

{ pid=$BASHPID; trap : USR1; (sleep 1; kill -USR1 $pid) &
         printf %0100000d 1; } | sleep 3600
bash: printf: write error: Interrupted system call

Ocurre porque basha) no establece a) sus manejadores de señal con SA_RESTART(excepto el SIGCHLDmanejador), o b) maneja el EINTRal llamar write()en los builtins printfy echo.

EINTR("Llamada de sistema interrumpida") no es una forma de indicar una condición de error, sino un truco que permite al programador combinar el bloqueo de lecturas / escrituras / etc. con el manejo de señales en el bucle principal. Nunca se debe filtrar al usuario.

Este error no aparece con demasiada frecuencia porque es una hazaña lograr las condiciones correctas en su lugar: write()debe hacerse por un builtin (no por un comando externo), debe llenar el buffer de la tubería (el lector en el otro El final debe ser mucho más lento o no leer desde la tubería, pero aún estar vivo ), y el script debe usar trampas o la ventana del terminal debe ser redimensionada.

Y debido a los diversos artefactos de implementación, esto solo afecta a write()s interrumpidos , no read()s o open()s (como, por ejemplo, el bloqueo open()de una tubería con nombre / fifo).

[1] una forma de esto ya se informó hace algún tiempo.

Mosvy
fuente