Skip to content

Instantly share code, notes, and snippets.

@acoulton
Last active August 27, 2021 05:49
Show Gist options
  • Save acoulton/6210457 to your computer and use it in GitHub Desktop.
Save acoulton/6210457 to your computer and use it in GitHub Desktop.
An enhanced version of [cronic - a cure for cron's chronic email problem](http://habilis.net/cronic/) that supports logging task output to a file for situations where you want to keep history on the server for further inspection but only want to be emailed if your task fails.
#!/bin/bash
# Cronic v2 - cron job report wrapper
# Copyright 2007 Chuck Houpt. No rights reserved, whatsoever.
# Amended 2013 Andrew Coulton.
# Public Domain CC0: http://creativecommons.org/publicdomain/zero/1.0/
# Basic usage, to run a task and discard the output unless it fails or outputs to STDERR
# cronic /run/my/task
#
# Enhanced usage, to run a task, always log to a file and only output for email if it fails or outputs to STDERR
# CRONIC_REPORT=/var/log/mytask/mytask cronic /run/my/task
#
# Each execution will log output to files called something like /var/log/mytask/mytask-{unix-timestamp}.out,
# .err and .trace. Presuming cronic itself survives these will be combined post-run to a single .log file.
# If the task outputs anything to STDERR or quits with a nonzero exit code this output will be sent to
# the console (and if running under cron will become the email body).
# The directory must exist
set -eu
TASKID=$(date +%s)
CRONIC_REPORT="${CRONIC_REPORT:=}"
# Prepare paths for working and report files
if [ -z "$CRONIC_REPORT" ]
then
OUT=/tmp/cronic.out.$$
ERR=/tmp/cronic.err.$$
TRACE=/tmp/cronic.trace.$$
REPORT=/tmp/cronic.report.$$
else
OUT="$CRONIC_REPORT-$TASKID.out"
ERR="$CRONIC_REPORT-$TASKID.err"
TRACE="$CRONIC_REPORT-$TASKID.trace"
REPORT="$CRONIC_REPORT-$TASKID.log"
fi
# Run the subcommand
set +e
"$@" >$OUT 2>$TRACE
RESULT=$?
set -e
# Filter any trace output
PATTERN="^${PS4:0:1}\\+${PS4:1}"
if grep -aq "$PATTERN" $TRACE
then
! grep -av "$PATTERN" $TRACE > $ERR
else
ERR=$TRACE
fi
# Build the report log file ready for output
if [ $RESULT -ne 0 -o -s "$ERR" ]
then
echo "Cronic detected failure or error output for the command:" > $REPORT
else
echo "Cronic detected successful execution of the command:" > $REPORT
fi
echo "$@" >> $REPORT
echo "" >> $REPORT
echo "RESULT CODE: $RESULT" >> $REPORT
echo "" >> $REPORT
echo "ERROR OUTPUT:" >> $REPORT
cat "$ERR" >> $REPORT
echo "" >> $REPORT
echo "STANDARD OUTPUT:" >> $REPORT
cat "$OUT" >> $REPORT
if [ $TRACE != $ERR ]
then
echo "" >> $REPORT
echo "TRACE-ERROR OUTPUT:" >> $REPORT
cat "$TRACE" >> $REPORT
fi
# If there was an error, output the report to trigger an email
if [ $RESULT -ne 0 -o -s "$ERR" ]
then
cat "$REPORT"
fi
# Remove the temporary working files
rm -f "$OUT"
rm -f "$ERR"
rm -f "$TRACE"
# Remove the report file if not configured to keep it
if [ -z "$CRONIC_REPORT" ]
then
rm -f "$REPORT"
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment