В чем разница между этими четырьмя командами (fifo, замена процесса, перенаправление ...)

8

Моя цель - создать простой эхо-сервер с использованием ncодного fifo. Я не ищу лучший способ сделать это, я просто пытаюсь понять семантику следующих команд (когда происходит форк, почему, что это меняет, почему команды ведут себя по-разному ...).

Я использую Bash, так что я не уверен , что все команды будут работать с POSIX shили zsh, ksh...

Вот четыре команды, которые я упоминаю в названии (при условии, что я уже сделал mkfifo fifo):

cat fifo | nc -l localhost 8888 > fifo
exec 3<> fifo && nc -l localhost 8888 <&3 >&3 && exec 3>&-
nc -l localhost 8888 <(cat fifo) > fifo
nc -l localhost 8888 < fifo > fifo

Теперь я ожидаю, что 4 команды будут делать то же самое, по крайней мере две последние будут делать то же самое.

  1. Первая команда работает, как и ожидалось, простой эхо-сервер, который отключается, когда клиент закрывает соединение.
  2. Ведет себя как 1.
  3. Я могу подключиться к серверу, отправить данные, но я ничего не получаю обратно. Когда я закрываю клиентское соединение, сервер выключается.
  4. Не удается подключиться к серверу, сервер слушает вечно.
Foo
источник

Ответы:

8

Ключевым моментом здесь является то, что открытие FIFO является операцией блокировки. В openВозвратить только один раз оба конца соединены, то есть после того , как ФИФО открыт для чтения и записи.

человек пятеро (7)

Normally, opening the FIFO blocks until the other end is opened also.

В 1-м случае оболочка разветвляется для выполнения конвейера, поэтому открытие fifo для read ( cat fifo) и открытие fifo для writing ( > fifo) происходит в отдельных процессах, поэтому происходит независимо.

Во втором случае открытие для чтения и открытие для записи ( 3<>fifo) происходит за один шаг.

В третьем случае <(cat fifo)расширяется до имени файла, например /dev/fd/42. Так что ты бежишь nc -l localhost 8888 /dev/fd/42 > fifo. Вам нужно дополнительное, <чтобы оно было эквивалентным, например nc -l localhost 8888 < <(cat fifo) > fifo.

В четвертом случае оболочка пытается открыть fifo для чтения ( < fifo) и открыть его для записи ( > fifo) как часть того же процесса. Оболочка делает их по одному, слева направо. Таким образом, он пытается открыться fifoдля чтения и блокируется навсегда, ожидая, что что-то откроется fifoдля записи. Я думаю, вы обнаружите, что в этом случае ncникогда даже не начинали, и порт никогда не был открыт для прослушивания.

Mikel
источник
О да, глупая ошибка в # 3, но в итоге результат остается прежним. Еще один вопрос, который вызывает больше любопытства, чем все остальное, является ли exec единственным способом открыть fifo для r / w за один шаг? И есть ли другой способ заставить оболочку раскошелиться, как в # 1? Спасибо!
Foo
nc ... <>fifoдолжно быть достаточно. gnu.org/software/bash/manual/html_node/Redirections.html
Микель,
1
Оболочка будет разветвляться каждый раз, когда вы используете конвейер, подоболочку или процесс подстановки.
Микель
2
Коррекция вам понадобится nc ... <>fifo >&0, так как она <>fifoоткрыта fifoдля чтения и записи на fd 0, и мы хотим, чтобы вывод тоже шел туда.
Микель