46 votes

Comment puis-je corriger une erreur de tuyau cassé ?

J'ai récemment réinstallé RVM (en suivant les instructions du site http://rvm.io ) après une nouvelle installation d'Ubuntu 12.10 lorsque j'ai obtenu un disque SSD.

Maintenant, quand je tape : type rvm | head -1

Je reçois l'erreur suivante :

rvm is a function
-bash: type: write error: Broken pipe

Mais si je répète immédiatement l'ordre, je ne fais que recevoir :

rvm is a function

Et il semble que tout soit en ordre ? Que se passe-t-il ? Que puis-je faire pour y remédier ? Cela ne se produit pas toujours. Il semble que ce soit plus sporadique. J'ai essayé de trouver un modèle, mais je n'y suis pas parvenu.

63voto

James Mertz Points 390

Il est rare, mais normal, de voir "Broken pipe" (tuyau cassé) dans cette situation.

Lorsque vous exécutez type rvm | head -1 bash exécute type rvm en un seul processus, head -1 dans un autre. 1 La sortie stdout de type est connecté à l'extrémité "écriture" d'un tuyau , le stdin de head à l'extrémité "lecture". Les deux processus se déroulent en même temps.

En head -1 lit des données à partir de stdin (généralement par morceaux de 8 kB), imprime une seule ligne (en fonction de l'attribut -1 ), et sort, provoquant la fermeture de l'extrémité "lecture" du tuyau. Puisque l'option rvm est assez longue (environ 11 kB après avoir été analysée et reconstruite par bash), ce qui signifie que la fonction head sort pendant que type a encore quelques Ko de données à écrire.

À ce stade, étant donné que type essaie d'écrire dans un tuyau dont l'autre extrémité a été fermée - une cassé pipe - la fonction write() qu'elle appelle renverra une erreur EPIPE, traduite par "Broken pipe". En plus de cette erreur, le noyau envoie également le signal SIGPIPE à la fonction type qui, par défaut, tue le processus immédiatement.

(Ce signal est très utile dans les shells interactifs, car la plupart des utilisateurs ne souhaitent pas que le premier processus continue à s'exécuter et à essayer d'écrire nulle part. Par ailleurs, les services non interactifs ignorent SIGPIPE - il ne serait pas bon qu'un démon fonctionnant depuis longtemps meure sur une erreur aussi simple - et trouvent donc le code d'erreur très utile).

Cependant, la délivrance du signal n'est pas immédiate à 100 %, et il peut arriver que write() renvoie EPIPE et que le processus continue à fonctionner pendant un court moment avant de recevoir le signal. Dans ce cas, type a suffisamment de temps pour remarquer l'échec de l'écriture, traduire le code d'erreur et même imprimer un message d'erreur sur stderr avant d'être tué par SIGPIPE. (Le message d'erreur indique "-bash : type :" puisque type est une commande intégrée à bash).

Cette situation semble plus fréquente sur les systèmes multi-CPU, étant donné que le nombre d'unités de traitement de l'information est inférieur à celui des unités de traitement de l'information. type et le code de distribution des signaux 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 Parcheandola type (dans le code source de bash) pour sortir immédiatement lorsqu'il reçoit un EPIPE de la fonction write().

Toutefois, il n'y a pas lieu de s'inquiéter et cela n'a rien à voir avec votre rvm l'installation de quelque manière que ce soit.

31voto

Jason Grey Points 31

Vous pouvez réparer un tuyau cassé au détriment d'un autre processus en insérant tail -n +1 dans votre pipe, comme ceci :

type rvm | tail -n +1 | head -1

En +1 raconte tail pour imprimer la première ligne d'entrée et tout ce qui suit. La sortie sera exactement la même que si tail -n +1 n'était pas là, mais le programme est assez intelligent pour vérifier la sortie standard et ferme le tuyau proprement. Il n'y a plus de tuyaux cassés .

3voto

Miao1007 Points 131

Essayons avec yes un processus d'impression sans fin oui...

Auparavant, le yes a été tué par SIGPIPE lorsqu'il a atteint sa limite.

 set -o pipefail
 yes | head -n 1
y
 echo $?        
141

Ma solution

 yes | (head -n 1;dd status=none of=/dev/null)
y

# the process will still running and output to null

Vous pouvez remplacer yes avec votre programme.

2voto

zancox Points 21

En [write error: Broken pipe](https://stackoverflow.com/questions/20573282/hudson-yes-standard-output-broken-pipe) se réfère à un processus d'écriture qui tente d'écrire sur un tuyau alors qu'il n'y a plus de lecteurs à l'extrémité lecture de ce tuyau et à la circonstance particulière que le message SIGPIPE est ignoré par le processus en cours ou par le processus parent. Si c'est le processus parent qui a défini SIGPIPE soit ignorée, il n'est pas possible pour le processus enfant de l'annuler à nouveau dans un Shell non interactif.

Cependant, il est possible de tuer type rvm cuando head -1 se termine en utilisant des sous-coquilles explicites. De cette manière, nous pouvons mettre en arrière-plan type rvm , envoyer typepid à la head -1 puis mettre en place un piège sur EXIT pour tuer type rvm explicitement.

trap "" PIPE        # parent process sets SIGPIPE to be ignored
bash                # start child process
export LANG=C
# create a fake rvm function
eval "
rvm() {
$(printf 'echo line of rvm code %s\n' {1..10000})
}
"

# rvm is a function
# bash: type: write error: Broken pipe
type rvm | head -1

# kill type rvm when head -1 terminates
# sleep 0: do nothing but with external command
( (sleep 0; type rvm) & echo ${!} ; wait ${!} ) | 
    (trap 'trap - EXIT; kill "$typepid"; exit' EXIT; typepid="$(head -1)"; head -1)

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X