Si je lance simplement read
, il lit une ligne et se ferme immédiatement lorsque Enter est pressé.
$ read
typing something here
$
Cependant, lorsque je passe l’entrée à travers un tuyau, par ex. from cat
, read
se comporte différemment et continue à s'exécuter jusqu'à ce qu'il rencontre la deuxième nouvelle ligne:
$ cat | read
typing first line
typing second line
$
Quelqu'un peut-il expliquer pourquoi c'est comme ça?
PS: Cette question a été inspirée par Comment alimenter l’entrée standard et le vider dans un fichier en même temps?
Cela n'a rien à voir avec la nouvelle ligne.
Si vous exécutez votre commande en utilisant strace
, vous découvrirez que le cat
recevra un SIGPIPE
à la fin, avant d'être fermé:
$ strace cat | read
...
someOutput
...
+++ killed by SIGPIPE +++
cat
doit être exécutée.read
.cat
est toujours en cours d'exécution et attend un EOF.Cette fois, il ne peut pas être transmis à read
, car il n'y a plus de read
en attente d'entrée (il a été fermé après le premier tuyau) à moins que vous ne le lanciez comme ceci:
cat | while read line; do echo $line; done;
cat
recevra un SIGPIPE
et sera fermé.Un processus reçoit un SIGPIPE lorsqu'il tente d'écrire dans un canal (nommé ou non) ou un socket de type SOCK_STREAM qui n'a plus de lecteur. [1]
La réception de SIGPIPE
se produit après lorsque le second canal de communication se produit.
Par exemple, considérez la commande yes
, car une commande telle que yes
dirige quelque chose rapidement et de manière répétée:
yes | read
il se ferme immédiatement après le deuxième tuyau, faites attention aux deux appels write()
:
close(3) = 0
write(1, "y\ny\ny\ny\ny\ny\ny\ny\ny\n"..., 8192) = 8192
write(1, "y\ny\ny\ny\ny\ny\ny\ny\ny\n"..., 8192) = -1 EPIPE (Broken pipe)
--- SIGPIPE {si_signo=SIGPIPE, si_code=SI_USER, si_pid=3542, si_uid=1000} ---
+++ killed by SIGPIPE +++
Cependant, étant donné que la commande yes
est trop rapide, vous pouvez voir plus de deux appels write()
, mais si vous l'exécutez plusieurs fois, vous ne verrez qu'au moins deux appels et jamais un.