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?
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
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>&-
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
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.
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