仅在 stderr 上通过电子邮件发送所有 cron stdout+stderr 输出

仅在 stderr 上通过电子邮件发送所有 cron stdout+stderr 输出

我希望 cron 只在 stderr 输出上发送电子邮件,但当它这样做时,它应该包括所有 stdout 和 stderr

这与通常仅在 stderr 上发送电子邮件(即,将 stdout 重定向到 /dev/null)的问题不同。在这种情况下,cron 只会向 stderr 发送电子邮件,但我希望查看所有内容以了解上下文。

我正在运行 Rocky 9,并以 cronie 作为 cron 守护程序。

答案1

如果命令以非零状态代码退出,您可以尝试:

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

在哪里:

  • bash -c ''允许在 cronjob 上使用多个命令;您也可以使用脚本。
  • command是要执行的命令的路径
  • 2>&1将 stderr 重定向到 stdout
  • > /tmp/err将 stdout(现在是两个流)保存到文件(路径/tmp/err
  • ||仅当第一个命令失败且状态代码非零时才运行第二个命令
  • mail -A /tmp/err将文件作为附件发送

您可以增强此功能,例如,在同时运行且文件末尾缺少某些内容的mktemp情况下,对每个日志使用不同的路径。sleep

答案2

我决定编写一个脚本来近似解决仅在 stderr 输出上发送电子邮件的问题。

关键是将 stdout/stderr 存储到文件中,直到检测到 stderr,然后输出组合文件。

只要 tail 能够足够快地迭代其文件,那么合并的文件就可以大致保持 stdout/stderr 顺序。如果没有缓冲,命令需要一两秒以上,并且 stdout/stderr 输出之间存在一些延迟,则此方法可以近似有序的 stdout/stderr 输出。

我将此脚本命名为 cron-wrapper.sh。其目的是接受命令和参数并运行它们。

它旨在从 crontab 中调用,如下所示:

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

请注意,在 stderr 上输出所有内容时,“所有内容”都输出到 stderr 而不是 stdout,以满足我的要求,即 cron 通过电子邮件发送 stderr 输出上的所有内容

脚本:

#!/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"

相关内容