web-dev-qa-db-ja.com

毎週のcronジョブをテストする方法

Cron.weekディレクトリに#!/bin/bashファイルがあります。

それが機能するかどうかをテストする方法はありますか? 1週間待てない

私はrootでDebian 6にいます

223
dynamic

Cronが行うことをするだけで、以下をrootとして実行します。

run-parts -v /etc/cron.weekly

...または「Not a directory:-v」というエラーが表示された場合は、次のエラーメッセージが表示されます。

run-parts /etc/cron.weekly -v

オプション-vは、実行前にスクリプト名を表示します。

224
NNRooth

あなたの質問の範囲を少し超えたところで...しかし、ここに私がしていることがあります。

「どのようにしてcronジョブをテストするのですか?」質問は、「他のプログラムによって起動された非対話型コンテキストで実行されるスクリプトをどのようにテストするのですか」と密接に関係しています。 cronでは、トリガーは時間条件ですが、他の多くの* nix機能は非対話的な方法でスクリプトまたはスクリプトフラグメントを起動します。また、これらのスクリプトが実行される条件には予期しないものが含まれます。

この問題への一般的なアプローチは持っているのに役立ちます。

私のお気に入りのテクニックの1つは、私が書いたスクリプト「 crontest 」を使うことです。これは、cron内からGNU画面セッション内でtargetコマンドを起動するので、別の端末に接続して何が起こっているのかを確認したり、スクリプトと対話したり、デバッガを使用したりできます。

これを設定するには、crontabエントリに "all stars"を使用し、コマンドラインの最初のコマンドとしてcrontestを指定します。

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

そのため、cronは毎分コマンドを実行しますが、crontestは一度に1つのインスタンスしか実行しないようにします。コマンドの実行に時間がかかる場合は、 "screen -x"を実行してそれをアタッチして実行を監視できます。コマンドがスクリプトの場合は、「read」コマンドを先頭に置いて停止させ、画面への添付が完了するのを待ちます(添付後にEnterキーを押す)。

コマンドが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
81
Stabledog

即座に互換性がないcronのいくつかのものをいじった後、私は次のアプローチがデバッグにはナイスであることがわかりました:

crontab -e

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

これは1分に1回タスクを実行します、そしてあなたは単に何が起こっているのか理解するために/tmp/cron_debug_log.logファイルを調べることができます。

それはあなたが探しているかもしれないまさしく "ファイアジョブ"ではありません、しかし、これは最初cronで働かなかったスクリプトをデバッグするとき私が大いに役立ちました。

39
Automatico

ロックファイルを使用してから、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
23
dave fernholz

それをcron.hourlyに入れて、次に毎時のcronジョブが実行されるまで待ってから削除しますか?それは1時間に1回、そしてcron環境でそれを実行するでしょう。 ./your_scriptを実行することもできますが、cronと同じ環境にはなりません。

5

それ以外にも使用することができます:

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

成功または失敗したときにあなたに電子メールを送るためにあなたのcronをまとめるため。

4
Low Kian Seong

これらの答えのどれもが私の特定の状況に適合しませんでした、それは私が1つの特定のcronジョブを一度だけ実行してすぐに実行したいということでした。

私はUbuntuサーバーを使っています、そしてcronを設定するのにcPanelを使います。

私は単に自分の現在の設定を書き留めてから、今から1分後になるようにそれらを編集しました。別のバグを修正したとき、今から1分後にもう一度編集しました。そして、すべてが終わったら、設定を元の状態にリセットします。

例:今は午後4時34分なので、16:35に実行するには35 16 * * *と入力します。

それは魅力のように働きました、そして私が今まで待たなければならなかったほとんどは1分弱でした。

私はこれを他のいくつかの答えよりも良い選択肢だと思いました。私は自分の毎週のクローンのすべてを実行したくなかったし、私は毎分ジョブを実行したくなかったからです。再度テストする準備が整う前に、問題が解決してから数分かかります。うまくいけば、これは誰かに役立ちます。

4
Ben C

私は通常私がこのように作成したジョブを実行してテストします。

これを行うには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
Dorlack
Sudo run-parts --test /var/spool/cron/crontabs/

そのcrontabs/ディレクトリ内のファイルは、所有者が実行可能である必要があります - 8進数の700

出典:man cronおよび NNRooth

2
n611x007

私が使用している解決策は次のとおりです。

  1. Crontabを編集して(コマンド:crontab -eを使用)、必要に応じて(1分または5分ごとに)ジョブを実行します。
  2. Cronを使用して実行する必要があるシェルスクリプトを変更して、出力を何らかのファイルに出力します(例:echo "Working fine" >>
    output.txt)
  3. Tail -f output.txtコマンドを使用して、output.txtファイルを確認します。これにより、最新の追加がこのファイルに出力され、スクリプトの実行を追跡できます。
2
Abhilash