sycam sysd-mail-once: slightly more verbose, plus dry run
authorIan Kelling <iank@fsf.org>
Wed, 10 May 2023 17:56:10 +0000 (13:56 -0400)
committerIan Kelling <iank@fsf.org>
Wed, 10 May 2023 20:05:50 +0000 (16:05 -0400)
sysd-mail-once

index 3b87eea08dbc7c4f399786d4ce5dc4ecaab84adc..3542200d12d52b437362d252a3047315d34d0bd7 100755 (executable)
@@ -20,9 +20,11 @@ trap 'echo "$0:$LINENO:error: \"$BASH_COMMAND\" returned $?" >&2' ERR
 errors=3
 cbase=$HOME/sysd-mail-once-state
 to=root
-case "$1" in
-  -h|--help)
-    cat <<EOF
+dryrun=false
+while [[ $1 == -* ]]; do
+  case "$1" in
+    -h|--help)
+      cat <<EOF
 Usage: sysd-mail-once [-t TO_ADDRESS] [-ERRORS] SERVICE COMMAND [COMMAND_ARGS...]
 
 For use with systemd timers, to email (with exim) on repeated failure &
@@ -34,30 +36,78 @@ The email will contain the service's logs for the last ERRORS runs.
 
 Stores error counts in $cbase
 
--ERRORS:  ERRORS is the number of failurs to accumulate before mailing the error.
-          Default is 3.
+-ERRORS         ERRORS is the number of failurs to accumulate before mailing the error.
+                Default is 3.
 
--t TO_ADDRESS:  Address to email about errors
+-t TO_ADDRESS   Address to email about errors
+-n              Dry run. Execute command but only print out what we would do in response.
 EOF
-    exit 0
-    ;;
-  -[0-9]*)
-    errors=${1#-}
-    shift
-    ;;
-  -t)
-    to="$2"
-    shift 2
-    ;;
-esac
-service=$1
+      exit 0
+      ;;
+    -[0-9]*)
+      errors=${1#-}
+      ;;
+    -t)
+      to="$2"
+      shift
+      ;;
+    -n)
+      dryrun=true
+      ;;
+    *)
+      echo "error: unexpected arg: $1"
+      exit 1
+      ;;
+  esac
+  shift
+done
+
+if (( $# < 2 )); then
+  echo "error: expected at least 2 args after options. args:"
+  exit 1
+fi
+
+service="$1"
 shift
 
+
+# maybe run, depending on $dryrun
+m() {
+  if $dryrun; then
+    printf "%s\n" "$*"
+  else
+    "$@"
+  fi
+}
+# maybe run, with stdin
+mi() {
+  if $dryrun; then
+    printf "%s <<'EOF'\n" "$*"
+    cat
+    echo EOF
+  else
+    "$@"
+  fi
+}
+e() {
+  printf "dryrun: %s\n" "$*"
+}
+
 c=$cbase/$service # c for command file path base
 
+if $dryrun; then
+  e "c=$c"
+fi
+
 glob="${c}[0-9]*"
 arr=($glob); file="${arr[0]}"; [[ $glob != "$file" ]] || file=
-[[ -d $cbase ]] || mkdir -p $cbase
+if [[ $dryrun && $file ]]; then
+  e "file=$file"
+fi
+
+if ! [[ -d $cbase ]]; then
+  mkdir -p $cbase
+fi
 
 if [[ ! $file ]]; then
   cursor=$(journalctl --show-cursor -qn0|sed 's/^\s*--\scursor:\s*//')
@@ -71,7 +121,7 @@ if (( code )); then
     i=${file#"$c"}
     if (( i < errors )); then
       new_file=$c$((i+1))
-      mv $file $new_file
+      m mv $file $new_file
       file=$new_file
       if [[ $file == $c$errors ]]; then
         send_mail=true
@@ -79,13 +129,18 @@ if (( code )); then
     fi
   else
     file=${c}1
-    printf "%s\n" "$cursor" >$file
+    if $dryrun; then
+      printf "dryrun: creating $file, contents: %s\n" "$cursor"
+    else
+      printf "%s\n" "$cursor" >$file
+    fi
     if (( errors == 1 )); then
       send_mail=true
     fi
   fi
   if $send_mail; then
-      exim -odf -t <<EOF
+    echo "sysd-mail-once: emailing on $errors errors. exit code: $code"
+    mi exim -odf -t <<EOF
 To: $to
 From: $USER@$(hostname -f)
 Subject: $HOSTNAME: $service exit code: $code
@@ -95,9 +150,10 @@ EOF
   fi
 else
   if [[ $file ]]; then
-    rm -f $file
+    rm -f $file
     if [[ $file == $c$errors ]]; then
-      exim -odf -t <<EOF
+      echo "sysd-mail-once: emailing success after >= $errors errors."
+      mi exim -odf -t <<EOF
 To: $to
 From: $USER@$(hostname -f)
 Subject: $HOSTNAME: $service success