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

dyn*_*mic 229 linux cron debian

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

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

我在Debian 6上用root

小智 229

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

run-parts -v /etc/cron.weekly
Run Code Online (Sandbox Code Playgroud)

...如果收到"Not a directory:-v"错误,则为下一个错误:

run-parts /etc/cron.weekly -v
Run Code Online (Sandbox Code Playgroud)

选项-v在运行之前打印脚本名称.

  • `run-parts`只运行给定目录的脚本.跟cron没什么关系. (31认同)
  • 但是这没有考虑可以在crontab中设置的环境变量 (21认同)
  • 这真的不应该被赞成和接受,除了运行脚本之外,它没有告诉你脚本在从cron运行时是否真的有效.在这个问题的其他答案之一中使用优秀的crontest脚本. (21认同)
  • 如果我使用-v选项显示"不是目录:-v"错误,我的系统中没有此命令的手册页,-v表示详细说明了吗?我正在使用centos 6.4 (4认同)
  • 为避免出现"Not a directory"错误,我不得不这样做:run-parts /etc/cron.weekly -v (3认同)

Sta*_*dog 83

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

"我该如何测试一个cron作业?" 问题与"如何测试在其他程序启动的非交互式上下文中运行的脚本"密切相关?在cron中,触发器是一些时间条件,但许多其他*nix工具以非交互方式启动脚本或脚本片段,并且这些脚本运行的条件通常包含意外情况并导致破坏,直到错误被整理出来.

这个问题的一般方法是有帮助的.

我最喜欢的技术之一是使用我写的一个名为' crontest ' 的脚本.它在cron内部的GNU屏幕会话中启动目标命令,这样您就可以使用单独的终端连接以查看正在发生的事情,与脚本交互,甚至使用调试器.

要进行此设置,您可以在crontab条目中使用"all stars",并在命令行中指定crontest作为第一个命令,例如:

* * * * * crontest /command/to/be/tested --param1 --param2
Run Code Online (Sandbox Code Playgroud)

所以现在cron将每分钟运行一次命令,但是crontest将确保一次只运行一个实例.如果命令需要一段时间才能运行,您可以执行"screen -x"连接并观察它运行.如果命令是脚本,您可以在顶部放置一个"读取"命令使其停止并等待屏幕附件完成(在附加后按Enter键)

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

* * * * * crontest --bashdb /command/to/be/tested --param1 --param2
Run Code Online (Sandbox Code Playgroud)

现在,如果你附加"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
Run Code Online (Sandbox Code Playgroud)

  • 真棒,完美的解决方案.我试过的所有其他技术都没有真正起作用,crontest很容易解决问题. (2认同)
  • 凉。是的,如果您只需要一把铲子,就没有理由点火推土机了:) (2认同)
  • 好东西。mac 上的注意事项我必须`brew tap discoteq/discoteq; brew install flock` 然后修改脚本使用`/usr/local/bin/flock` (2认同)

Aut*_*ico 41

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

crontab -e

* * * * * /path/to/prog var1 var2 &>>/tmp/cron_debug_log.log
Run Code Online (Sandbox Code Playgroud)

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

它并不完全是你可能正在寻找的"火力工作",但是在调试一个最初在cron中不起作用的脚本时,这对我帮助很大.

  • 我会推荐这种方法.大多数情况下的问题是您没有看到错误. (8认同)
  • 不正确的行,不是任何发行版使用bash for cron shell,因此&>>不起作用.我建议使用```/ tmp/cron_debug_log.log 2>&1```而不是 (8认同)
  • 你打算用cron运行的程序.这可以是`usr/home/myFancyScript.sh`,也可以是简单的`ls`,或者你想要经常运行的任何东西. (3认同)

小智 24

我使用锁文件,然后将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
Run Code Online (Sandbox Code Playgroud)

  • 你也可以从shell中使用`flock(1)`; 见'男人1羊群'.这种用途非常方便,因为它提供自动阻止功能. (4认同)

Jer*_*ock 5

怎么样把它放进去cron.hourly,等到下一轮每小时的cron工作,然后把它删除?那将在一小时内和cron环境中运行一次.您也可以运行./your_script,但这与cron下的环境不同.


Ben*_*n C 5

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

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

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

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

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

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