I'm running a Python script that executes a Bash subprocess. If the Bash subprocess times out, then the Python script is expected to print the stdout of the Bash subprocess. The Python script works as expected, however, if the Bash subprocess is executed using the "sudo" keyword, then reading the stddout after the timeout blocks the Python.
The Bash script (named test-bash.sh) looks like that:
#!/bin/sh
while :
do
echo "Press [CTRL+C] to stop.."
sleep 1
done
The Python script looks like that:
import subprocess
proc = subprocess.Popen("sudo ./test-bash.sh", shell=True, stdout=subprocess.PIPE)
try:
outs, errs = proc.communicate(timeout=3)
except subprocess.TimeoutExpired:
proc.kill()
print("Succesfully killed")
outs, errs = proc.communicate()
print("Stdout: {}".format(outs))
The last print is never called, being blocked on communicate(), unless we remove the "sudo" from:
proc = subprocess.Popen("sudo ./test-bash.sh", shell=True, stdout=subprocess.PIPE)
What is the reason for the blocking of communicate()? How do I unblock it and read stddout() if I must run the Bash subprocess using "sudo"?
The problem can be reproduced even without sudo
provided that shell=True
. It's just like John Bollinger explained above, so I'll spare us the reciting. Fortunately Popen
provides a means to deal with such multi-level subprocesses - it allows to start a new session and therewith to create a process group by which all subprocesses can be killed.
# add start_new_session=True argument
proc = subprocess.Popen(…, stdout=subprocess.PIPE, start_new_session=True)
…
# replace proc.kill() by
import os
import signal
os.killpg(proc.pid, signal.SIGTERM)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.