Вопрос по перенаправлению потоков в Linux

rosali

Задача: надо на двух машинах запустить по программе, так чтобы вход каждой из них был выходом другой.
Решение:


mkfifo x
mkfifo y
ssh host1 cmd1 <x >y &
ssh host2 cmd2 <y >x &


Не работает
Зато работает так:


ssh host1 cmd1 <x | tee y > /dev/null &
ssh host2 cmd2 <y | tee x > /dev/null &


Казалось бы это почти то же самое, но работает только второе.
Хотелось бы услышать лекцию на тему...

sergey_m

Ниибаца
Мысль такая: в первом случае в fifo пишет шелл, во втором tee. Можно предположить, что шелл пишет как-то хуево. Какой шелл кстати?
P.S. А работа происходит на третьей машине, а так понял?
P.P.S. Я бы наверное решал задачу на perl, через IPC::Open2.

rosali

bash. На третей, но мне показалось что это пофиг. Ладно, если разберусь когда-нибудь, то расскажу

rosali

PS. Кстати задача очень естественно возникла. Эти процессы общаются в итоге по специфическому сетевому оборудованию (InfiniBand) а чтобы установить соединение нужны особые цифры, которые каждый раз разные и доступны только на противоположной стороне. У самих разработчиков InfiniBand-а есть тестовая програмка, так она эту информацию по сокетам передает, как-то тяжеловато...

rosali

Возможно к разгадке приведет такой эксперимент:


xenon:~$ mkfifo a
xenon:~$ mkfifo b
xenon:~$ cat <a >b &
[1] 25460
xenon:~$ cat >a
asdfg
xenon:~$ cat >a
12345
xenon:~$ cat b
asdfg
12345
[1]+ Done cat <a >b


Почему Done?

rosali

Все, разобрался! Рассказываю.
Сперва замечание
в первом случае в fifo пишет шелл, во втором tee

это не верно, в первом случае в fifo пишет сам cmd, точнее его местный представитель -- ssh. bash только только провязывает потоки, а потом делает exec.
Дальше. Проводим эксперимент:


xenon:~$ echo "123" > x &
[1] 25538
[1] Done echo "123" >x
xenon:~$ mkfifo y
xenon:~$ echo "123" > y &
[1] 25540
xenon:~$ cat y
123
[1]+ Done echo "123" >y
xenon:~$


Итого: если сделать системный вызов записи в fifo то застрянешь на нем до тех пор, пока кто-нибудь оттуда не прочитает. По сути под fifo не отводится никаких ресурсов. Записывающий процесс засыпает до тех пор, пока не выяснится кто и куда будет эти данные читать, тогда OS делает копирование, а писатель просыпается.
Ну так вот, в первом случае засыпают ssh, но они то и есть те самые товарищи, которые собирались следующим вызовом прочитать, так что все стоит -- deadlock. А во втором случае спят tee, а ssh продолжают работать и инициируют чтение, чем будят tee.
Звучит логично...
В действительности проще tee заменить на cat вроде результат должен быть тот же. Пойду на работу -- попробую...

rosali

Клевый тред, похож на вот

rosali


а) создать канал;
б) установить на обоих концах канала режим неблокирующего
ввода-вывода;

О! А как?

Ivan8209

Буферизовать пайп штатными средствами?
---
...Я работаю антинаучным аферистом...

rosali

a)...
b)...
это цитата из FAQ, наверное Глеб знает как...

sergey_m

б) установить на обоих концах канала режим неблокирующего ввода-вывода;
Речь идет о fcntl(fd, F_SETFL, O_NONBLOCK). Но как это сделать в шелл - не ябу.
Реализуй задачу примерно так на perl: с помощью IPC::Open2 получаешь 4 дескриптора. Дальше на на них select и читаешь/пишешь что куда надо.

sergey_m

это цитата из FAQ, наверное Глеб знает как...
Это FAQ писал не я

Ivan8209

http://www.gnu.org/directory/all/bfr.html ?
---
...Я работаю антинаучным аферистом...

rosali

Реализуй задачу примерно так на perl

Зачем? У меня с tee работает
Оставить комментарий
Имя или ник:
Комментарий: