Как определить, какая пара псевдотерминалов подключена друг к другу?
У меня есть две программы на Python, которые должны общаться друг с другом через последовательное соединение. Чтобы смоделировать соединение, я создаю двунаправленный поток байтов, используя socat, как здесь:
socat -d -d pty,raw,echo=0 pty,raw,echo=0
Консоль возвращает следующее, указывая два pty-порта, которые теперь соединены вместе:
2018/04/15 22:33:03 socat[18197] N PTY is /dev/pts/2
2018/04/15 22:33:03 socat[18197] N PTY is /dev/pts/3
2018/04/15 22:33:03 socat[18197] N starting data transfer loop with FDs [5,5] and [7,7]
Затем мне нужно вручную изменить каждую из двух программ, чтобы указать последовательное соединение для каждой, например:
В программе A.py:
import serial
...
ser = serial.Serial('/dev/pts/2')
В программе B.py:
import serial
...
ser = serial.Serial('/dev/pts/3')
Мне нужен скрипт, который установит соединение socat, затем выполнит A.py с одним номером порта, переданным ему в качестве аргумента, и выполнит B.py с другим номером порта, переданным ему в качестве аргумента.
Я пробовал скрипт bash, но socat
блоки команд, и я не могу перехватить его вывод stderr, чтобы поместить его в переменную. Если бы я мог, я мог бы тогда разобрать переменную и быть на моем веселом пути.
Есть идеи? Или, может быть, лучший способ сделать это?
Спасибо!
1 ответ
Вы можете запустить socat
без блокировки используя низкий уровень Popen
класс в питоне. Вам нужно перенаправить stderr
так что вы можете отсканировать это имя pty, но затем вы можете передать его фоновому потоку после того, как получите нужную информацию.
import sys
import subprocess as subp
import threading
import shutil
import re
socat_proc = subp.Popen(['socat', '-d', '-d', 'pty,raw,echo=0', 'pty,raw,echo=0'],
stderr=subp.PIPE)
try:
# scan output for 2 ptys
ptylist = []
for line in socat_proc.stderr:
line = line.decode().strip()
print(line)
pty = re.search(r"N PTY is (.+)", line)
if pty:
ptylist.append(pty.group(1))
if len(ptylist) == 2:
break
if socat_proc.poll() is not None:
print("badness. socat dead.")
exit(2)
# background thread consumes proc pipe and sends to stdout
socat_thread = threading.Thread(target=shutil.copyfileobj,
args=(socat_proc.stdout, sys.stdout))
socat_thread.daemon = True
socat_thread.start()
print("pty", ptylist)
# now you can start your programs...
finally:
socat_proc.terminate()