如何测试每周一次的cron工作?

时间:2011-02-13 14:38:38

标签: linux cron debian

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

有没有办法测试它是否有效?不能等待1周

我在Debian 6上使用root

11 个答案:

答案 0 :(得分:224)

只需执行cron所做的操作,运行以下root

run-parts -v /etc/cron.weekly

...或下一个如果收到“Not a directory:-v”错误:

run-parts /etc/cron.weekly -v

选项-v在脚本名称运行之前打印它们。

答案 1 :(得分:81)

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

“我该如何测试一个cron作业?”问题与“如何测试在其他程序启动的非交互式上下文中运行的脚本”密切相关?在cron,触发一定的时间条件,但许多其他的* nix设施发动非交互方式的脚本或脚本片段,并经常在这些脚本运行含有意想不到的事情而导致破损,直到错误都整理出来的条件。

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

我最喜欢的技巧之一是使用我写的名为“crontest”的脚本。它启动目标命令GNU屏幕会话内从cron中,这样就可以用一个单独的终端连接,看看发生了什么事情,与脚本进行交互,甚至使用调试器。

要进行此设置,您可以在crontab条目中使用“all stars”,并在命令行中指定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 :(得分:38)

在使用cron中的某些东西搞砸后,我发现以下方法很适合调试:

crontab -e

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

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

这不是&#34;消防工作&#34;你可能正在寻找,但是在调试一个最初没有在cron中工作的脚本时,这对我帮助很大。

答案 3 :(得分:23)

我使用锁定文件,然后将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 :(得分:5)

如何将它放入cron.hourly,等到下一轮小时cron作业,然后将其删除?那将在一小时内和cron环境中运行一次。您也可以运行./your_script,但这与cron下的环境不同。

答案 5 :(得分:4)

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

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

结束你的cron,在成功或失败时给你发电子邮件。

答案 6 :(得分:4)

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

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

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

示例:现在是下午4:34,所以我放了35 16 * * *,让它在16:35运行。

它就像一个魅力,而我曾经等待的最多只有不到一分钟。

我认为这是一个比其他一些答案更好的选择,因为我不想每周运行所有的crons,而且我不想让这份工作每分钟都运行一次。在我准备好再次测试之前,我需要花几分钟时间来解决所有问题。希望这有助于某人。

答案 7 :(得分: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:设置执行命令前等待的最长时间

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

-d 0:将调试级别设置为0 - 打开或关闭打印的内容量。 (范围:0 - 10)。

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

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

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

希望这有帮助, Dorlack

答案 8 :(得分:2)

sudo run-parts --test /var/spool/cron/crontabs/
crontabs/目录中的

文件必须所有者可执行 - 八进制700

来源:man cronNNRooth

答案 9 :(得分:2)

我使用的解决方案如下:

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

答案 10 :(得分:-1)

我使用Webmin因为它对于发现命令行管理有点令人生畏和难以理解的人来说是一个生产力宝石。

有一个&#34;保存并立即运行&#34; &#34;系统&gt;中的按钮预定的Cron工作&gt;编辑Cron Job&#34;网络界面。

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