Kenichi Maehashi's Blog

脳内コアダンプ

RSS
Category: Linux
cron の実装である vixie-cron (およびそのフォーク版である cronie) では、@reboot という時刻指定の記法がサポートされています。

通常の 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 */
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);
「REBOOT_LOCK ファイルが存在していたらログを出力し、ジョブは実行しない」「REBOOT_LOCK ファイルが存在しなければ、ファイルを作成してジョブを実行する」という動作内容です。REBOOT_LOCK は pathnames.h に定義されており、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

Leave Yours...
Name:
E-mail / URL (optional):
Comment:
Are You Robot?: