毎日実行するようにスケジュールされている cron ジョブがありますが、スケジュールを変更する以外に、コマンドを今すぐテスト実行して、意図したとおりに動作するかどうかを確認する方法はありますか?
編集: (コメントから) シェル (私のシェル) にコマンドを入力すると正常に機能することはわかっていますが、cron で実行したときに正しく機能するかどうかを知りたいのですが、ENV やシェル固有のもの (~ 拡張)、所有権や権限などの影響を受ける可能性があります...
答え1
次のコマンドで crontab を強制的に実行できます。
run-parts /etc/cron.daily
答え2
cronユーザー環境をシミュレートするには、「cron ジョブを手動ですぐに実行する」これにより、cron ユーザーとして実行されたときにジョブが機能するかどうかをテストできます。
リンクからの抜粋:
ステップ1: この行を一時的にユーザーの crontab に配置します:
* * * * * /usr/bin/env > /home/username/tmp/cron-env
ファイルが書き込まれたら、それを取り出しました。
ステップ2: 以下の内容を含む小さな run-as-cron bash スクリプトを作成しました:
#!/bin/bash
/usr/bin/env -i $(cat /home/username/tmp/cron-env) "$@"
そこで、問題のユーザーとして、私は
run-as-cron /the/problematic/script --with arguments --and parameters
答え3
私の知る限り、cron には特定の時間にスケジュールされたコマンドを実行するという特別な目的があるため、これを直接実行する方法はありません。したがって、最善の方法は、手動で (一時的な) crontab エントリを作成するか、環境を削除してリセットするスクリプトを作成することです。
「環境を削除してリセットする」の説明:
ラッパー スクリプトはenv -i
(環境を削除する) を使用して開始できます。これにより、set -a
スクリプトを開始する前に、保存された環境がソース化されます (最初に設定することによって、すべての変数がエクスポートされていることを確認します)。
保存された環境は、cron ジョブのデフォルト環境であり、cron ジョブとして実行することによって記録されenv
(または、declare -p
cron ジョブが使用するシェルに応じて)、その出力が保存されます。
答え4
cron ジョブをデバッグする必要が生じたため、次のスクリプトを作成しました。コマンドを実行する前に、cron とまったく同じ条件をシミュレートしようとします (変更された環境が含まれますが、非対話型シェル、接続されていないターミナルなどにも関係します)。
コマンド/スクリプトを引数として呼び出すと、cron ジョブを即座に簡単にデバッグできます。また、GitHub でもホストされています (更新される可能性もあります)。run-as-cron.sh
:
#!/bin/bash
# Run as if it was called from cron, that is to say:
# * with a modified environment
# * with a specific shell, which may or may not be bash
# * without an attached input terminal
# * in a non-interactive shell
function usage(){
echo "$0 - Run a script or a command as it would be in a cron job," \
"then display its output"
echo "Usage:"
echo " $0 [command | script]"
}
if [ "$1" == "-h" -o "$1" == "--help" ]; then
usage
exit 0
fi
if [ $(whoami) != "root" ]; then
echo "Only root is supported at the moment"
exit 1
fi
# This file should contain the cron environment.
cron_env="/root/cron-env"
if [ ! -f "$cron_env" ]; then
echo "Unable to find $cron_env"
echo "To generate it, run \"/usr/bin/env > /root/cron-env\" as a cron job"
exit 0
fi
# It will be a nightmare to expand "$@" inside a shell -c argument.
# Let's rather generate a string where we manually expand-and-quote the arguments
env_string="/usr/bin/env -i "
for envi in $(cat "$cron_env"); do
env_string="${env_string} $envi "
done
cmd_string=""
for arg in "$@"; do
cmd_string="${cmd_string} \"${arg}\" "
done
# Which shell should we use?
the_shell=$(grep -E "^SHELL=" /root/cron-env | sed 's/SHELL=//')
echo "Running with $the_shell the following command: $cmd_string"
# Let's redirect the output into files
# and provide /dev/null as input
# (so that the command is executed without an open terminal
# on any standard file descriptor)
so=$(mktemp "/tmp/fakecron.out.XXXX")
se=$(mktemp "/tmp/fakecron.err.XXXX")
"$the_shell" -c "$env_string $cmd_string" > "$so" 2> "$se" < /dev/null
echo -e "Done. Here is \033[1mstdout\033[0m:"
cat "$so"
echo -e "Done. Here is \033[1mstderr\033[0m:"
cat "$se"
rm "$so" "$se"