Comment éviter que echo ferme les pipes FIFO named? - Comportement drôle D'Unix FIFOs

je veux afficher certaines données à un tuyau et le processus de faire quelque chose pour les données ligne par ligne. Voici un jouet exemple:

mkfifo pipe
cat pipe&
cat >pipe

maintenant je peux entrer ce que je veux, et après avoir appuyé sur Entrée je vois immédiatement la même ligne. Mais si substituer deuxième tube avec echo:

mkfifo pipe
cat pipe&
echo "some data" >pipe

la pipe se ferme après echo et cat pipe& finitions de sorte que je ne peux pas passer plus de données à travers le tuyau. Y a-t-il un moyen d'éviter de fermer la conduite et le processus qui reçoit les données, de sorte que je puisse passer de nombreuses lignes de données à travers le tuyau à partir d'un script bash et les faire traiter à leur arrivée?

42
demandé sur limovala 2011-12-07 08:36:30

6 réponses

quand un FIFO est ouvert pour la lecture, il bloque le processus d'appel (normalement). Quand un processus ouvre le FIFO pour l'écriture, alors le lecteur est débloqué. Quand l'auteur ferme le FIFO, le processus de lecture obtient EOF (0 bytes à lire), et il n'y a rien d'autre qui peut être fait sauf fermer le FIFO et rouvrir. Ainsi, vous devez utiliser une boucle:

mkfifo pipe
(while cat pipe; do : Nothing; done &)
echo "some data" > pipe
echo "more data" > pipe

une alternative est de garder un certain processus avec le FIFO ouvert.

mkfifo pipe
sleep 10000 > pipe &
cat pipe &
echo "some data" > pipe
echo "more data" > pipe
40
répondu Jonathan Leffler 2011-12-07 04:48:36

mettez toutes les instructions que vous voulez afficher sur le fifo dans la même sous-couche:

# Create pipe and start reader.
mkfifo pipe
cat pipe &
# Write to pipe.
(
  echo one
  echo two
) >pipe

Si vous avez un peu plus de complexité, vous pouvez ouvrir le tuyau pour l'écriture:

# Create pipe and start reader.
mkfifo pipe
cat pipe &
# Open pipe for writing.
exec 3>pipe
echo one >&3
echo two >&3
# Close pipe.
exec 3>&-
49
répondu Mark Edgar 2011-12-08 19:19:09

Vous pouvez résoudre cela très facilement en ouvrant le côté lecture du tuyau en mode Lecture-écriture. Le lecteur n'a droit à un " EOF " qu'après la fermeture du dernier auteur. Afin de l'ouvrir en lecture-écriture permet de s'assurer qu'il ya toujours au moins un écrivain.

alors changez votre second exemple en:

mkfifo pipe
cat <>pipe &
echo "some data" >pipe
18
répondu Patrick 2016-11-02 22:32:12

Comme une alternative aux autres solutions ici, vous pouvez appeler cat dans une boucle tant que la saisie de votre commande:

mkfifo pipe
(while true ; do cat pipe ; done) | bash

Maintenant vous pouvez lui donner des commandes une à la fois et il ne fermera pas:

echo "'echo hi'" > pipe
echo "'echo bye'" > pipe

Vous devrez tuer le processus quand vous voulez, elle a disparu, bien sûr. Je pense que c'est la solution la plus pratique car elle vous permet de spécifier le comportement de non-sortie que vous créez le processus.

1
répondu Adam Dingle 2014-09-14 19:25:17

j'ai amélioré la deuxième version de la réponse de Jonathan Leffler pour soutenir la fermeture de la pipe:

dir=`mktemp -d /tmp/temp.XXX`
keep_pipe_open=$dir/keep_pipe_open
pipe=$dir/pipe

mkfifo $pipe
touch $keep_pipe_open

# Read from pipe:
cat < $pipe &

# Keep the pipe open:
while [ -f $keep_pipe_open ]; do sleep 1; done > $pipe &

# Write to pipe:
for i in {1..10}; do
  echo $i > $pipe
done

# close the pipe:
rm $keep_pipe_open
wait

rm -rf $dir
1
répondu silyevsk 2015-01-19 16:18:50

honnêtement, le meilleur moyen que j'ai trouvé pour que ça marche était d'utiliser