最近は主要なレンタルサーバー会社でもレンタルサーバー上で cron を実行できるところが増えてきました。
これはさくらのレンタルサーバーの機能紹介のページですが「CRON(スクリプト実行ツール)」が機能に含まれていることが分かります。
これはエックスサーバーですが、当たり前のように「Cron」の機能が付いています。
【cron】cron で設定したスクリプトが動かない場合の確認手順
cronとは何か?
cron は、クーロンと読みます。
クローンだと複製の意味だと思われて話がややこしくなります。
crond(cron)は、スケジュール通りにコマンドやスクリプトを実行するデーモンです。
スケジュールを設定することで定期的にコマンドやスクリプトを実行できます。
デーモンは、英語では deamon と綴るので、悪魔の方の demon とは違います。
- demon → デーモン、悪魔、鬼(ギリシャ神話では神と人間の中間)
- devil → ちなみにデビルは悪い悪魔でキリスト教で神の敵対者
- satan → ちなみにサタンは、デビルの王で一番悪い、キリスト教で神の敵対者の王
- deamon → デーモン、ダイモン、ディーモン、守護神、ギリシャ神話で神々と人間の中間にいる神様
完全に余談ですが、ここまで書いて思ったのがソクラテスが「ダイモーン」がどうのこうの語っている場面があったなと思って調べてみたら、プラトンが記述した「ダイモーン」とcronなどのデーモンは同じ綴り(deamon)でした。
整理ですが、
- cron → プログラム名、プロセス名
- crond → デーモンプロセスとして実際に動いているプロセス
たとえば、サーバー上でコマンドを実行すると、
# ps -ef | grep cron root 538 1 0 4月26 ? 00:00:05 /usr/sbin/crond -n ← crond として動いている root 22124 21890 0 08:41 pts/0 00:00:00 grep –color=auto cron |
「cron」ではなく「crond」として動いています。
manコマンドで確認します。
※定期的にmanを読むと新しい発見があるので少しずつ読みましょう。
crondで調べました。
# man crond | col -b NAME スケジュールされたコマンドを実行するデーモン SYNOPSIS DESCRIPTION 古典的なsysvinitスクリプトが使用されている場合、Cronは/etc/rc.d/init.dまたは/etc/init.dから起動されます。
In case systemd is enabled, then unit file is installed into /lib/systemd/system/crond.service and daemon is started by systemctl start crond.service command. systemd が有効な場合、ユニットファイルは/lib/systemd/system/crond.serviceにインストールされ、デーモンは systemctl start crond.service コマンドによって起動されます。
It returns immediately, thus, there is no need to need to start it with the ‘&’ parameter. Cron searches /var/spool/cron for crontab files which are named after accounts in /etc/passwd; The found crontabs are loaded into the memory. Cron は、/etc/passwd のアカウントに基づいて名前が付けられた crontab ファイル(例えば root、test など)を /var/spool/cron ディレクトリで検索します。 見つかった crontab はメモリにロードされます。 Cron also searches for /etc/anacrontab and any files in the /etc/cron.d directory, which have a different format (see crontab(5)). Cron は、/etc/anacrontab と、/etc/cron.d ディレクトリにある、異なる形式のファイルも検索します(crontab(5)を参照)。
Cron examines all stored crontabs and checks each job to see if it needs to be run in the current minute. Cron は格納されているすべての crontab を調べ、各ジョブをチェックして現在時刻で実行する必要があるかどうかを確認します。
When executing commands, any output is mailed to the owner of the crontab (or to the user specified in the MAILTO environment variable in the crontab, if such exists). コマンドを実行すると、crontab の所有者(または crontab 内の MAILTO 環境変数で指定されたユーザがあれば)に出力されます。
Any job output can also be sent to syslog by using the -s option. すべてのジョブ出力は、-sオプションを使用して syslog に送ることもできます。
There are two ways how changes in crontables are checked. crontablesの変更がどのようにチェックされるかは、2つの方法があります。
The first method is checking the modtime of a file. 最初の方法は、ファイルの modtime(更新時間)をチェックすることです。
The second method is using the inotify support. 2番目の方法は、inotify サポートを使用しています。 ※inotify (inode notify) とは、ファイルシステムへの変更をアプリケーションに報告するLinuxカーネルサブシステムです。
Using of inotify is logged in the /var/log/cron log after the daemon is started. inotify の使用は、デーモンの起動後に /var/log/cron ログに記録されます。
The inotify support checks for changes in all crontables and accesses the hard disk only when a change is detected. inotify サポートは、すべての crontables の変更をチェックし、変更が検出された場合にのみハードディスクにアクセスします。 When using the modtime option, Cron checks its crontables’ modtimes every minute to check for any changes and reloads the crontables which have changed. modtime オプションを使用すると、Cron は crontables の modtimes を毎分チェックして変更をチェックし、変更された crontables をリロードします。
There is no need to restart Cron after some of the crontables were modified. crontables のいくつかが変更された後に Cron を再起動する必要はありません。
The modtime option is also used when inotify can not be initialized.
Cron checks these files and directories: Cronはこれらのファイルとディレクトリをチェックします: /etc/crontab システム crontab
Nowadays the file is empty by default. 現在、ファイルはデフォルトで空です。
Originally it was usually used to run daily, weekly, monthly jobs. 当初は通常、毎日、毎週、毎月のジョブの実行に使用されていました。
By default these jobs are now run through anacron which reads /etc/anacrontab configuration file. デフォルトでは、これらのジョブは、/ etc / anacrontab構成ファイルを読み取るanacronを介して実行されるようになりました。
See anacrontab(5) for more details. /etc/cron.d/
/var/spool/cron Note that the crontab(1) command updates the modtime of the spool directory whenever it changes a crontab. crontab(1)コマンドは、crontabを変更するたびにスプールディレクトリのmodtimeを更新することに注意してください。
Daylight Saving Time and other time changes 夏時間およびその他の時間変更
Local time changes of less than three hours, such as those caused by the Daylight Saving Time changes, are handled in a special way. 3時間未満の現地時間の変更(夏時間の変更によるものなど)は、特別な方法で処理されます。
This only applies to jobs that run at a specific time and jobs that run with a granularity greater than one hour. これは、特定の時間に実行されるジョブと、1時間を超える粒度で実行されるジョブにのみ適用されます。
Jobs that run more frequently are scheduled normally. より頻繁に実行されるジョブは、通常はスケジュールされます。 If time was adjusted one hour forward, those jobs that would have run in the interval that has been skipped will be run immediately. 時間を1時間進めた場合、スキップされた間隔で実行されていたはずのジョブがすぐに実行されます。
Conversely, if time was adjusted backward, running the same job twice is avoided. 逆に、時間が調整された場合、同じジョブを2回実行することは避けられます。 Time changes of more than 3 hours are considered to be corrections to the clock or the timezone, and the new time is used immediately. 3時間を超える時間の変更は、時計またはタイムゾーンの修正と見なされ、新しい時間がすぐに使用されます。 It is possible to use different time zones for crontables. crontableに異なるタイムゾーンを使用することが可能です。
See crontab(5) for more information.
PAM Access Control Cronは、システムにPAMがインストールされている場合、PAMによるアクセス制御をサポートします。
For more information, see pam(8).
A PAM configuration file for crond is installed in /etc/pam.d/crond. crondのPAM構成ファイルは/etc/pam.d/crondにインストールされます。
The daemon loads the PAM environment from the pam_env module. デーモンは、pam_envモジュールからPAM環境をロードします。
This can be overridden by defining specific settings in the appropriate crontab file. これは、適切なcrontabファイルで特定の設定を定義することでオーバーライドできます。
OPTIONS -i Disables inotify support. inotifyサポートを無効にします。 -m This option allows you to specify a shell command to use for sending Cron mail output instead of using sendmail(8) このオプションを使用すると、sendmail(8)を使用する代わりに、Cronメール出力の送信に使用するシェルコマンドを指定できます
This command must accept a fully formatted mail message (with headers) on standard input and send it as a mail message to the recipients specified in the mail headers. このコマンドは、標準入力で完全な形式のメールメッセージ(ヘッダー付き)を受け入れ、メールヘッダーで指定された受信者にメールメッセージとして送信する必要があります。
Specifying the string off (i.e., crond -m off) will disable the sending of mail.
-n Tells the daemon to run in the foreground. This can be useful when starting it out of init. With this option is needed to change pam setting. /etc/pam.d/crond must not enable pam_loginuid.so module. -p Allows Cron to accept any user set crontables. -P Don’t set PATH. PATH is instead inherited from the environment. -c This option enables clustering support, as described below. -s This option will direct Cron to send the job output to the system log using syslog(3). This is useful if your system does not have sendmail(8), installed or if mail is disabled. -x This option allows you to set debug flags. SIGNALS This proves to be useful in scripts which rotate and age log files. CLUSTERING SUPPORT This is done by starting Cron with the -c option, and have the /var/spool/cron/.cron.hostname file contain just one line, which represents the hostname of whichever host in the cluster should run the jobs. If this file does not exist, or the hostname in it does not match that returned by gethostname(2), then all crontab files in this directory are ignored. This has no effect on cron jobs specified in the /etc/crontab file or on files in the /etc/cron.d directory. These files are always run and considered host specific. Rather than editing /var/spool/cron/.cron.hostname directly, use the -n option of crontab(1) to specify the host. You should ensure that all hosts in a cluster, and the file server from which they mount the shared crontab directory, have closely synchronised clocks, e.g., using ntpd(8), otherwise the results will be very unpredictable. Using cluster sharing automatically disables inotify support, because inotify cannot be relied on with network-mounted shared file systems. CAVEATS This requirement can be overridden by using the -p option on the crond command line. If inotify support is in use, changes in the symlinked crontabs are not automatically noticed by the cron daemon. The cron daemon must receive a SIGHUP signal to reload the crontabs. This is a limitation of the inotify API. The syslog output will be used instead of mail, when sendmail is not installed. SEE ALSO AUTHOR cronie 2013-09-26 CRON(8) |
実は以下のように「man cron」でも表示されます。
ただし1993年12月20日の日付になっていて、且つ「/var/cron/tabs」など古い情報のままなので注意です。
$ man cron | col -b 名前 書 説明 すぐに(シェルに)戻るので、’&’ を付けて起動する必要はない。 cron は /etc/passwd にあるアカウントをファイル名に持つ crontab ファイルを /var/cron/tabs から探し、見つけた crontab ファイルをメモリに読み込む。 また cron は /etc/crontab も見る (このファイルのフォーマットは少々異なっている: crontab(5)を参照)。 cron は 1 分ごとに起きて、読み込まれた crontab ファイルを評価し、それぞれのコマンドを今起動すべきかどうかチェックする。 コマンドを実行すると、全ての出力を crontab ファイルの所有者にメールする (または MAILTO 環境変数が crontab ファイルにあれば、そこで指定されたユーザーに送る)。 さらに cron は 1 分ごとにスプールディレクトリ(または /etc/crontab ファイル)の最終修正時刻(modtime)をチェックし、もし変更されていれば、すべての crontab ファイルの最終修正時刻をチェックし、 変更された crontab ファイルを読み直す。 よって crontab ファイルを修正するたびに cron を再起動する必要はない。 crontab(1) コマンドは、crontab ファイルが変更されたかどうかにかかわらず、スプールディレクトリの最終修正時刻を更新することに注意せよ。 関 著 4th Berkeley Distribution 20 December 1993 CRON(8) |
crontabの設定方法
crond(cron) を利用して特定のスケジュールを設定してコマンドやスクリプトを実行する場合は、crontab に記述します。
crontabの書き方
基本的なcrontabの記述は「この時刻、この日付で、このコマンドを使用せよ」という順番です。
各ユーザーはそれぞれ自分の crontab(ファイル)を持っています。
権限
crondから実行されるコマンドやスクリプトの実行権限は、crontab を所有しているユーザの権限で実行されます。
→だから、operatorアカウントが作成してoperatorが所有しているスクリプトを、rootがrootのcrontabに設定して実行するとrootの権限で実行されます。
【cron】cron で設定したスクリプトが動かない場合の確認手順
コメントアウトについて
行の先頭に#(シャープ記号) があるとコメントアウトしているとみなされ、スキップされます。(無視されます)
【例】 #0 0-23/6 * * * /usr/bin/python /home/test_script/wordpress.py >> /var/log/wordpress.log 2>&1 → 行の先頭が#なのでコメントアウトされている状態です。 |
コメントアウトについてはいろんな表現があります。
- 「コメントする」 → #を付ける → 無視される
- 「コメントアウトする」 → #を付ける → 無視される
- 「コメントを外す」 → #を消す → 実行される
- 「コメントアウトを外す」 → #を消す → 実行される
ようするに#(シャープ)を付けるか外すかということです。
コメントの注意点について
もう1つ、コメント時の注意点です。
コマンドが書いてある行に注釈的にコメントを追加できません。
【例】 0 0-23/6 * * * /usr/bin/python /home/test_script/wordpress.py #このスクリプトはテストです ← コマンド行にコメントを書くとエラーになる。 |
実際にやって試してみました。
# crontab テスト * * * * * /usr/bin/date >> /home/test_script/cron_test.txt >> /home/test_script/cron_test.txt # エラーになるかどうかテスト ←わざとコマンド行に#(シャープ)を入れてみる。 |
数分後に「/home/test_script/cron_test.txt」を確認したところ、以下のように問題なく実行されています。
$ cat cron_test.txt 2017年 5月 5日 金曜日 09:50:01 JST 2017年 5月 5日 金曜日 09:51:01 JST 2017年 5月 5日 金曜日 09:52:01 JST 2017年 5月 5日 金曜日 09:53:01 JST 2017年 5月 5日 金曜日 09:54:01 JST 2017年 5月 5日 金曜日 09:55:01 JST 2017年 5月 5日 金曜日 09:56:01 JST 2017年 5月 5日 金曜日 09:57:01 JST 2017年 5月 5日 金曜日 09:58:01 JST 2017年 5月 5日 金曜日 09:59:02 JST |
/var/log/cron ログを確認してみても
# tail cron May 5 09:52:01 tk2-xxx-xxxxx CROND[23175]: (test_script) CMD (/usr/bin/date >> /home/test_script/cron_test.txt # \343\202\250\343\203\251\343\203\274\343\201\253\343\201\252\343\202\213\343\201\213\343\201\251\343\201\206\343\201\213\343\203\206\343\202\271\343\203\210) May 5 09:53:01 tk2-xxx-xxxxx CROND[23181]: (test_script) CMD (/usr/bin/date >> /home/test_script/cron_test.txt # \343\202\250\343\203\251\343\203\274\343\201\253\343\201\252\343\202\213\343\201\213\343\201\251\343\201\206\343\201\213\343\203\206\343\202\271\343\203\210) May 5 09:54:01 tk2-xxx-xxxxx CROND[23185]: (test_script) CMD (/usr/bin/date >> /home/test_script/cron_test.txt # \343\202\250\343\203\251\343\203\274\343\201\253\343\201\252\343\202\213\343\201\213\343\201\251\343\201\206\343\201\213\343\203\206\343\202\271\343\203\210) May 5 09:55:01 tk2-xxx-xxxxx CROND[23386]: (test_script) CMD (/usr/bin/date >> /home/test_script/cron_test.txt # \343\202\250\343\203\251\343\203\274\343\201\253\343\201\252\343\202\213\343\201\213\343\201\251\343\201\206\343\201\213\343\203\206\343\202\271\343\203\210) |
特に問題なく実行されていますね。
(日本語が文字化けしていますが)
ただ、「man 5 crontab」コマンドでは以下のように記述があります。
空行および行頭のスペース・タブは無視される。 行先頭の空白以外の文字が # の行はコメント行であり、無視される。 cron コマンドとしての行に注釈としてのコメントを入れることはできない。 ←この文言の正しい解釈が不明。コメントを入れることができて且つエラーにならなかった。 |
「cron コマンドとしての行に注釈としてのコメントを入れることはできない。それらはコマンドの一部とみなされてしまう。同様に、環境変数を設定している行にコメントを入れることはできない。」
この文言の正確な解釈が不明なので、私の認識と異なる可能性があります。
なので、manコマンドが正しいとするなら、コマンドを書いている行にコメントを入れるのは控えた方がいいです。
(エラーになるかどうか関係なく控える)
コマンド行には「コマンド」か「環境変数」を設定できる
つまり、crontab ファイルには以下の3種類を記述できるということです。
- コマンド or スクリプト
- 環境変数の設定
- コメント
ここで「なぜ環境変数なの?」を思った方もいるかもしれません。
「man 5 crontab」コマンドを実行すると以下の記述があります。
crontab の動作行は、環境変数の設定か cron コマンドのいずれかである。 環境変数の設定は以下の形式をとる: name = value ただし、等号 (=) 両側のスペースはなくても良い。 |
私も最初は「なぜ環境変数?」と疑問に思いました。
しかし何度も cron を利用した方なら分かると思いますが、cron の環境変数を確認するとコマンドパスが全然通っていなくて後でエラーになっているとか、そもそも実行されずに終了していた経験があると思います。
つまり、cron からコマンドやスクリプトを実行する場合は「環境変数が設定されていない」「コマンドパスが通っていない」という前提で考えた方がいいです。
そのため、卵が先か鶏が先かという議論になるかもしれませんが、crontabに環境変数の設定もすることができます。
※ちなみに環境変数の設定もコマンドであると考えるならできて当たり前です。
以下、例ですが、この場合は「PATH=”/usr/bin:$PATH”」が全体に影響します。
(すぐ1行下のdateコマンドだけでなく、2行目、3行目にも影響します)
# crontab テスト PATH=”/usr/bin:$PATH” ←環境変数の設定を入れることができる * * * * * date >> /home/test_script/cron_test.txt |
たとえば、全体に影響させずにこのコマンド行だけに環境変数設定したいなら、以下の書き方ができます。
# crontab テスト * * * * * PATH=”/usr/bin:$PATH” date >> /home/test_script/cron_test.txt ←コマンド行に環境変数の設定を入れることもできる |
スケジュールの設定
スケジュールは5つの項目を設定できます。
左から順番に「分」「時」「日」「月」「曜日」です。
以下、時間と日付フィールドです。
フィールド 指定可能な値
———- ————–
分 0-59
時 0-23
月内日 1-31
月 1-12 (もしくは名前。下記を参照)
曜日 0-7 (0 と 7 は日曜日。もしくは名前)
アスタリスク (*) も指定できます。
アスタリスクの意味は「すべて」です。
「分」のフィールドに「*」を使用すると、「00」「01」「02」「03」「04」・・・と毎分実行されます。
数値の範囲も指定できます。
範囲は二つの数をハイフンでつなげます。
例えば「時」に 8-11 を指定すると、8時,9時,10時,11時に実行されます。
リスト形式で設定することもできます。
カンマで区切ってリストを作ります。
例:1,2,5,9 0-4,8-12
間隔値を範囲とともに指定することもできます。
範囲の後に /数値 で、範囲内で指定数値ずつ実行されることになります。
例えば「時」フィールドに「0-23/2」と指定すると、コマンドは「0時~23時(つまり一日中)」2時間おきに実行されます。
どのcrontabに書けばいいのか?
複数の crontab があるので注意しましょう。
よくありがちなのが、何か裏側でスクリプトが動いているらしいが、よく分からないので放置されている状態です。
- crontabコマンドで編集する
- /etc/crontab ファイルを直接編集する
- /var/spool/cron/各アカウント ファイルを直接編集する
どのやり方でも間違いではないと思いますが、私の推奨は/etc配下のcrontabを設定するのではなく、crontabコマンドを実行して/var/spool/cronに集める方法を推奨します。
メリット
crontab コマンドを実行して /var/spool/cron に集める方法には、以下のメリットがあります。
- /var/spool/cronディレクトリを確認するだけで誰がcronを設定しているのかが分かるので管理がしやすい
- crontabコマンドを使用することになり、構文を間違えるとエラーになるので気が付きやすい
実際に間違えてみると以下のようなエラーが出力されるのですぐに気が付きます。
# crontab -e ← crontabコマンドで編集 crontab: installing new crontab “/tmp/crontab.OfH8tf”:3: bad minute ←3行目がエラーであると教えてくれる errors in crontab file, can’t install. Do you want to retry the same edit? |
デメリット
crontab コマンドは、「編集オプション」と「削除オプション」がややこしいです。
-r オプションは、現在の crontab を削除する。
-e オプションは、環境変数 VISUAL もしくは EDITOR で指定されているエディターを使って、現在の crontab を編集するのに使われる。 |
間違って「-r」オプションを付けて実行すると、crontab の設定がすべて消えるので注意します。
-r の r は「remove」だと覚えたとしても、-e の e は、「erase」の e ではないかと迷うときもあります。
そういう時は、以下の対応を考えます。
- man crontab でオプションを確認する
- 一度「crontab -l」で設定内容を出力してから「crontab -e」コマンドを実行する
- 環境変数で「crontab -r」コマンド実行すると「crontab -ir」コマンドになるようにエイリアスを設定する
ちなみに、「crontab -r」だと一瞬ですべて削除されて二度と復活しませんが、「crontab -ir」だと「本当に削除しますか?」の確認が入ります。
# crontab -ir ← -iオプションを付けると、確認してくれる crontab: really delete root’s crontab? |
エイリアスの設定方法
全員に対してエイリアスを設定したいので「/etc/profile」ファイルに設定します。
# cp -ip /etc/profile /etc/profile_20170505 # vi profile ↓一番下に追加する。 alias crontab=’crontab -i’ |
設定を入れたらsourceコマンドで設定を反映させます。
# source /etc/profile |
若干怖いですが試してみます。
# crontab -r ←削除コマンドを実行してみる |
以上で設定は完了です。
crontabコマンドの man 結果
最後に「man 5 crontab」のコマンド結果を記載します。
(たまに見返すと新しい発見があります)
$ man 5 crontab | col -b 名 説 空行および行頭のスペース・タブは無視される。 行先頭の空白以外の文字が # crontab の動作行は、 環境変数の設定か cronコマンドのいずれかである。 name = value ただし、等号 (=) 両側のスペースはなくても良い。 value 内部の (先頭ではない) いくつかの環境変数は cron(8) デーモンによって自動的に設定される。 SHELL は (さらに注意:LOGNAME 変数は、 BSD システムではまれに USER と称される… cron コマンドの形式は V7 標準そのものであるが、 多くの上位互換な拡張がある。 フィールド 指定可能な値 フィールドにはアスタリスク (*) も指定できる。 これはあらゆるフィールドで 数値の範囲も指定できる。範囲は二つの数をハイフンでつなげる。 リストもできる。リストはコンマで区切られた数値 (または範囲) のセットである。 間隔値を範囲とともに指定することもできる。 範囲の後に “/<number>” 「月」フィールドや「曜日」フィールドには名前を使用することもできる。 「第 6」フィールド (行の残りの部分) には実行されるコマンドを指定する。 注意: コマンド実行の日は 2 つのフィールドで指定できる ― CRON フ 関 拡 リストと範囲は同じフィールドに共存できる。 ATT や BSD の cron では “1-3,7-9” 範囲に「間隔値」を指定できる。すなわち “1-9/2” が “1,3,5,7,9” と同じ。 月または曜日を名前で指定できる。 環境変数を crontab の内部で設定できる。 BSD や ATT コマンドの出力は crontab の所有者にメールされる (BSD ではこれを行わない)。 また 著 4th Berkeley Distribution 24 January 1994 CRONTAB(5) |
コメント