Selon sa documentation, bash attend que toutes les commandes d'un pipeline aient fini de s'exécuter avant de continuer
Le shell attend que toutes les commandes du pipeline se terminent avant de renvoyer une valeur.
Alors pourquoi la commande se yes | true
termine-t-elle immédiatement? La yes
boucle ne devrait-elle pas indéfiniment et empêcher le pipeline de revenir?
Et une sous-question: selon la spécification POSIX , les pipelines shell peuvent choisir de retourner après la fin de la dernière commande ou d'attendre que toutes les commandes se terminent. Les coquilles communes ont-elles un comportement différent dans ce sens? Y a-t-il des obus yes | true
qui boucleront pour toujours?
yes | tee >(true) >/dev/null
fera ce que vous attendez, btw, comme celatee
continue jusqu'à ce que tous les écrivains soient morts, donc latrue
sortie ne le perturbera pas complètement.true
est fondamentalement un{return 0;}
programme, donc je ne m'attendrais pas à ce qu'il fonctionne pendant longtemps, et encore moins pour toujours.Réponses:
À la
true
sortie, le côté lecture du tuyau est fermé, maisyes
continue d'essayer d'écrire sur le côté écriture. Cette condition est appelée "pipe cassée", et elle amène le noyau à envoyer unSIGPIPE
signal àyes
. Puisqueyes
ne fait rien de spécial sur ce signal, il sera tué. S'il ignorait le signal, sonwrite
appel échouerait avec un code d'erreurEPIPE
. Les programmes qui font cela doivent être prêts à remarquerEPIPE
et à arrêter d'écrire, sinon ils entreront dans une boucle infinie.Si vous faites
strace yes | true
1, vous pouvez voir le noyau se préparer pour les deux possibilités:strace
surveille les événements via l'API de débogage, qui lui indique d'abord le retour de l'appel système avec une erreur, puis le signal. Duyes
point de vue, cependant, le signal arrive en premier. (Techniquement, le signal est délivré après que le noyau retourne le contrôle dans l'espace utilisateur, mais avant que d'autres instructions machine ne soient exécutées, donc la fonctionwrite
"wrapper" de la bibliothèque C n'a pas la possibilité de définirerrno
et de revenir à l'application.)1 Malheureusement, il
strace
est spécifique à Linux. La plupart des Unix modernes ont une commande qui fait quelque chose de similaire, mais elle a souvent un nom différent, elle ne décode probablement pas les arguments syscall aussi complètement, et parfois elle ne fonctionne que pour root.la source
yes
n'est connecté au tuyau.yes
d'obtenir SIGPIPE, car le FD sur lequel il écrit n'est pas connecté à un tuyau.yes >/dev/null
pour toujours. Il ne montre rien du tout sur les pipelines qui ne soit pas également vrai pour les commandes simples (comme le comportement en attente de terminaison que Tom souligne est également vrai pour les commandes simples).write()
(la fonction dans libc) ne revient pas (contrôle du transfert vers le PC qui le suit) qu'après le gestionnaire de signaux s'est exécuté, mais puisque le gestionnaire de signaux termine le programme, le contrôle n'est jamais transféré etwrite()
ne revient donc jamais. Oui, cela est implémenté dans le noyau en ayant unxxx_write()
retour de fonction-EPIPE
, mais nous déboguons un programme d'espace utilisateur et ne nous intéressons pas à cela.Peu probable, car la
yes
commande utilise le tuyau, et il échouera lorsque le tuyau sera cassé.sleep
d'autre part, n'utilise pas le tuyau, donc:fonctionnera pendant 100000000 secondes, au moins.
la source
true
trouve une commande intégrée. Ceci est valable pour les versions récentes duBourne Shell
,ksh93
,zsh
. Si vous frappez^Z
lorsqu'une telle commande est en cours d'exécution, cela suspendra le sommeil et le shell ne pourra jamais récupérer sans aide externe.sbrk()
. Une version portable et maintenue est dans le paquet d'outils schily et @Charles Duffy a déjà découvert un emplacement pour obtenir des informations ;-)bsh
(Berthold Shell de VBERTOS, une version améliorée de la mémoire virtuelle d'UNOS - le premier clone UNIX). Bsh a obtenu de nombreuses fonctionnalités csh en 1984 et 1985, mais le mécanisme d'alias d'UNOS était déjà supérieur à celui de csh en 1980. D'autres nouvelles fonctionnalités de Bourne Shell proviennent de POSIX, pour lui permettre d'approcher la conformité POSIX.