2015-02-14 4 views
7

Я пытаюсь создать постоянное соединение с помощью bash. На терминале 1, я держу Netcat работает в качестве сервера:Постоянное соединение в скрипте Bash

$ nc -vlkp 3000 
Listening on [0.0.0.0] (family 0, port 3000) 

На терминал 2, я создаю ФИФО и держать кошку:

$ mkfifo fifo 
$ cat > fifo 

На терминале 3, я делаю ФИФО как вход для клиента Netcat:

$ cat fifo | nc -v localhost 3000 
Connection to localhost 3000 port [tcp/*] succeeded! 

на терминал 4, я отправляю все, что я хочу:

$ echo command1 > fifo 
$ echo command2 > fifo 
$ echo command3 > fifo 

Возвращаясь к терминалу 1, я вижу команды принимается:

$ nc -vlkp 3000 
Listening on [0.0.0.0] (family 0, port 3000) 
Connection from [127.0.0.1] port 3000 [tcp/*] accepted (family 2, sport 41722) 
command1 
command2 
command3 

Итак, все работает. Но когда я положил, что в сценарий (я назвал это fifo.sh), баш не может писать в ФИФО:

На терминале 1, то же прослушивания сервера:

$ nc -vlkp 3000 
Listening on [0.0.0.0] (family 0, port 3000) 

На терминале 2 я запустить скрипт:

#!/bin/bash 

rm -f fifo 
mkfifo fifo 
cat > fifo & 
pid1=$! 
cat fifo | nc -v localhost 3000 & 
pid2=$! 

echo sending... 
echo comando1 > fifo 
echo comando2 > fifo 
echo comando3 > fifo 

kill -9 $pid1 $pid2 

выход в терминале 2:

$ ./fifo.sh 
Connection to localhost 3000 port [tcp/*] succeeded! 
sending... 

на терминале 1 я вижу только Конек Тион. Нет команд:

$ nc -vlkp 3000 
Listening on [0.0.0.0] (family 0, port 3000) 
Connection from [127.0.0.1] port 3000 [tcp/*] accepted (family 2, sport 42191) 
Connection closed, listening again. 

Любая идея о том, почему она работает только в интерактивном режиме? Или есть ли другой способ создать постоянное соединение, используя только Bash? Я не хочу искать Expect, потому что у меня есть более большой скрипт Bash, который выполняет некоторую работу после отправки команды1, а command2 зависит от выхода команды 1 и т. Д.

Спасибо!

+1

Привет и добро пожаловать в переполнение стека! Это лучший начинающий вопрос, который я когда-либо видел. – l0b0

ответ

2

Когда процесс запускается в фоновом режиме в скрипте, стандартный ввод перенаправляется с /dev/null. Это означает, что первая команда cat будет считывать и испускать EOF, как только она будет выполнена, что приведет к выходу netcat сразу после запуска, поэтому выход позже в скрипте никогда не попадет в fifo, потому что нет активного прослушивателя в то время.

В этом случае, когда оценивается cat > fifo, оболочка виляет дочерний процесс, перенаправляет стандартный ввод от /dev/null и пытается открыть fifo для записи. Ребенок остается в блокировке open звонка в это время. Обратите внимание, что cat не выполняется до завершения вызова open.

Дальше, cat fifo | nc -v localhost 3000 порождается. cat открывает fifo для чтения, что позволяет блокировать open от первого дочернего элемента и выполнить первый cat.

Первый cat наследует дескрипторы файла своего родителя, поэтому его стандартный ввод прикреплен к /dev/null, и поэтому он считывает и испускает EOF.Второй cat считывает EOF и передает его на стандартный вход nc, что приводит к выходу netcat.

К моменту утверждения операторов echo процессы, идентифицированные $pid1 и $pid2, завершены. Поскольку на fifo больше нет слушателя, первый echo будет блокироваться навсегда.


Я не исправить чисто оболочку, но вы можете использовать внешнюю программу, как Perl, чтобы открыть шаблонный писатель fifo вместо того, чтобы использовать перенаправление оболочки. Кроме того, обратите внимание, что есть гонка с nc, начиная с операторов echo (где kill происходит до того, как netcat имеет возможность обрабатывать вывод ввода/отправки), поэтому здесь я добавил задержку после выражения cat | nc. Существует почти наверняка лучшее решение там, но вот что я придумал:

#!/bin/bash 

rm -f fifo 
mkfifo fifo 
perl -e 'open(my $fh, ">", "fifo"); sleep 3600 while 1' & 
pid1=$! 
cat fifo | nc -v localhost 3000 & 
pid2=$! 

sleep 2 

echo sending... 
echo comando1 > fifo 
echo comando2 > fifo 
echo comando3 > fifo 

kill -9 $pid1 $pid2 

Надеется, что это помогает, большой вопрос!

Смежные вопросы