毎週のcronジョブをテストする[終了]


237

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

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

私はrootでDebian 6を使用しています


4
コマンドラインで実行してスクリプトをテストすることはできませんか?
フレデリックハミディ

5
crontab数分ごとにファイルを実行する別のエントリをに追加し、期待される結果があるかどうかを確認してから、crontabからテストエントリを削除します。試してみるcrontab -e
davin

61
いいえ、コマンドラインから実行するのは良い方法ではありません。コマンドラインからスクリプトを実行しただけでは、cronから実行したときと同じユーザーとして実行されるとは限りません。同じユーザーとして実行されたとしても、他のすべてが同じになるかどうかは決してわかりません。コマンドラインからの作業をするために失敗することをスクリプトすべてのcronから実行する場合の理由の種類。
andynormancx 2013年

8
「すべての並べ替え」はわずかに双曲線的である可能性があります...権限と環境変数は2つ思い浮かぶ2つですが、エイリアスのような他の異なる初期条件を簡単に持つことができます
andynormancx

3
私は新しいcronジョブをテストしたばかりなので、「すべての種類」に別の項目を追加します。bash_profileに何かがある場合、それらはcronジョブで一度は実行されませんが、コマンドラインからのジョブのテストは完全に機能します。標準のコマンドラインでcronジョブをテストすることは、まったく良いテストではありません。
andynormancx

回答:


233

cronが行うことを行うだけで、次のように実行しますroot

run-parts -v /etc/cron.weekly

...または、「ディレクトリではありません:-v」エラーを受け取った場合の次のエラー:

run-parts /etc/cron.weekly -v

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


4
-vオプションを使用すると、「ディレクトリではありません:-v」エラーが表示されますが、システムにこのコマンドのmanページがありません。CentOS 6.4を使用しています
最大

3
「ディレクトリではない」エラーを回避するために、代わりにこれを実行する必要がありました。run-parts /etc/cron.weekly -v
Craig Hyatt

22
しかし、これはcrontabで設定できる環境変数を考慮に入れていません
fcurella

34
run-parts特定のディレクトリのスクリプトを実行するだけです。cronとは関係ありません。
ニコラ

23
これは実際には賛成も受け入れもされるべきではありません。スクリプトを実行する以外に、cronから実行したときにスクリプトが実際に機能するかどうかを通知するものではありません。この質問に対する他の回答の1つで優れたcrontestスクリプトを使用してください。
andynormancx

87

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

「cronジョブをテストするにはどうすればよいですか?」質問は、「他のプログラムによって起動された非インタラクティブなコンテキストで実行されるスクリプトをどのようにテストするか」と密接に関連しています。cronでは、トリガーは一定の時間条件ですが、他の多くの* nix機能は非インタラクティブな方法でスクリプトまたはスクリプトフラグメントを起動します。多くの場合、これらのスクリプトが実行される条件には予期しない何かが含まれ、バグが解決されるまで破損します。 (参照:https : //stackoverflow.com/a/17805088/237059

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

私のお気に入りのテクニックの1つは、私が書いた「crontest」というスクリプトを使用することです。cron内からGNUスクリーンセッション内でターゲットコマンドを起動するため、別のターミナルに接続して、何が起こっているのかを確認したり、スクリプトを操作したり、デバッガーを使用したりすることもできます。

これを設定するには、crontabエントリで「すべての星」を使用し、コマンドラインの最初のコマンドとしてcrontestを指定します。例:

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

したがって、cronは毎分コマンドを実行しますが、crontestは一度に1つのインスタンスのみが実行されるようにします。コマンドの実行に時間がかかる場合は、「screen -x」を実行して、接続して実行を監視できます。コマンドがスクリプトの場合は、「読み取り」コマンドを上部に配置して停止し、画面のアタッチが完了するのを待ちます(アタッチ後に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

2
素晴らしい、完璧なソリューションです。私が試した他のテクニックはすべてうまくいきませんでした。crontestは問題を簡単に解決しました。
andynormancx

1
これは私が必要とするものをはるかに上回っていましたが、とにかく素晴らしい解決策として+1しました。より頻繁に実行するようにcronを設定し、出力を/ tmpにダンプすると、問題を特定するのに十分でした。
jcollum

2
涼しい。はい、ハンドスペードが必要な場合にブルドーザーを起動する理由はありません:)
Stabledog

2
素晴らしいもの。Macについての注意:brew tap discoteq/discoteq; brew install flock使用するスクリプトを変更する必要がありました/usr/local/bin/flock
Claudiu

1
素敵なユーティリティ!非インタラクティブなコンテキストで認証の問題を診断するのに非常に役立ちます。
Eric Blum

44

すぐに互換性のないcronの要素をいじった後、次の方法がデバッグに適していることがわかりました。

crontab -e

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

これにより、1分に1回タスクが実行され、/tmp/cron_debug_log.logファイルを調べるだけで何が起こっているのかを把握できます。

それは、まさにあなたが探している「火の仕事」ではありませんが、これは、最初はcronで機能しなかったスクリプトをデバッグする際に非常に役立ちました。


9
このアプローチをお勧めします。ほとんどの場合の問題は、エラーが表示されないことです。
Yauhen Yakimovich

8
不正な行。どのディストリビューションでもcronシェルにbashを使用していないため、&>>は機能しません。>>/tmp/cron_debug_log.log 2>&1代わりに使用することをお勧めします
drizzt

1
どういう意味/path/to/progですか-どのprog?
ネイサン

3
cronで実行するプログラム。これはusr/home/myFancyScript.sh、単純なものlsでも、定期的に実行したいものでもかまいません。
Automatico

これでうまくいきました。すべてが正常かどうかを確認するための簡単なテストを行うのが最も簡単な方法でした
アビジット

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)シェルからも使用できます。参照してくださいman 1 flock。自動ブロッキングを提供するので、そのような用途には非常に便利です。
クレイグリンガー、

5

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


これは、@ Cort3zの回答とほとんど同じですが、詳細は少なくなっています
jcollum

5

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

私はUbuntuサーバーを使用しており、cPanelを使用してcronジョブをセットアップしています。

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

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

それは魅力のように働きました、そして私が今まで待たなければならなかった最も多くは1分弱でした。

私は毎週のcronをすべて実行したくなかったし、ジョブを毎分実行したくなかったので、これは他のいくつかの回答よりも良いオプションだと思いました。再度テストする準備ができる前に、問題が何であれ修正するのに数分かかります。うまくいけば、これは誰かを助けます。


cronを使用して「一度だけ実行してすぐに実行する」のはなぜですか?スクリプトを直接実行した方がいいようです。
イアンハンター

4

それとは別に、次のものも使用できます。

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

成功または失敗したときにメールを送信するようにcronをラップします。


10
Cronは既に実行時にスクリプトから電子メールを送信して出力していませんか?
エリック

cronはユーザーにメールを送信します。通常、ほとんどのcronジョブのユーザーはrootユーザーまたは非対話型サービスのみのユーザーであるため、メールは表示されません。これは、エラーが大量の電子メールをトリガーし、ルートに跳ね返ったときにサーバーがいっぱいになる方法です。
dragon788

3

私が使用しているソリューションは次のとおりです:

  1. crontabを編集し(コマンド:crontab -eを使用)、必要な頻度でジョブを実行します(1分または5分ごと)。
  2. cronを使用して実行する必要があるシェルスクリプトを変更して、出力をファイルに出力します(例:echo "Working fine" >>
    output.txt)
  3. 次のコマンドを使用してoutput.txtファイルを確認します。tail-f output.txt。このファイルに最新の追加情報が出力されるため、スクリプトの実行を追跡できます。

2

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

これを行うには、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/ディレクトリ内のファイルは、所有者実行可能である必要があります -8進数700

ソース:man cronNNRooth


5
2ティン。まず、sudoが別の環境(定義された変数)を使用するように実行します。したがって、crontabのバグは「sudo」として実行すると機能しますが、「root」として実行すると機能しません(逆も同様です)。第二: 'man cron'は私にこの情報を表示しません(そうです、私の人はdebian固有のようです)... 'man run-parts'は--testはスクリプトを実行せず、それら。したがって、スクリプトもテストされていません。マイナーなこと:「所有者が実行可能」:私の知る限り、cronジョブはrootとしてのみ実行されます。
Alex

-1

Webminを使用しているのは、コマンドライン管理が少し困難で不可解な人のための生産性の宝石だからです。

「システム>スケジュールされたcronジョブ> cronジョブの編集」Webインターフェイスに「保存して今すぐ実行」ボタンがあります。

それはコマンドの出力を表示し、まさに私が必要としたものです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.