2011-05-10 4 views
15

Envisagez le scénario suivant:Empêcher FIFO de fermeture/réutilisation fermée FIFO

un FIFO nommé test est créé. Dans une fenêtre de terminal (A) je cours cat <test et dans un autre (B) cat >test. Il est maintenant possible d'écrire dans la fenêtre B et d'obtenir la sortie dans la fenêtre A. Il est également possible de terminer le processus A et de le relancer tout en continuant à utiliser cette configuration comme suspectée. Toutefois, si vous terminez le processus dans la fenêtre B, B (pour autant que je sache) envoie un EOF via le FIFO pour traiter A et mettre fin à cela aussi. En fait, si vous exécutez un processus qui ne se termine pas sur EOF, vous ne pourrez toujours pas utiliser votre FIFO que vous avez redirigé vers le processus. Ce que je pense, c'est que ce FIFO est considéré comme fermé.

Est-il possible de contourner ce problème?

La raison pour laquelle j'ai rencontré ce problème est que je voudrais envoyer des commandes à mon serveur minecraft en cours d'exécution dans une session d'écran. Par exemple: echo "command" >FIFO_to_server. C'est probablement possible de faire en utilisant l'écran seul mais je ne suis pas très à l'aise avec l'écran je pense qu'une solution utilisant uniquement des tuyaux serait plus simple et plus propre.

Répondre

26

A lit à partir d'un fichier. Quand il atteint la fin du fichier, il arrête de lire. C'est un comportement normal, même si le fichier est un fifo. Vous avez maintenant quatre approches.

  1. Modifiez le code du lecteur pour qu'il continue de lire après la fin du fichier. Cela signifie que le fichier d'entrée est infini et que l'atteinte de la fin du fichier n'est qu'une illusion. Pas pratique pour vous, car vous devrez changer le code du serveur minecraft.
  2. Appliquer la philosophie Unix. Vous avez un écrivain et un lecteur qui ne sont pas d'accord sur le protocole, donc vous interposez un outil qui les relie. En l'occurrence, il existe un tel outil dans la boîte à outils unix: tail -f. tail -f continue à lire à partir de son fichier d'entrée même après qu'il voit la fin du fichier. Faites tous vos clients parlent à la conduite, et se connecter tail -f au serveur minecraft:

    tail -n +1 -f client_pipe | minecraft_server & 
    
  3. As mentioned by jilles, utiliser une astuce: pipes soutiennent les auteurs multiples, et ne se ferment lorsque le dernier écrivain va. Alors assurez-vous qu'il y a un client qui ne s'en va jamais.

    while true; do sleep 999999999; done >client_pipe & 
    
  4. Le problème est que le serveur est fondamentalement conçu pour gérer un seul client. Pour gérer plusieurs clients, vous devez utiliser un socket. Considérez les sockets comme des «méta-pipes»: la connexion à un socket crée un canal, et une fois que le client se déconnecte, ce canal particulier est fermé, mais le serveur peut accepter plus de connexions. C'est l'approche propre, car elle garantit également que vous n'aurez pas de données mélangées si deux clients se connectent en même temps (en utilisant des tuyaux, leurs commandes peuvent être intercalées). Cependant, cela nécessite de changer le serveur minecraft.

+0

Malheureusement, 'tail' attend EOF pour qu'il ne passe pas le contenu du pipeline ligne par ligne. – pabouk

+2

@pabouk Merci d'avoir signalé ce bug: 'tail -n 1 -f' ignorerait l'entrée qui était disponible avant qu'elle ne démarre ou ne soit disponible plus rapidement qu'elle ne pourrait en lire.Je voulais écrire 'tail -n +1 -f', qui commence immédiatement à sortir. – Gilles

+2

Merci. Je l'ai déjà essayé mais '-n + 1' ne fonctionnait pas comme prévu. Maintenant que vous avez confirmé que c'est la bonne façon, j'ai examiné le problème plus loin et j'ai réalisé que le problème est dans la mise en mémoire tampon des blocs (au lieu de la mise en mémoire tampon par défaut) de la queue de tail. La solution pour la tuyauterie ligne par ligne: 'stdbuf -oL tail -n +1 -f client_pipe | command ' – pabouk

6

Commencez un processus qui maintient le FIFO ouvert pour l'écriture et continue à fonctionner indéfiniment. Cela empêchera les lecteurs de voir une condition de fin de fichier.