Consider:
import subprocess
import time
def run_instance():
command = "sleep 30 >out 2>err &"
subprocess.check_output(command, shell=True, start_new_session=True)
def kill_instance():
print(subprocess.check_output(f"pgrep -f 30", shell=True))
subprocess.check_output(f"pkill -f 30", shell=True)
run_instance()
time.sleep(1)
kill_instance()
The output (run under Ubuntu) is:
b'17483\n17484\n'
Traceback (most recent call last):
File "test.py", line 15, in <module>
kill_instance()
File "test.py", line 10, in kill_instance
subprocess.check_output(f"pkill -f 30", shell=True)
File "/usr/lib/python3.8/subprocess.py", line 411, in check_output
return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
File "/usr/lib/python3.8/subprocess.py", line 512, in run
raise CalledProcessError(retcode, process.args,
subprocess.CalledProcessError: Command 'pkill -f 30' died with <Signals.SIGTERM: 15>.
Why does pkill fail even though pgrep finds the process?
Common way
The most clean, IMO, way here is to just manage your instance within python (note you don't even need
shell=True):Your code
Disclaimer: you shouldn't be doing this in production.
You are killing your
pkill. Here's the same with more verbose output:This outputs on my machine:
(ignore
dockerandfirefoxprocesses here, they're just for completeness here and to demonstrate that you're killing too much processes, ff tabs crash after this)The interesting output part from
pgrephere:When you call
pkill, it is a process. It will be there instead ofpgrep, something like... and you
pkillall matching processes. So you can kill the running instance successfully, but then kill yourself.To demonstrate that, the following succeeds:
Output:
Sorry for that ugly pipe, maybe there is a simpler way, but Linux
pgrepcannot exclude self (as opposed to FreeBSD, discussed here). This pipe lists processes, excludespgrepitself ($$refers to current parent shell, which is that runspgrephere) and passes them tokill.