bash脚本可以判断它是否通过cron运行?

时间:2010-07-09 17:09:11

标签: bash cron

没有太多运气谷歌搜索这个问题,我想在SF上发布它,但它实际上似乎是一个开发问题。如果没有,请随意迁移。

所以,我有一个脚本每天凌晨3点左右通过cron运行。我有时也手动运行相同的脚本。问题是,每次我手动运行脚本并失败时,它都会向我发送一封电子邮件;即使我可以查看输出并在控制台中查看错误。

有没有办法让bash脚本告诉它是通过cron运行的(也许是通过使用whoami)并且只发送电子邮件,如果是这样的话?当我正在进行测试时,我很想停止接收电子邮件......

9 个答案:

答案 0 :(得分:26)

您可以尝试“tty”查看它是否由终端运行。这不会告诉你它是由cron专门运行的,但你可以判断它是否“不是用户提示”。

你也可以得到你的父亲pid并在树上追查cron,虽然这有点笨拙。

答案 1 :(得分:9)

为什么没有命令行参数-t用于测试或-c用于cron。

或者更好:

-e=email@address.com

如果未指定,请勿发送电子邮件。

答案 2 :(得分:9)

以下是两种不同的选择:

  • 通过电子邮件发送您的脚本/程序,让cron处理它。如果在crontab中设置MAILTO变量,cron将发送打印到该电子邮件地址的任何内容。例如:

    MAILTO=youremail@example.com
    # run five minutes after midnight, every day
    5 0 * * *       $HOME/bin/daily.job
    
  • 在crontab中设置一个环境变量,用于确定是否在cron下运行。例如:

    THIS_IS_CRON=1
    # run five minutes after midnight, every day
    5 0 * * *       $HOME/bin/daily.job
    

    并在您的脚本中

    if [ -n "$THIS_IS_CRON" ]; then echo "I'm running in cron"; else echo "I'm not running in cron"; fi
    

答案 3 :(得分:7)

我有类似的问题。我通过检查stdout是否是TTY来解决它。这是检查脚本是否以交互模式运行的检查:

if [ -t 1 ] ; then 
    echo "interacive mode";
else
    #send mail
fi

我从How to detect if my shell script is running through a pipe?

得到了这个

如果文件描述符打开并且引用终端,则-t test返回true。 '1'是stdout。

答案 4 :(得分:6)

我知道这个问题很老,但我遇到了同样的问题。这是我的解决方案:

CRON=$(pstree -s $$ | grep -q cron && echo true || echo false)

然后用

进行测试
if $CRON
then
    echo "Being run by cron"
else
    echo "Not being run by cron"
fi

与@eruciform提到的想法相同 - 跟随你的PID检查进程树检查cron。

注意:此解决方案仅适用于cron,与其他一些解决方案不同,后者可以在非交互式运行脚本时随时工作。

答案 5 :(得分:4)

对我有用的是检查$TERM。在cron下,它是愚蠢的"但在一个外壳下它是别的东西。在终端中使用set命令,然后在cron脚本中查看

if [ "dumb" == "$TERM" ]
then
    echo "cron"
else
    echo "term"
fi

答案 6 :(得分:4)

我想对这个高度投票的问题提出新答案。这仅适用于loginctl的系统系统(例如Ubuntu 14.10 +,RHEL / CentOS 7+),但能够提供比以前提供的解决方案更具权威性的答案。

service=$(loginctl --property=Service show-session $(</proc/self/sessionid))
if [[ ${service#*=} == 'crond' ]]; then
   echo "running in cron"
fi

总结:当与systemd一起使用时,crond(如sshd和其他人)在为用户启动作业时会创建新的session。此会话具有唯一的ID,用于整个机器的正常运行时间。每个会话都有一些属性,其中一个属性是启动它的服务的名称。 loginctl可以告诉我们这个属性的价值,它将是&#34; crond&#34; 当且仅当会话实际上是由crond启动的时候。

使用环境变量的优点:

  • 无需修改cron条目以添加特殊调用或环境变量
  • 中间过程不可能修改环境变量以创建误报或漏报

测试tty的优点:

  • 管道,启动脚本等没有误报

检查进程树的优点:

  • 其名称中也有crond的进程没有误报。
  • 如果脚本被拒绝,则不会出现错误否定

答案 7 :(得分:0)

我也很喜欢Tal的想法,但也看到了未定义回报的风险。我最终得到了一个稍微修改过的版本,在我看来这似乎非常顺利:

CRON="$( pstree -s $$ | grep -c cron )"

因此,您可以随时检查$ CRON是1还是0。

答案 8 :(得分:0)

以前的文章中使用的许多命令并非在每个系统上都可用(pstree,loginctl,tty)。这是唯一对我已经使用了10年的BusyBox / OpenWrt路由器起作用的东西,我目前将其用作黑名单DNS服务器。它运行具有自动更新功能的脚本。从crontab运行,它将发送电子邮件。

[ -z "$TERM" ] || [ "$TERM" = "dumb" ] && echo 'Crontab' || echo 'Interactive'

在交互式外壳中,$TERM变量为我返回值vt102。因为@edoceo提到“哑巴”对他有用,所以我包括了“哑巴”支票。我没有使用'==',因为它不是完全可移植的。