测试每周的cron工作[关闭]


237

#!/bin/bash在cron.week目录中有一个文件。

有没有办法测试它是否有效?等不及1个星期

我以root身份在Debian 6上


4
您不能仅通过在命令行上运行脚本来测试脚本吗?
弗雷德里克·哈米迪

5
只需在其中添加一个单独的条目,crontab该条目每隔几分钟运行一次文件,查看是否有预期的结果,然后从crontab中删除测试条目。尝试crontab -e
戴文,2011年

61
不,从命令行运行它不是一个好方法。仅从命令行运行脚本不能保证它甚至可以像从cron运行时一样以相同的用户身份运行。即使确实以同一用户身份运行,您也无法确定其他所有内容是否都相同。脚本命令行工作可能无法为所有从cron运行时的理由多种多样。
andynormancx

8
“各种”可能有点双曲线...权限和环境变量是我想到的两个,但是您可以轻松地拥有其他不同的初始条件,例如别名
andynormancx 2014年

3
我刚刚测试了一个新的cron作业,我将另一个项目添加到“各种”中。如果您在bash_profile中有内容,则它们不会在cron作业中运行一次,而从命令行测试该作业则效果很好。在标准命令行上测试cron作业根本不是一个好的测试。
andynormancx 16-4-24

Answers:


233

只需执行cron的操作,即可运行以下命令root

run-parts -v /etc/cron.weekly

...或下一个,如果收到“不是目录:-v”错误:

run-parts /etc/cron.weekly -v

Option -v在运行脚本之前先打印脚本名称。


4
如果我使用-v选项,它显示“不是目录:-v”错误,则我的系统中没有此命令的手册页,-v表示详细信息吗?我正在使用centos 6.4
最高

3
为避免出现“不是目录”错误,我不得不改做:run-parts /etc/cron.weekly -v
Craig Hyatt

22
但这没有考虑可能在crontab中设置的环境变量
fcurella 2014年

34
run-parts只运行给定目录的脚本。与cron无关。
Nicolas 2014年

23
这确实不应该被接受和接受,除了运行脚本之外,它并不能告诉您从cron运行时该脚本是否真正起作用。在此问题的其他答案之一中,使用出色的crontest脚本。
andynormancx 16-4-24

87

有点超出您问题的范围...但是这就是我的工作。

“我如何测试cron工作?” 这个问题与“我如何测试在其他程序启动的非交互式上下文中运行的脚本”紧密相关?在cron中,触发器是一个时间条件,但是许多其他* nix工具以非交互方式启动脚本或脚本片段,并且这些脚本运行的条件通常包含意外情况并导致损坏,直到错误被解决为止。 (另请参阅:https : //stackoverflow.com/a/17805088/237059

解决此问题的一般方法很有帮助。

我最喜欢的技术之一是使用我编写的脚本“ crontest ”。它在cron内的GNU屏幕会话内启动目标命令,因此您可以附加一个单独的终端以查看发生了什么,与脚本进行交互,甚至使用调试器。

要进行设置,您可以在crontab条目中使用“所有星号”,并在命令行上将crontest指定为第一个命令,例如:

* * * * * crontest /command/to/be/tested --param1 --param2

因此,现在cron将每分钟运行一次命令,但是crontest将确保一次仅运行一个实例。如果该命令花费时间来运行,则可以执行“ screen -x”来附加并观看其运行。如果该命令是脚本,则可以在顶部放置“读取”命令以使其停止并等待屏幕附件完成(附加后按回车键)

如果您的命令是bash脚本,则可以执行以下操作:

* * * * * crontest --bashdb /command/to/be/tested --param1 --param2

现在,如果您附加“ screen -x”,您将面临一个交互式bashdb会话,并且可以单步执行代码,检查变量等。

#!/bin/bash

# crontest
# See https://github.com/Stabledog/crontest for canonical source.

# Test wrapper for cron tasks.  The suggested use is:
#
#  1. When adding your cron job, use all 5 stars to make it run every minute
#  2. Wrap the command in crontest
#        
#
#  Example:
#
#  $ crontab -e
#     * * * * * /usr/local/bin/crontest $HOME/bin/my-new-script --myparams
#
#  Now, cron will run your job every minute, but crontest will only allow one
#  instance to run at a time.  
#
#  crontest always wraps the command in "screen -d -m" if possible, so you can
#  use "screen -x" to attach and interact with the job.   
#
#  If --bashdb is used, the command line will be passed to bashdb.  Thus you
#  can attach with "screen -x" and debug the remaining command in context.
#
#  NOTES:
#   - crontest can be used in other contexts, it doesn't have to be a cron job.
#       Any place where commands are invoked without an interactive terminal and
#       may need to be debugged.
#
#   - crontest writes its own stuff to /tmp/crontest.log
#
#   - If GNU screen isn't available, neither is --bashdb
#

crontestLog=/tmp/crontest.log
lockfile=$(if [[ -d /var/lock ]]; then echo /var/lock/crontest.lock; else echo /tmp/crontest.lock; fi )
useBashdb=false
useScreen=$( if which screen &>/dev/null; then echo true; else echo false; fi )
innerArgs="$@"
screenBin=$(which screen 2>/dev/null)

function errExit {
    echo "[-err-] $@" | tee -a $crontestLog >&2
}

function log {
    echo "[-stat-] $@" >> $crontestLog
}

function parseArgs {
    while [[ ! -z $1 ]]; do
        case $1 in
            --bashdb)
                if ! $useScreen; then
                    errExit "--bashdb invalid in crontest because GNU screen not installed"
                fi
                if ! which bashdb &>/dev/null; then
                    errExit "--bashdb invalid in crontest: no bashdb on the PATH"
                fi

                useBashdb=true
                ;;
            --)
                shift
                innerArgs="$@"
                return 0
                ;;
            *)
                innerArgs="$@"
                return 0
                ;;
        esac
        shift
    done
}

if [[ -z  $sourceMe ]]; then
    # Lock the lockfile (no, we do not wish to follow the standard
    # advice of wrapping this in a subshell!)
    exec 9>$lockfile
    flock -n 9 || exit 1

    # Zap any old log data:
    [[ -f $crontestLog ]] && rm -f $crontestLog

    parseArgs "$@"

    log "crontest starting at $(date)"
    log "Raw command line: $@"
    log "Inner args: $@"
    log "screenBin: $screenBin"
    log "useBashdb: $( if $useBashdb; then echo YES; else echo no; fi )"
    log "useScreen: $( if $useScreen; then echo YES; else echo no; fi )"

    # Were building a command line.
    cmdline=""

    # If screen is available, put the task inside a pseudo-terminal
    # owned by screen.  That allows the developer to do a "screen -x" to
    # interact with the running command:
    if $useScreen; then
        cmdline="$screenBin -D -m "
    fi

    # If bashdb is installed and --bashdb is specified on the command line,
    # pass the command to bashdb.  This allows the developer to do a "screen -x" to
    # interactively debug a bash shell script:
    if $useBashdb; then
        cmdline="$cmdline $(which bashdb) "
    fi

    # Finally, append the target command and params:
    cmdline="$cmdline $innerArgs"

    log "cmdline: $cmdline"


    # And run the whole schlock:
    $cmdline 

    res=$?

    log "Command result: $res"


    echo "[-result-] $(if [[ $res -eq 0 ]]; then echo ok; else echo fail; fi)" >> $crontestLog

    # Release the lock:
    9<&-
fi

2
太棒了,完美的解决方案。我尝试过的所有其他技术都没有真正起作用,crontest轻松解决了该问题。
andynormancx 16-4-24

1
这远远超出了我的需要,但无论如何都需要+1。将cron设置为更频繁地运行并将输出转储到/ tmp足以发现我的问题。
jcollum

2
凉。是的,如果您只需要一把铲子,就没有理由解雇推土机了:)
Stabledog

2
好东西。在Mac上注意,我必须先brew tap discoteq/discoteq; brew install flock修改脚本才能使用/usr/local/bin/flock
Claudiu

1
好实用!在非交互式上下文中诊断身份验证问题非常有用。
埃里克·布鲁姆

44

在弄乱了cron中的某些东西之后,这些东西不是立即兼容的,我发现以下方法非常适合调试:

crontab -e

* * * * * /path/to/prog var1 var2 &>>/tmp/cron_debug_log.log

这将每分钟运行一次任务,您只需查看/tmp/cron_debug_log.log文件即可了解正在发生的情况。

这并不是您可能正在寻找的“消防工作”,但这在调试最初在cron中不起作用的脚本时对我有很大帮助。


9
我会推荐这种方法。在大多数情况下,问题是您看不到错误。
Yauhen Yakimovich

8
错误的行,不是任何发行版都将bash用于cron shell,因此&>>不起作用。我建议用 >>/tmp/cron_debug_log.log 2>&1相反
崔斯特

1
您是什么意思/path/to/prog-哪个编?
内森

3
您将要使用cron运行的程序。这可以是usr/home/myFancyScript.sh或可以是简单的ls,也可以是要定期运行的任何内容。
Automatico

这对我有用。这是进行快速测试以检查一切是否正常的最简单方法
Abhijit

25

我会使用一个锁定文件,然后将cron作业设置为每分钟运行一次。(使用crontab -e和* * * * * / path / to / job)这样,您可以继续编辑文件,并且每分钟都会对其进行测试。此外,您只需触摸锁定文件即可停止cronjob。

    #!/bin/sh
    if [ -e /tmp/cronlock ]
    then
        echo "cronjob locked"
        exit 1
    fi

    touch /tmp/cronlock
    <...do your regular cron here ....>
    rm -f /tmp/cronlock

4
您也可以flock(1)从shell 使用;见man 1 flock。这种用途非常方便,因为它提供了自动阻止功能。
Craig Ringer

5

把它放进去cron.hourly,等到下一次每小时一次的cron作业,然后再删除它,该怎么办?这将在一个小时内在cron环境中运行一次。您也可以运行./your_script,但是环境不会与cron下的环境相同。


这是几乎一样@ Cort3z的答案,以较少的细节
jcollum

5

这些答案都不适合我的具体情况,即我只想运行一个特定的cron作业一次,然后立即运行它。

我在Ubuntu服务器上,使用cPanel设置我的cron作业。

我只是写下我当前的设置,然后将它们编辑到现在的一分钟。当我修复了另一个错误时,我只是将其编辑到现在的一分钟。当我完成所有工作后,我只是将设置重置为以前的设置。

示例:现在是下午4:34,所以我将35 16 * * *设置为在16:35运行。

它像一种魅力一样工作,而我所需要等待的最短时间只有不到一分钟。

我认为这是一个比其他答案更好的选择,因为我不想运行所有每周的任务,而且我也不希望这项工作每分钟运行一次。在准备再次进行测试之前,我需要花费几分钟来解决所有问题。希望这对某人有帮助。


为什么要使用cron运行“仅一次,然后立即运行”?听起来,直接运行脚本会更好。
伊恩·亨特

4

除此之外,您还可以使用:

http://pypi.python.org/pypi/cronwrap

整理您的Cron,以便在成功或失败后向您发送电子邮件。


10
Cron在执行时是否已经通过脚本发送电子邮件并输出?
Erik

Cron向用户发送电子邮件,通常大多数cron作业的用户是root用户或非交互式仅服务用户,因此您永远不会看到电子邮件。当错误触发大量电子邮件并反弹到根时,这就是服务器填充的方式。
Dragon788

3

我正在使用的解决方案如下:

  1. 编辑crontab(使用命令:crontab -e)以根据需要频繁运行作业(每1分钟或5分钟)
  2. 修改应使用cron执行的shell脚本,以将输出打印到某些文件中(例如:echo“ Working fine” >>
    output.txt)
  3. 使用以下命令检查output.txt文件:tail -f output.txt,该命令会将最新添加的内容打印到该文件中,因此您可以跟踪脚本的执行情况

2

我通常通过运行这样创建的作业来进行测试:

使用两个终端更容易执行此操作。

运行作业:

#./jobname.sh

去:

#/var/log and run 

运行以下命令:

#tailf /var/log/cron

这使我可以实时查看cron日志。您还可以在运行日志后查看日志,我更喜欢实时观看。

这是一个简单的cron作业示例。正在运行yum更新...

#!/bin/bash
YUM=/usr/bin/yum
$YUM -y -R 120 -d 0 -e 0 update yum
$YUM -y -R 10 -e 0 -d 0 update

这是细分:

第一个命令将自行更新yum,下一个命令将应用系统更新。

-R 120:设置yum在执行命令之前等待的最长时间

-e 0:将错误级别设置为0(范围0-10)。0表示仅打印必须告知您的严重错误。

-d 0:将调试级别设置为0-增大或减小打印的内容。(范围:0-10)。

-y:假设是;假设将要回答的任何问题的答案是肯定的

构建cron作业后,我运行以下命令使作业可执行。

#chmod +x /etc/cron.daily/jobname.sh 

希望这对您有帮助,Dorlack


2
sudo run-parts --test /var/spool/cron/crontabs/

crontabs/目录中的文件需要所有者执行 -八进制700

来源:man cronNNRooth


5
两声。第一:要以sudo的身份运行事物,请使用其他环境(定义的变量)。因此,crontab中的错误在以“ sudo”执行时可以工作,而在以“ root”执行时则不能工作(反之亦然)。第二:“ man cron”不会向我显示此信息(好吧,我的男人似乎是特定于debian的)。他们。因此,这些脚本甚至都没有经过测试。一件小事:“可由所有者执行”:据我所知,cronjobs仅作为root执行。
Alex

-1

我之所以使用Webmin,是因为它对于那些发现命令行管理有些艰巨和不可穿透的人来说是一个生产力宝。

Web界面中的“系统>计划的Cron作业>编辑Cron作业”中有一个“保存并立即运行”按钮。

它显示命令的输出,正是我所需要的。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.