Запретить закрытие FIFO / повторное использование закрытого FIFO - PullRequest
17 голосов
/ 11 мая 2011

Рассмотрим следующий сценарий:

FIFO с именем test создан. В одном окне терминала (A) я запускаю cat <test, а в другом (B) cat >test. Теперь можно писать в окне B и получать выходные данные в окне A. Также возможно завершить процесс A и перезапустить его, и при этом можно использовать эту настройку как подозревается. Однако, если вы прервете процесс в окне B, B (насколько я знаю) отправит EOF через FIFO для обработки A и также прекратит его.

Фактически, если вы запустите процесс, который не завершается в EOF, вы все равно не сможете использовать свой FIFO, перенаправленный в процесс. Я думаю, это потому, что этот FIFO считается закрытым.

Есть ли способ обойти эту проблему?

Причина, по которой я столкнулся с этой проблемой, заключается в том, что я хотел бы отправлять команды на мой сервер minecraft, работающий в сеансе экрана. Например: echo "command" >FIFO_to_server. Вероятно, это возможно сделать, используя сам экран, но мне не очень удобно с экраном. Я думаю, что решение, использующее только трубы, было бы проще и чище.

Ответы [ 3 ]

29 голосов
/ 11 мая 2011

A читает из файла. Когда он достигает конца файла, он перестает читать. Это нормальное поведение, даже если файл оказался fifo. Теперь у вас есть четыре подхода.

  1. Измените код читателя, чтобы он продолжал читать после конца файла. Это говорит о том, что входной файл бесконечен, и достижение конца файла - просто иллюзия. Непрактично для вас, потому что вам придется изменить код сервера minecraft.
  2. Применить философию Unix. У вас есть писатель и читатель, которые не согласны с протоколом, поэтому вы используете инструмент, который их связывает. Так случилось, что в наборе инструментов unix есть такой инструмент: tail -f. tail -f продолжает чтение из своего входного файла даже после того, как он видит конец файла. Заставьте всех ваших клиентов общаться с каналом и подключите tail -f к серверу minecraft:

    tail -n +1 -f client_pipe | minecraft_server &
    
  3. Как упомянуто Джиллсом , используйте хитрость: каналы поддерживают несколько писателей и закрываются, только когда последний писатель уходит. Поэтому убедитесь, что есть клиент, который никогда не уйдет.

    while true; do sleep 999999999; done >client_pipe &
    
  4. Проблема в том, что сервер в основном предназначен для работы с одним клиентом. Для работы с несколькими клиентами вы должны перейти на использование сокета. Думайте о сокетах как о «мета-каналах»: подключение к сокету создает канал, и как только клиент отключается, этот конкретный канал закрывается, но сервер может принимать больше подключений. Это чистый подход, поскольку он также гарантирует, что вы не перепутаете данные, если два клиента подключатся одновременно (используя каналы, их команды могут быть перемежены). Тем не менее, это требует изменения сервера Minecraft.

7 голосов
/ 11 мая 2011

Запустите процесс, который сохраняет fifo открытым для записи и работает бесконечно долго. Это не позволит читателям увидеть условие конца файла.

0 голосов
/ 25 октября 2018

Вы можете добавить несколько входных данных в трубу, добавив в скобках то, что вам нужно, в скобках с точкой с запятой:

(cat file1; cat file2; ls -l;) > yourpipe
...