8

I have a python script that runs in the background on startup. The starting method is a entry in a run.sh file which is called with /etc/rc.local. The exact entry would be "sudo python /home/pi/run/main.py &". The system is a raspberry pi with wheezy.

The script is running, no problem so far. If a shutdown command is send to the system (via console "sudo shutdown -h now") I need further the script to not abort right away but to execute some code first. Thats what I got so far:

#!/usr/bin/env python

import atexit

@atexit.register
def byebye():
    c = "End"
    datei = open("/home/pi/logfile",'a+b')
    datei.write(c + "\n")
    datei.close()

def main():

   while True:
     ...do anything...

main()

Right now it seems to just exit the main loop on shutdown. Do I need to use a different way to shutdown the system so the signal is transmitted to my script or did I maybe not get the usage of the "@atexit" method? Any ideas?

Thanks

2
  • Maybe if you look at how molly-guard - packages.debian.org/sid/all/molly-guard/filelist - does it, you will have a better method? Commented Feb 6, 2014 at 20:57
  • Thanks for your comment but it seems this code is way above my expertise...don´t even know how to begin there... :( Commented Feb 6, 2014 at 21:16

1 Answer 1

10

shutdown sends the SIGTERM signal, which atexit does not handle. Nor will context managers, finally blocks, etc.

import signal

signal.getsignal(signal.SIGTERM)
Out[64]: 0 #i.e. nothing

Contrast this with, say ctrl-C:

signal.getsignal(signal.SIGINT)
Out[65]: <function signal.default_int_handler> #i.e. something

You can register your byebye function with signal to run instead of doing nothing (which leads to the interpreter eventually getting killed by the shell)

signal.signal(signal.SIGTERM,byebye)

If you do the above you'll need to do two things:

  • change the signature of byebye to accept the two arguments that signal will pass to it.
  • you should do something like call sys.exit() at the end of your byebye function to allow python to gracefully close up shop.

You could alternatively do some combination of signal and atexit:

import sys
signal.signal(signal.SIGTERM, lambda num, frame: sys.exit(0))

Which would drop right in to your current code. This ensures the atomicity of your cleanup operation (i.e. byebye is guaranteed to be the last I/O operation) at the cost of being a bit clunky.

Sign up to request clarification or add additional context in comments.

3 Comments

+1 for the lambda. I don't think it's clunky, provided it's commented.
Yeah that's my only concern - your code doesn't declare where/what your exit handler is anymore. It could be modules, nay, packages away! (so yeah, use a comment :-))
Thanks a lot for your answer...that was the push i needed! :-)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.