Category:
Linux
cron の実装である vixie-cron (およびそのフォーク版である cronie) では、@reboot という時刻指定の記法がサポートされています。
通常の crontab では、日付と時間を指定して
RHEL 5 までの vixie-cron では、@reboot は crond の起動時に必ず実行されるようになっていたため、例えば
RHEL 6 の cronie および最近の vixie-cron では、この問題は改善され、@reboot で指定されたコマンドは「システムで最初に crond が起動されたタイミングでのみ実行」されるようになっています。これがどのように実装されているのか気になったので、調べてみました (本題)。
cronie のソースを見てみます。@reboot ジョブを実行する箇所は cron.c の run_reboot_jobs 関数で定義されています。少し引用します。
ちなみに
OSS の良いところは、こういうところですね。
通常の crontab では、日付と時間を指定して
4 3 2 1 * /path/to/commandのように記述 (この例では、1月2日の3時4分に /path/to/command を実行) しますが、@reboot を使用すると
@reboot /path/to/commandのような記述を行うことができ、これにより、/path/to/command がシステムの起動時に実行されるようにスケジュールすることができます。
RHEL 5 までの vixie-cron では、@reboot は crond の起動時に必ず実行されるようになっていたため、例えば
service crond restartなどを実行したタイミングで @reboot で登録されたコマンドが再実行されてしまっていました。
RHEL 6 の cronie および最近の vixie-cron では、この問題は改善され、@reboot で指定されたコマンドは「システムで最初に crond が起動されたタイミングでのみ実行」されるようになっています。これがどのように実装されているのか気になったので、調べてみました (本題)。
cronie のソースを見てみます。@reboot ジョブを実行する箇所は cron.c の run_reboot_jobs 関数で定義されています。少し引用します。
/* lock exist - skip reboot jobs */「REBOOT_LOCK ファイルが存在していたらログを出力し、ジョブは実行しない」「REBOOT_LOCK ファイルが存在しなければ、ファイルを作成してジョブを実行する」という動作内容です。REBOOT_LOCK は pathnames.h に定義されており、
if (access(REBOOT_LOCK, F_OK) == 0) {
log_it("CRON", pid, "INFO",
"@reboot jobs will be run at computer's startup.", 0);
return;
}
/* lock doesn't exist - create lock, run reboot jobs */
if ((reboot = creat(REBOOT_LOCK, S_IRUSR & S_IWUSR)) < 0)
log_it("CRON", pid, "INFO", "Can't create lock for reboot jobs.",
errno);
else
close(reboot);
PIDDIR "cron.reboot"
つまり /var/run/cron.reboot
ということになります。PIDDIR
即ち /var/run
の中身はシステムの起動時に消去されるので、このようにファイルをフラグにしてシンプルに制御できることが分かりました。ちなみに
/var/run
内の消去処理は、RHEL 6 では /etc/rc.sysinit
で以下のように実現されています。find /var/lock /var/run ! -type d -exec rm -f {} \;動作原理が分かってスッキリ :-)
OSS の良いところは、こういうところですね。
Comments