Предотвратите автоматические EOFs по именованному каналу и отправьте EOF, когда я захочу

У меня есть программа, которая автоматически выходит при чтении EOF в данном потоке (в следующем случае, stdin).
Теперь я хочу создать сценарий оболочки, который создает именованный канал и подключает к нему стандартный stdin. Затем сценарий записывает в трубку несколько раз, используя echo и cat (и другие инструменты, которые автоматически генерируют EOF, когда они выходят). Проблема, с которой я сталкиваюсь, заключается в том, что когда выполняется первое echo , он отправляет EOF в трубу и выдает программу. Если я использую что-то вроде tail -f то я не могу отправить EOF, когда я намерен выйти из программы. Я исследую сбалансированное решение, но безрезультатно.
Я уже нашел, как предотвратить EOF и как вручную отправить EOF, но я не могу их комбинировать. Есть ли намек?

 #!/bin/sh mkfifo P program < P & : # Run in background # < P tail -n +1 -f | program echo some stuff > P # Prevent EOF? cat more_stuff.txt > P # Prevent EOF? send_eof > P # How can I do this? # fg 

Как указывали другие, читатель трубы получает EOF, когда нет писателей. Таким образом, решение состоит в том, чтобы убедиться, что всегда существует один писатель, который держит его открытым. Этот писатель не должен ничего посылать, просто держите его открытым.

Поскольку вы используете сценарий оболочки, самым простым решением является указание оболочке открыть канал для записи. И затем закройте его, когда закончите.

 #!/bin/sh mkfifo P exec 3>P # open file descriptor 3 writing to the pipe program < P # < P tail -n +1 -f | program echo some stuff > P cat more_stuff.txt > P exec 3>&- # close file descriptor 3 

Обратите внимание, что если вы опустите последнюю строку, дескриптор файла 3 будет автоматически закрыт (и, таким образом, читатель получит EOF), когда скрипт выйдет. Помимо удобства, это также обеспечивает безопасность, если сценарий должен как-то прекратиться раньше.

Труба получает EOF, когда последний писатель уходит. Чтобы этого избежать, убедитесь, что всегда есть писатель (процесс, который открывает канал для записи, но на самом деле ничего не пишет). Чтобы отправить EOF, сделайте, чтобы резервный автор ушел.

 mkfifo P while sleep 1; do :; done >P & P_writer_pid=$! send_eof_to_P () { kill $P_writer_pid } 

Программа не может различать EOF, что означает «пришло время бросить» и EOF, что означает, что «писатель сделан, но может быть больше информации от кого-то другого».

Если у вас есть возможность изменить поведение вашей программы, выполните чтение в бесконечном цикле (одна итерация длится до EOF) и отправьте ему конкретную командную строку, которая означает «время выхода». Отправка этой строки будет задачей команды send_eof в вашем вопросе.

Другой вариант:

 ( echo some stuff; cat more_stuff.txt ) >P 

или

 { echo some stuff; cat more_stuff.txt; } >P