Voir "Pipe cassée" dans cette situation est rare, mais normal.
Lorsque vous exécutez type rvm | head -1
, bash s'exécute type rvm
dans un processus, head -1
dans un autre. 1 La sortie standard de type
est connectée à l'extrémité "écriture" d'un tuyau , la sortie standard head
à l'extrémité "lecture". Les deux processus s'exécutent en même temps.
Le head -1
processus lit les données de stdin (généralement par blocs de 8 Ko), imprime une seule ligne (selon l' -1
option) et se ferme, provoquant la fermeture de l'extrémité "lecture" du tuyau. Étant donné que la rvm
fonction est assez longue (environ 11 kB après avoir été analysée et reconstruite par bash), cela signifie que la head
sortie type
a encore quelques kB de données à écrire.
À ce stade, puisque type
tente d'écrire sur un tuyau dont l'autre extrémité a été fermée - un tuyau cassé - la fonction write () qu'elle a appelée renverra une erreur EPIPE, traduite par "tuyau cassé". En plus de cette erreur, le noyau envoie également le signal SIGPIPE à type
, qui par défaut tue immédiatement le processus.
(Le signal est très utile dans les shells interactifs, car la plupart des utilisateurs ne veulent pas que le premier processus continue de fonctionner et essaie d'écrire nulle part. Pendant ce temps, les services non interactifs ignorent SIGPIPE - il ne serait pas bon pour un démon de longue durée de mourir sur une erreur aussi simple - ils trouvent donc le code d'erreur très utile.)
Cependant, la livraison du signal n'est pas 100% immédiate, et il peut y avoir des cas où write () renvoie EPIPE et le processus continue de s'exécuter pendant un court moment avant de recevoir le signal. Dans ce cas, type
obtient suffisamment de temps pour remarquer l'échec de l'écriture, traduire le code d'erreur et même imprimer un message d'erreur à stderr avant d'être tué par SIGPIPE. (Le message d'erreur indique "-bash: type:" car il type
s'agit d'une commande intégrée de bash lui-même.)
Cela semble être plus courant sur les systèmes multi-CPU, car le type
processus et le code de livraison du signal du noyau peuvent s'exécuter sur différents cœurs, littéralement en même temps.
Il serait possible de supprimer ce message en type
corrigeant le code intégré (dans le code source de bash) pour qu'il se ferme immédiatement lorsqu'il reçoit un EPIPE de la fonction write ().
Cependant, il n'y a rien à craindre et ce n'est en aucun cas lié à votre rvm
installation.
ls
throughhead -1
depuis des années, et aujourd'hui je reçois un message de pipe cassé.Vous pouvez réparer un tuyau cassé au détriment d'un autre processus en l'insérant
tail -n +1
dans votre tuyau, comme ceci:Le
+1
dittail
d'imprimer la première ligne d'entrée et tout ce qui suit. La sortie sera exactement la même que si elletail -n +1
n'était pas là, mais le programme est assez intelligent pour vérifier la sortie standard et ferme proprement le tuyau. Plus de tuyaux cassés .la source
find /var/lib/mysql -xdev -type f -daystart -mmin +5 -print0 | xargs -0 ls -ldt | tail -n +1 | head
produit de manière fiablexargs: ls: terminated by signal 13
. Comme nous le savons, le problème est celui de l'épuisement des entrées et il n'y a vraiment qu'une seule commande qui traite de la mise en mémoire tampon: dd. L'ajout| dd obs=1M
au pipeline corrige le SIGPIPE pour mon cas d'utilisation.type rvm | (head -1 ; dd of=/dev/null)
Ceci, bien sûr, est similaire à d'autres suggestions car il provoque le traitement de toutes les entrées , maisdd
devrait être le programme le plus efficace pour gérer de telles choses.Le
write error: Broken pipe
message fait référence à un processus d'écriture qui essaie d'écrire sur un canal sans aucun lecteur à l'extrémité de lecture de ce canal et à la circonstance spéciale que leSIGPIPE
signal est défini pour être ignoré par le processus actuel ou parent. Si c'est le processus parent qui a été définiSIGPIPE
pour être ignoré, il n'est pas possible pour le processus enfant de l'annuler à nouveau dans un shell non interactif.Cependant, il est possible de tuer une
type rvm
foishead -1
terminé en utilisant des sous-coquilles explicites. De cette façon, nous pouvons créer un arrièretype rvm
- plan , envoyertypepid
auhead -1
sous - shell, puis implémenter un piègeEXIT
là-bas pour tuertype rvm
explicitement.la source
type
obtient suffisamment de temps pour remarquer l'échec de l'écriture, traduire le code d'erreur et même imprimer un message d'erreur à stderr avant d'être tué par SIGPIPE . Je pense que votre solution n'empêche pas le processus producteur (type
ici) de réagir à l'écriture échouée (en raison de la fermeture du tuyau), n'est-ce pas?