0

I would like cron to only email on stderr output but when it does it should include all stdout and stderr

This is different than the usual question of only emailing on stderr (ie. redirect stdout to /dev/null). In that case, cron only emails the stderr but I would like to see everything for context.

I'm running Rocky 9 with cronie as the cron daemon.

3
  • home and enduser question are offtopic on serverfault.com but might be on topic on superuser.com instead. What is the business related question or issue in here, what do you really want to solve because most users forget that point due the have not read How to Ask yet Commented Feb 19, 2024 at 20:51
  • Fwiw this is a business server related situation... I don't care. If someone wants to move it to superuser go ahead. Commented Feb 19, 2024 at 21:06
  • 1
    Redirect STDERR and STDOUT each into separate files. If there is anything in STDERR - concatenate and mail both. If you want to keep the order of messages then you'll probably need to mix some tee in. Commented Feb 19, 2024 at 21:33

3 Answers 3

3

If the command exits with a non-zero status code, you could try:

bash -c 'command 2>&1 > /tmp/err || mail -A /tmp/err [email protected]' 

where:

  • bash -c '' enables using multiple commands on a cronjob; you could use a script, too.
  • command is path to the command to be excuted
  • 2>&1 redirects stderr to stdout
  • > /tmp/err saves stdout (now both streams) to a file (path /tmp/err)
  • || runs the second command only if the first failed with a non-zero status code
  • mail -A /tmp/err sends the file as an attachment

You could enhance this using, e.g. mktemp to use different path for every log in case of simultaneous runs & sleep there is something missing from the end of the file.

2
  • Thank you, this is a helpful comment but does not address the question exactly Commented Feb 20, 2024 at 20:40
  • 1
    It gives plenty of Legos you can use to build a solution that best fits your needs. You'd likely need a script. Commented Feb 20, 2024 at 20:43
0

I decided to write a script that could approximate a solution to the question of only emailing on stderr output.

The key is storing stdout/stderr to files until stderr is detected and then outputting the combined file.

The combined file can loosely be said to retain stdout/stderr order in so far as tail can iterate over its files quickly enough. If there's no buffering and a command takes more than a second or two and there's some delay between stdout/stderr ouputs then this approach can approximate ordered stdout/stderr output.

I call this script cron-wrapper.sh. It's purpose is to accept a command and arguments and run them.

It's intended to be called from a crontab like this:

30 * * * * root sh cron-wrapper.sh sh cron-job.sh >/dev/null

Note that when outputing everything on stderr "everything" is output to stderr not stdout to fulfill my requirement that cron email everything on stderr output

Script:

#!/bin/bash # Input cmd=$1 shift # Run given command in background so we can tail output files immediately stdoutFile=`mktemp` stderrFile=`mktemp` $cmd "${@}" >"$stdoutFile" 2>"$stderrFile" & cmdPid=$! # Tail stdout and stderr files teeFile=`mktemp` tail -F -s 0.01 --pid=$cmdPid --quiet --silent "$stdoutFile" "$stderrFile" | tee "$teeFile" # Output everything if stderr output detected if [ -s "$stderrFile" ]; then cat "$teeFile" >&2 fi # Clean up rm -f "$stdoutFile" "$stderrFile" "$teeFile" 
1
  • I'm letting this implementation settle with a real cron job to make sure it's doing what I want. Then I'll probably mark this as the answer. Commented Feb 22, 2024 at 19:28
0

Use cronic which does exactly that. From the web page:

Cronic is a small shim shell script for wrapping cron jobs so that cron only sends email when an error has occurred. Cronic defines an error as any non-trace error output or a non-zero result code.

Example:

# Do the thing as 23:42 every day. 42 23 * * * cronic /root/.local/bin/doit.sh 
2
  • Hard to tell if and how cronic emails stdout and stderr output. The goal of mine was to output both outputs in as much the same order as they were originally output. Commented Jan 22 at 21:32
  • The order in which both are displayed is not really fixed, they are two streams and the shell is free to poll from them as it wants. But maybe that's what you mean with "as much"? Cronic loses every temporal relation though, that's true.. Commented Jan 30 at 9:13

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.