Как определить, какая пара псевдотерминалов подключена друг к другу в bash

У меня есть пара программ Linux C, которые используют псевдотерминалы /dev/pts/* для связи друг с другом. Pty, на котором можно обмениваться данными, передается этим программам в качестве аргумента командной строки.

Я могу создать пару устройств pty с помощью socat следующим образом:

socat -d -d pty,raw,echo=0 pty,raw,echo=0

Вывод выше дает как:

2018/07/05 17:56:54 socat[58319] N PTY is /dev/pts/1
2018/07/05 17:56:54 socat[58319] N PTY is /dev/pts/3
2018/07/05 17:56:54 socat[58319] N starting data transfer loop with FDs [7,7] and [9,9]

как я могу извлечь узлы pty, /dev/pts/* из вывода socat и передать их моему приложению через командную строку в сценарии оболочки:

$./test_pty_app /dev/pts/1 & 
$./test_pty_app /dev/pts/2 &

Я видел аналогичный вопрос, который может сделать это в python друг другу">здесь Спасибо!


person Yusuf Husainy    schedule 05.07.2018    source источник


Ответы (2)


Обновленный ответ

Похоже, вам придется использовать файл, если socat должен быть фоновым.

( socat ... 2>&1 | grep -Eo "/dev/pts/\d+" > /tmp/a ) &
portA=$(head -n 1 /tmp/a)
portB=$(tail -n 1 /tmp/a)

Исходный ответ

Ответ @jeremysprofile, вероятно, более разумен, но просто для удовольствия вы также можете сделать что-то из этого:

socat ... | grep -Eo "/dev/pts/\d+" | { read portA; read portB; }

Или, используя "подстановку процесса" в bash, вы можете сделать следующее:

{ read portA; read portB; } < <(socat ... | grep -Eo "/dev/pts/\d+")

Затем вы сделаете это после любого из них:

./test_pty_app $portA &
./test_pty_app $portB &
person Mark Setchell    schedule 06.07.2018
comment
Спасибо, Марк. При передаче значений portA и portB в приложение и их печати (поскольку эхо не печатает их) я получаю значения NULL. Кажется, портам portA и portB не присвоены значения узла pty. Также socat должен работать в фоновом режиме, чтобы bash снова запустился, в противном случае он ждет завершения сигтерма, а затем bash снова запускается. - person Yusuf Husainy; 06.07.2018
comment
grep не понимает \d+, вместо него нужно использовать [0-9]\+. - person Jérôme Pouiller; 29.04.2021
comment
Также необходимо передать --line-buffered в grep. Остальное ничего не написано в /tmp/a. - person Jérôme Pouiller; 29.04.2021
comment
Возможна также гонка между моментом, когда grep пишет /tmp/a, и моментом, когда вы читаете /tmp/a - person Jérôme Pouiller; 29.04.2021

 arr=($(socat -d -d pty,raw,echo=0 pty,raw,echo=0 2>&1 | grep -oh "/dev/pts/\w*"))

теперь "${arr[0]}" и "${arr[1]}" — два ваших tty-порта.

grep -oh выводит только тот шаблон, которому он соответствует, и ничего больше. `/dev/pts/\w* соответствует только тому, что начинается с /dev/pts/, а затем любого количества буквенно-цифровых (или _) символов, что в основном означает «до конца слова».

person jeremysprofile    schedule 06.07.2018
comment
Спасибо за ответ. Это не работает. Я получаю сообщение об ошибке: command substitution: line 36: syntax error near unexpected token '|' . Я пробовал со следующим, тоже не работает: arr=($(socat -d -d pty,raw,echo=0 pty,raw,echo=0 2>&1 | grep -oh "/dev/pts/\w* &")) - person Yusuf Husainy; 06.07.2018
comment
@YusufHusainy, вывод socat через stderr? - person jeremysprofile; 06.07.2018
comment
Да, я так думаю, поскольку без перенаправления stderr на stdout grep не получал его; вход для работы - person Yusuf Husainy; 06.07.2018
comment
Еще раз спасибо, Джереми. Отредактированный ответ по-прежнему не работает. Поскольку мне нужно, чтобы socat работал в фоновом режиме, иначе скрипт bash не будет обрабатываться, если я не завершу socat с помощью sigterm - person Yusuf Husainy; 06.07.2018
comment
Что это делает: {arr=($(socat -d -d pty,raw,echo=0 pty,raw,echo=0 2>&1 | grep -oh "/dev/pts/\w*"))} & ? - person jeremysprofile; 06.07.2018
comment
Это дает синтаксическую ошибку, например: syntax error near unexpected token $(socat -d -d pty,raw,echo=0 pty,raw,echo=0 2>&1 | grep -oh "/dev/pts/\w*") - person Yusuf Husainy; 06.07.2018
comment
Интересно отметить, что следующее работает без присваивания массиву: socat -d -d pty,raw,echo=0 pty,raw,echo=0 2>&1 | grep -oh "/dev/pts/\w*" &. Он распечатывает узлы pty, а затем необходимо назначить их массиву, а также запустить его в фоновом режиме. - person Yusuf Husainy; 06.07.2018
comment
@YusufHusainy, извините, это не в моих силах. Я не знаю, как вы могли это сделать. удачи. - person jeremysprofile; 06.07.2018