From 30c42d2c3f6a9ce65e85363601abd1e469a32a2f Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Fri, 28 Nov 2014 00:04:59 -0500 Subject: Cleanup of offlineimap utilities. --- .gitignore | 2 +- Makefile | 2 +- offlineimap-exit.sh | 10 -------- offlineimap-killer.sh | 31 ++++++++++++++++++++++ offlineimap-runner.sh | 71 ++++----------------------------------------------- 5 files changed, 38 insertions(+), 78 deletions(-) delete mode 100644 offlineimap-exit.sh create mode 100644 offlineimap-killer.sh diff --git a/.gitignore b/.gitignore index 5854bc4..1347fbf 100644 --- a/.gitignore +++ b/.gitignore @@ -6,8 +6,8 @@ chardiff_post daemon hangman-helper maildups +offlineimap-killer offlineimap-runner -offlineimap-exit ord roll tempmon diff --git a/Makefile b/Makefile index cf50e18..aafce7c 100644 --- a/Makefile +++ b/Makefile @@ -12,8 +12,8 @@ BINFILES = \ daemon \ hangman-helper \ maildups \ + offlineimap-killer \ offlineimap-runner \ - offlineimap-exit \ ord \ roll \ tempmon \ diff --git a/offlineimap-exit.sh b/offlineimap-exit.sh deleted file mode 100644 index 7838cd7..0000000 --- a/offlineimap-exit.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash - -offlineimap='offlineimap' - -output_file="$(mktemp --tmpdir "${0##*/}.XXXXXXXXXX")" -trap "rm -f $(printf '%q' "$output_file")" EXIT - -"$offlineimap" "$@" |& tee "$output_file" - -! grep 'ERROR:' "$output_file" diff --git a/offlineimap-killer.sh b/offlineimap-killer.sh new file mode 100644 index 0000000..91f9509 --- /dev/null +++ b/offlineimap-killer.sh @@ -0,0 +1,31 @@ +#!/bin/bash +# Usage: offlineimap-killer LIMIT +# +# Kills any instance of offlineimap that has been running longer than +# LIMIT seconds. + +pid_uptime() { + local pid=$1 + local sec_uptime=$(cut -d ' ' -f1 /proc/uptime) + local tic_started_at + tic_started_at=$(cut -d ' ' -f 22 /proc/${pid}/stat 2>/dev/null) || + { echo 0; return 0; } + local tic_per_sec=$(getconf CLK_TCK) + + bc <<<"${sec_uptime} - (${tic_started_at}/${tic_per_sec})" +} + +main() { + declare -i limit=$1 + local pids=($(pgrep -x offlineimap)) + local pid + for pid in "${pids[@]}"; do + declare -i uptime=$(pid_uptime $pid) + if [[ "$uptime" -gt "$pid" ]]; then + printf 'Killing %d which has been running for %d seconds' "$pid" "$uptime" + kill -9 "$pid" + fi + done +} + +main "$@" diff --git a/offlineimap-runner.sh b/offlineimap-runner.sh index ae8bf10..440b2bf 100644 --- a/offlineimap-runner.sh +++ b/offlineimap-runner.sh @@ -1,70 +1,9 @@ #!/bin/bash +# Run offline imap, but "parse" the output to generate a sane exit status -# 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. +output_file="$(mktemp --tmpdir "${0##*/}.XXXXXXXXXX")" +trap "rm -f $(printf '%q' "$output_file")" EXIT -# 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. +offlineimap "$@" |& tee "$output_file" -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 +! grep -q '^ERROR:' -- "$output_file" -- cgit v1.2.3