#!/bin/sh # offlineimap is pretty nifty, and generally does the right thing, and is # remarkably fault-tolerant, even of it's own code. # # One nifty thing it doesn is to check if an instance of it is already running, # and to exit and let the original insance do it's thing. That lets us do # things like put it in a crontab. We wouldn't want to do this if it didn't have # that feature, because then # * If the previous run hadn't finished, things would break # I have it run every at m="*/5". 5 minutes is usually plenty of time, but # for large attachments, it might not be enough. # * If I wanted to run it manually, at say m="*/5+4", if it takes more than a # minute to run, then the instance invoked by cron would bork everything. # As awesome as this is, it has one fatal flaw: an instance hanging. # This only happens rarely, but I've had an instance of offlineimap invoked by # cron decided to hang up. After 2 days of recieving suspiciously little email, # I decided to check if offlineimap was running ok. That instance had hung up, # not recieving any mail, but preventing cron from starting another instance. # # So, here is my workaround: keep track of how many times in a row that we've # tried to start offlineimap, and it failed. If that number exceeds a specified # number, then assume the running instance hung, and kill it. if [ "$1" = '-v' ]; then shift; msg() { echo "$@"; } else msg() { :; } fi # A note on notation: # the number/limit is the number of failures allowed *before* anything is killed. # So, if the limit is "1", the first time, it will just pass by. The second # time, it will see that we've already failed once, so if it's still running, # kill it. default_limit=2 limit=${1-$default_limit} shift cookie_file="$HOME/.offlineimap.cookie" offlineimap='offlineimap-exit' # Try running offlineimap if $offlineimap "$@"; then # Everything went smoothly, remove any record of failures msg 'Successfully ran offlineimap' msg 'Clearing cookie file' echo '0' > "$cookie_file" else # oh noez! msg 'offlineimap had an error' # we interupt your regularly scheduled panic for a sanity check if [ ! -f "$cookie_file" ]; then echo '0' > "$cookie_file" fi # you may now resume panicing number=`cat "$cookie_file"` echo $(($number+1)) > "$cookie_file" msg " has failed $number times (with a limit of $limit)" if [ "$number" -ge "$limit" ]; then # kill it! killall -9 offlineimap # We invoke offlineimap directly, instead of recursing on # ourself because if something else is causing it to fail, then # we'll fork-bomb $offlineimap "$@" fi fi