Почему эта команда bash работает, когда я обычно запускаю ее в оболочке, но не выполняю через Popen Python?

#python #bash #kali-linux

Вопрос:

Я хочу создать терминал в Кали с помощью python, а затем отправить управление окном терминала.

Таким образом, я могу создать новый терминал и получить его pid на Python:

 from subprocess import Popen, PIPE, STDOUT, check_output
p1 = Popen(['x-terminal-emulator'])
print(f'pid: {p1.pid}') // 31700
 

затем передайте это xdotool лайку:

 xdotool search --pid 31700
 

выход из строя:

 90177537 // first code given isn't the one to use
88080390 // second one seems to work, not sure why
 

а затем передайте это обратно xdotool :

 xdotool windowfocus 88080390
 

успех! Я могу перемещать окно, передавать ему ввод и т. Д.

Но когда я пытаюсь объединить все это в код Python, xdotool search --pid 31700 команда завершается неудачно:

 from subprocess import Popen, PIPE, STDOUT, check_output
p1 = Popen(['x-terminal-emulator'])
print(f'pid: {p1.pid}')
window_id = check_output(['xdotool', 'search', '--pid', str(p1.pid)])
 

ошибка:

 pid: 548
Traceback (most recent call last):
  File "/mnt/c/Users/jonat/Documents/Github/net-vis/python/scanner.py", line 6, in <module>
    window_id = check_output(['xdotool', 'search', '--pid', str(p1.pid)])
  File "/usr/lib/python3.9/subprocess.py", line 424, in check_output
    return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
  File "/usr/lib/python3.9/subprocess.py", line 528, in run
    raise CalledProcessError(retcode, process.args,
subprocess.CalledProcessError: Command '['xdotool', 'search', '--pid', '548']' returned non-zero exit status 1.
 

Что я делаю не так?

Комментарии:

1. Вы, вероятно, пытаетесь найти окна до того, как процесс успеет открыть одно из них. Попробуйте добавить второй продолжительный сон перед вызовом xdotool

Ответ №1:

Я думаю, у тебя гоночное состояние. Существует интервал между тем, когда x-terminal-emulator процесс запускается, и когда он фактически открывает окно и его можно обнаружить с помощью xdotool . Простое добавление короткого ожидания в ваш код заставляет его работать на меня:

 import subprocess
import time

p1 = subprocess.Popen(['x-terminal-emulator'])
print(f'pid: {p1.pid}')
time.sleep(2)
window_id = subprocess.check_output(['xdotool', 'search', '--pid', str(p1.pid)])
 

Или вместо сна используйте цикл опроса, чтобы дождаться xdotool успешного завершения, возможно, с каким-то таймаутом:

 import subprocess
import time

p1 = subprocess.Popen(['lxterminal'])
print(f'pid: {p1.pid}')

t_start = time.time()
while True:
    try:
        window_id = subprocess.check_output(['xdotool', 'search', '--pid', str(p1.pid)])
        break
    except subprocess.CalledProcessError:
        t_delta = time.time() - t_start
        if t_delta > 5:
            raise
        time.sleep(0.1)

print('got window id:', window_id)
 

Второе решение даст вам гораздо лучшее время отклика.