Article ID No. 13604950680 (Delete) | New Date & Time 2011 2012 2013 2014 2015 /1 2 3 4 5 6 7 8 9 10 11 12 /1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 :0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 :0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 Category Title Content cron の実装である vixie-cron (およびそのフォーク版である cronie) では、@reboot という時刻指定の記法がサポートされています。 通常の crontab では、日付と時間を指定して <pre> 4 3 2 1 * /path/to/command </pre> のように記述 (この例では、1月2日の3時4分に /path/to/command を実行) しますが、@reboot を使用すると <pre> @reboot /path/to/command </pre> のような記述を行うことができ、これにより、/path/to/command がシステムの起動時に実行されるようにスケジュールすることができます。 RHEL 5 までの vixie-cron では、@reboot は crond の起動時に必ず実行されるようになっていたため、例えば <pre> service crond restart </pre> などを実行したタイミングで @reboot で登録されたコマンドが再実行されてしまっていました。 RHEL 6 の cronie および最近の vixie-cron では、この問題は改善され、@reboot で指定されたコマンドは「システムで最初に crond が起動されたタイミングでのみ実行」されるようになっています。これがどのように実装されているのか気になったので、調べてみました (本題)。 cronie のソースを見てみます。@reboot ジョブを実行する箇所は <a href="http://git.fedorahosted.org/cgit/cronie.git/tree/src/cron.c?id=cronie1.4.4#n394">cron.c の run_reboot_jobs 関数</a>で定義されています。少し引用します。 <pre> /* 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); </pre> 「REBOOT_LOCK ファイルが存在していたらログを出力し、ジョブは実行しない」「REBOOT_LOCK ファイルが存在しなければ、ファイルを作成してジョブを実行する」という動作内容です。REBOOT_LOCK は <a href="http://git.fedorahosted.org/cgit/cronie.git/tree/src/pathnames.h?id=cronie1.4.4#n46">pathnames.h</a> に定義されており、<code>PIDDIR "cron.reboot"</code> つまり <code>/var/run/cron.reboot</code> ということになります。 <code>PIDDIR</code> 即ち <code>/var/run</code> の中身はシステムの起動時に消去されるので、このようにファイルをフラグにしてシンプルに制御できることが分かりました。 ちなみに <code>/var/run</code> 内の消去処理は、RHEL 6 では <code>/etc/rc.sysinit</code> で以下のように実現されています。 <pre> find /var/lock /var/run ! -type d -exec rm -f {} \; </pre> 動作原理が分かってスッキリ :-) OSS の良いところは、こういうところですね。 Password