代码之家  ›  专栏  ›  技术社区  ›  Topher Fangio

一个bash脚本能告诉我们它是否是通过cron运行的吗?

  •  24
  • Topher Fangio  · 技术社区  · 14 年前

    在谷歌上搜索这个问题并没有什么运气,我想把它发布到SF上,但实际上它看起来像是一个开发问题。如果没有,请随时迁移。

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

    有没有一种方法可以让bash脚本告诉它正在通过cron运行(可能是通过使用whoami),如果是,只发送电子邮件?当我做测试的时候我很想停止接收邮件…

    8 回复  |  直到 7 年前
        1
  •  25
  •   eruciform    14 年前

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

    你也可以得到你的家长PID,并跟踪它在树上寻找cron,尽管这有点笨手笨脚。

        2
  •  9
  •   d-_-b    14 年前

    为什么不使用命令行参数来测试-t或cron的-c。

    或者更好的是:

    -电子邮箱:email@address.com

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

        3
  •  8
  •   Geoff Reedy    14 年前

    以下是两个不同的选项:

    • 把邮件从你的脚本/程序中取出,让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
      
        4
  •  7
  •   Community Marks    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测试返回true。1是STDUT。

        5
  •  6
  •   Tal    10 年前

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

    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,与其他一些解决方案不同,这些解决方案在脚本非交互运行的任何时候都有效。

        6
  •  4
  •   edoceo    10 年前

    对我来说有效的是检查 $TERM . 在克罗恩的统治下,这是“愚蠢的”,但在壳下,这是另一回事。使用 set 命令在终端中,然后在cron脚本中检查它

    if [ "dumb" == "$TERM" ]
    then
        echo "cron"
    else
        echo "term"
    fi
    
        7
  •  4
  •   Grisha Levit    8 年前

    我想对这个投票率很高的问题提出一个新的答案。这仅适用于具有 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对于机器的整个正常运行时间是唯一的。每个会话都有一些属性,其中一个是启动它的服务的名称。 洛克林 可以告诉我们这个属性的值,它将是“ 周期任务 当且仅当 会话实际上是由crond启动的。


    使用环境变量的优势:

    • 不需要修改cron条目来添加特殊调用或环境变量
    • 中间过程不可能修改环境变量以创建假正或假负

    TTY测试的优势:

    • 管道、启动脚本等中无误报

    与检查流程树相比的优势:

    • 没有来自同样具有 周期任务 以他们的名义
    • 如果脚本被拒绝,则没有错误的否定
        8
  •  0
  •   frank42    7 年前

    我也喜欢好未来的想法,但也看到了不确定回报的风险。我最后得到了一个稍微修改过的版本,在我看来,它的工作非常顺利:

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

    所以你可以随时检查$cron是1还是0。