Issue
I want to spawn a terminal in Kali with python, then send manipulate the terminal window.
So I can spawn a new terminal and get its pid in Python:
from subprocess import Popen, PIPE, STDOUT, check_output
p1 = Popen(['x-terminal-emulator'])
print(f'pid: {p1.pid}') // 31700
then pass it to xdotool
like:
xdotool search --pid 31700
stdout:
90177537 // first code given isn't the one to use
88080390 // second one seems to work, not sure why
and then pass that back to xdotool
:
xdotool windowfocus 88080390
success! I can move the window around, pass it input, etc.
But when I try to combine all this into the Python code, the xdotool search --pid 31700
command fails:
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)])
error:
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.
What am I doing wrong?
Solution
I think you've got a race condition. There's an interval between when the x-terminal-emulator
process starts running and when it actually brings up a window and is discoverable using xdotool
. Simply adding a short wait in your code makes it work for me:
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)])
Or instead of a sleep, use a polling loop to wait until xdotool
is successful, possibly with some sort of timeout:
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)
The second solution will give you much better response time.
Answered By - larsks