I have a simple question. I have tried to search for a solution but there are no answers which would explain what I need.
The question is:
How do I start a nohup
command from Python? Basically the idea is, that I have a Python script which prepares my environment and I need it to launch multiple scripts with nohup
commands. How do I start a nohup
command like nohup python3 my_script.py &
from within a running Python script to have that nohup command running even after I log out?
Thank you
You do not need nohup
-- not even in shell, and even less so in Python. It does the following things:
nohup.out
/dev/null
That's it. There's no reason to use nohup
to do any of those things; they're all trivial to do without it:
</dev/null
redirects stdin from /dev/null
in shell; stdin=subprocess.DEVNULL
does so in Python.>nohup.out
redirects stdout to nohup.out
in shell; stdout=open('nohup.out', 'w')
does so in Python.2>&1
makes stderr go to the same place as stdout in shell; stderr=subprocess.STDOUT
does so in Python.Because your process isn't attached to the terminal by virtue of the above redirections, it won't implicitly get a HUP when that terminal closes. If you're worried about a signal being sent to the parent's entire process group, however, you can avoid that by splitting off the child into a separate one:
subprocess.Popen
argument start_new_session=True
splits the child process into a separate group from the parent in Python, so a parent sent to the process group of the parent as a whole will not be received by the child.preexec_fn
with signal.signal(signal.SIGHUP, signal.SIG_IGN)
is even more explicit that the child should by default ignore a SIGHUP even if one is received.Putting this all together might look like (if you really do want logs to go to a file named nohup.out
-- I would suggest picking a better name):
import subprocess, signal
subprocess.Popen(['python3', 'my_script.py'],
stdin=subprocess.DEVNULL,
stdout=open('nohup.out', 'w'),
stderr=subprocess.STDOUT,
start_new_session=True,
preexec_fn=(lambda: signal.signal(signal.SIGHUP, signal.SIG_IGN)))