i have script-launcher (bash) executes python scripts in background, can start , close terminal/ssh connection, leaving script working.
it accepts name of script run , optional arguments pass there. starts python script (detached) , creates file pid (of python script) in same directory, can later reconnect server , kill background process using pid file.
also pid file used prevent same script been started if it's running (singleton).
the problem can't figure out how delete pid file after python script finished work. need implemented in bash script, no python solutions (since want use cases) or screen tool. supervisor (that delete pid file after script finished work) should run in background (!), can same thing: close terminal session.
what i've tried far:
#!/bin/bash pidfile=$1.pid if [ -f $pidfile ]; echo "process running, pid: $(< $pidfile)" exit 1 else nohup python $1 "${@:2}" > /dev/null 2>&1 & pid=$! echo $pid > $pidfile # supervisor nohup sh -c "wait $pid; rm -f $pidfile" > /dev/null 2>&1 & fi
in example pid file deleted immediately, because wait command returns (i think it's because new process isn't child of current one, wait doesn't work in case expect).
do have thoughts how can implemented? basically, need replace line
nohup sh -c "wait $pid; rm -f $pidfile" > /dev/null 2>&1 &
that wait until previous script (python's in case) finish work , delete pid file.
upd: ok, problem wait command, because can't wait non-child processes. working solution replace while loop:
#!/bin/bash function cleanup { while [ -e /proc/$1 ]; sleep 1; done rm -f $pidfile } pidfile=$1.pid if [ -f $pidfile ]; echo "process running, pid: $(< $pidfile)" exit 1 else python $1 "${@:2}" > /dev/null 2>&1 & pid=$! echo $pid > $pidfile cleanup $pid > /dev/null 2>&1 & disown fi
for shell scripts, use traps:
#!/bin/bash function finish { wait $pid rm $pidfile > /dev/null 2>&1 & } trap finish exit trap "exit 2; finish" sigint pidfile=$1.pid if [ -f $pidfile ]; echo "process running, pid: $(< $pidfile)" exit 1 else nohup python $1 "${@:2}" > /dev/null 2>&1 & pid=$! echo $pid > $pidfile fi
traps allow catch signals , respond them, in code above, exit signal (normal completion) execute finish, removing $pidfile
. on sigint (user requested exit ctrl-c), script remove $pidfile
, exit 2.
directly in python: if want handle manually take @ atexit. haven't looked @ source, looks implements traps in order register cleanup functions:
import atexit import os def cleanup(): os.unlink(pidfile) atexit.register(cleanup)
or automate pidfile handling checkout pid handle preventing simultaneous execution on own:
from pid import pidfile pidfile(): do_something()
or better yet
from pid.decorator import pidfile @pidfile() def main(): pass if __name__ == "__main__": main()
Comments
Post a Comment