Je veux générer une liste triée avec tous les nombres à 8 chiffres - de 00000000 à 99999999. J'ai tapé dans le 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 réponse est
bash: echo: write error: Interrupted system call
bash: echo: write error: Interrupted system call
bash: echo: write error: Interrupted system call
99998890
Pourquoi ai-je ces trois erreurs et result.txt malformé?
j'utilise
GNU bash, version 4.4.12 (1) -release (x86_64-pc-linux-gnu)
Debian GNU / Linux 9.6 (stretch)
Noyau Linux: 4.19.0 # 2 SMP jeu 1 nov 15:31:34 EET 2018 x86_64 GNU / Linux
seq -w 0 99999999
.}
) fonctionne correctement. @ GAD3Rkonsole
fenêtre. Un tel redimensionnement est presque suffisant dans mon cas, mais pas nécessaire.| tee result.txt
, et toujours obtenir l'erreur./bin/echo
dans mon cas) au lieu deecho
la fonction intégrée rend la fonction immunisée (ou du moins moins sujette) à ce problème.Réponses:
L'
write error: Interrupted system call
erreur spécifique est générée lorsque la taille de la fenêtre de la console est modifiée pendant l'exécution du script.Faire un:
va l'éviter.
Notez qu'un
Sera à la fois plus rapide et évitera le
SIGWINCH
problème.la source
Il s'agit en fait d'un bug [1] dans
bash
, et cela ne se produit pas seulement surSIGWINCH
, mais aussi sur n'importe quel signal pour lequel une interruption a été définie:Cela se produit car
bash
ne parvient pas à a) définir ses gestionnaires de signaux avecSA_RESTART
(à l'exception duSIGCHLD
gestionnaire), ou b) à gérer leEINTR
lors de l'appelwrite()
dans les commandes internesprintf
etecho
.EINTR
("Appel système interrompu") n'est pas un moyen d'indiquer une condition d'erreur, mais un hack qui permet au programmeur de combiner le blocage des lectures / écritures / etc avec le traitement des signaux dans la boucle principale. Il ne doit jamais être divulgué à l'utilisateur.Ce bogue n'apparaît pas trop souvent car c'est tout un exploit de mettre en place les bonnes conditions: le
write()
devrait être fait par un builtin (pas par une commande externe), il devrait remplir le buffer de pipe (le lecteur à l'autre end doit être beaucoup plus lent ou ne pas lire du tout, mais toujours vivant ), et le script doit utiliser des interruptions ou la fenêtre du terminal doit être redimensionnée.Et en raison de divers artefacts d'implémentation, cela n'affecte que les
write()
s interrompus , pas lesread()
s ou lesopen()
s (comme par exemple le blocageopen()
d'un canal / fifo nommé).[1] une forme de cela a déjà été signalée il y a quelque temps.
la source