crontabの設定方法をすぐに忘れるのでメモ代わりにまとめています。
※最初にまとめてからかなり時間が経過したので、内容の精査とその間に勉強した項目を追加しました。
crontabを設定する方法
crontabを設定・編集する方法には、大きく分けて次の2通りの方法があります。
- crontab -e 対話型エディタで編集
- crontab ファイル名 ファイルを読み込ませる
それぞれの特徴と具体的な手順について説明していきます。
「crontab -e」コマンドで設定
「crontab -e」コマンドを実行すると、cronのスケジュールを設定する画面が表示されます。
超重要注意点!!
キーボードの配列上、「e」のすぐ横には「r」があります。
誤って指定して「crontab -r」を実行してしまうと、現在設定されているcronの内容がすべて削除されてしまうので、実行する際には十分に注意してください。
$ crontab -e
コマンドを実行すると設定編集画面が表示されるので、下記のような書式で設定を行います。
00 * * * * /home/tamohiko/script/disk-space.sh
ちなみに、上記の設定は「毎時00分にdisk-space.shというスクリプトを実行する」という意味になります。
設定に使用されるエディターについて
「crontab -e」で開くエディターは、システム全体のデフォルト設定か、環境変数の「EDITOR」に設定されているものが使用されます。
現在の設定は、下記の方法で確認することができます。
echo $EDITOR
何も表示されない場合は環境変数が設定がされていないため、システム標準に設定されているエディターが使用されます。
「crontab ファイル名」ファイルを読み込んで設定
あらかじめcronの設定を記述したテキストファイルを作成しておき、それを「crontab」コマンドに読み込ませることで設定を反映させる方法です。
この方法を使うと、コマンド入力時に 「-r」と誤入力して設定が全削除されるといった事故を完全に防げるため、安全に設定変更を行うことができます。
crontab ファイル名
実際に運用する場合は、以下のような手順で行うと、設定の変更履歴が残るだけでなく、問題があった場合の切り戻し(ロールバック)もすぐに行えるのでおすすめです。
- crontab -l > ファイル (現在の設定をファイルへ書き出す)
- ファイルをバックアップ
- ファイルを編集
- crontab ファイル (設定ファイルを読み込ませる)
安全な設定変更の手順例
今回は例として、作業用ファイルを「crontab-data」という名前にしていますが、ファイル名はお好きな名前でかまいません。
※「#」からはじまる行は説明文なので、実際に入力する必要はありません。
# 1. 現在の現在の設定をファイルへ書き出す $ crontab -l > crontab-data # 2. 編集前のファイルをバックアップ(日付プレフィックス付き) $ cp -p crontab-data crontab-data_`date "+%Y%m%d-%H%M%S"` # 3. ファイルをテキストエディタで編集する $ vi crontab-data # 4. 編集後の設定ファイルを読み込ませて反映する $ crontab crontab-data
設定ファイルの保存場所
crontabで設定した内容は、システム上の以下のディレクトリにユーザーごとのファイルとして保存されます。
- /var/spool/cron/ユーザー名 (RHEL系)
- /var/spool/cron/crontabs/ユーザー名 (Ubuntu / Debian系)
これらのディレクトリやファイルはセキュリティ(パーミッション)の関係上、一般ユーザーは直接中身を確認することができず、rootユーザー(またはsudo)でのみ確認可能です。
# ls -l /var/spool/cron/ 合計 8 -rw------- 1 root root 22 4月 2 11:39 root -rw------- 1 root tamo 20 4月 2 12:53 tamohiko
オプションの説明
「crontab」コマンドで普段よく使用する、主なオプションの一覧です。
| オプション | 説明 |
|---|---|
| -u ユーザ名 | 操作対象のユーザーを指定する(rootユーザのみ使用可) |
| -l | 現在設定されているcronの内容を標準出力に表示する |
| -e | 設定の編集画面を開く |
| -r | 現在の設定内容をすべて削除する |
| -i | 削除(-r)を実行する前に、確認のメッセージを表示する。 「y」か「Y」キーを押下することで設定が削除される |
-u:ユーザの指定
どのユーザのcrontabを設定・参照するのかを指定します。(rootユーザーのみ使用可能です)
下記の例では、tamohikoユーザを指定して、crontabの内容を表示しています。
# crontab -u tamohiko -l 1 * * * * echo "cron test"
「-u」オプションを省略した場合は、現在コマンドを実行しているユーザー(カレントユーザー)の設定が対象になります。
-l:設定内容の表示
現在登録されているcrontabの設定内容を標準出力(ターミナル)に表示します。
$ crontab -l
1 * * * * echo test ### 設定内容が出力される
-e:設定の編集
対話型エディタを開いてcronのスケジュールを編集・追加します。
-r:設定の削除
登録されている設定をすべて削除します。
通常、このオプション単体だと確認プロンプトが出ず、一瞬で設定が消去されてしまうので注意が必要です。
-i:削除時の確認(-rと組み合わせて使用)
「-r」オプションと同時に使用することで、削除を実行する前に確認のメッセージを出してくれます。
$ crontab -ri crontab: really delete tamohiko's crontab?
本当に削除したい場合は y(または Y)を入力してエンターを押します。
それ以外を入力すれば削除はキャンセルされます。
スケジュール(実行時間)の設定書式
crontabのスケジュールは、スペースまたはタブで区切られた5つのフィールドと、その後に続く実行コマンドで構成されています。
フィールドは左から順に「分」「時」「日」「月」「曜日」を指定します。
* * * * * [実行コマンド] │ │ │ │ │ │ │ │ │ └─ 曜日 (0 - 7) (0と7は日曜日) │ │ │ └─── 月 (1 - 12) │ │ └───── 日 (1 - 31) │ └─────── 時 (0 - 23) └───────── 分 (0 - 59)
システム標準のcron設定との違い
「/etc/crontab」や「/etc/cron.d/」配下に配置するシステム用の設定ファイルでは、曜日の後ろに 「実行ユーザー(rootなど)」 を指定する項目が1つ増えます。
詳しい書き方の違いは、こちらのページでまとめていますので、時間があれば目を通してみてください。
各フィールドで指定できる値と意味
「分」「時」「日」「月」「曜日」のフィールドに指定できる数値は下記のとおりとなっていて、それを「リスト(list)」「範囲(range)」「間隔(step)」といった設定方法と組み合わせてスケジュールを設定します。
| フィールド | 設定可能な値 |
|---|---|
| 分 | 0-59 |
| 時 | 0-23 |
| 日 | 1-31 |
| 月 | 1-12 |
| 曜日 | 0-7 (0または7は日曜日) 0=日、1=月、2=火、3=水、4=木、5=金、6=土、7=日 |
ワイルドカード「*」の意味
数値を指定する代わりに 「*」(アスタリスク)を記述すると、そのフィールドの「すべての値」を選択したことになります。
例えば、下記のようにすべてのフィールドを「*」にすると、「毎分」 コマンドが実行されます。
* * * * * [実行コマンド]
柔軟なスケジュール指定方法
スケジュールは、数値や「*」以外にも、以下の記号を組み合わせることで、複雑なスケジュールを簡単に指定することができます。
| 指定方法 | 設定例 | 説明 |
|---|---|---|
| リスト指定(,) | 0,10,20,30 | 「,」(カンマ)で区切ることで複数指定が可能。 左の例を分フィールドに指定した場合、0分、10分、20分、30分に実行します |
| 範囲指定(-) | 1-5 | 「-」(ハイフン)で範囲指定が可能。 左の例を月フィールドに指定した場合、1から5月まで毎月処理を実行します。 |
| 間隔指定(/) | */10 | スラッシュの後に数値(*/数値)を指定して「~間隔」の設定が可能。 左の例を分フィールドで指定した場合、10分間隔で処理を実行します。 |
これらは組み合わせて指定することも可能で、例えば時フィールドで「1,6,9-11」と指定した場合、1時、6時、9時、10時、11時に実行されます。
スケジュール設定例
具体的な設定パターンをいくつか紹介します。
分単位の設定例
毎時15分に実行
15 * * * * 実行コマンド
時間単位の設定例
毎日午前4:02に実行
02 4 * * * 実行コマンド
日にち単位の設定
毎月10日の午前6:15 に実行
15 6 10 * * 実行コマンド
月単位の設定
7月1日午前3:00に実行
00 3 1 7 * 実行コマンド
曜日単位の設定
毎週月曜日の午前10:00に実行
00 10 * * 1 実行コマンド
リスト設定「,」
毎日午前4:30と午前9:30に実行
30 4,9 * * * 実行コマンド
毎週月、金曜日の午前3:00に実行
00 3 * * 1,5 実行コマンド
範囲設定「-」
毎日午前3:00から午前9:00までの1時間ごとに実行
00 3-9 * * * 実行コマンド
毎月10日の午前「3:15」「4:15」「5:15」「6:15」の1時間ごとに実行
15 3-6 10 * * 実行コマンド
間隔設定「/」
10分ごとに実行
*/10 * * * *
3時間ごとに実行
00 0-23/3 * * * 実行コマンド
複合(リストや範囲の組み合わせ)
リストや範囲をあわせた記述も可能です。
午前「1:00」「6:00」および、「9:00」から「11:00」まで1時間ごとに実行
00 1,6,9-11 * * * 実行コマンド
crontabのTips&逆引きテクニック
実務で覚えておくと非常に便利なTips集です。
cronで月末を指定
cronの標準機能には「月末」という直接的な指定方法がありません。
そのため、毎月28~31日の間に「test」コマンドで月末かどうかを判定しています。
- $( date --date '+1 day' +\%d ) 1日後は何日かを求めて変数へ格納
- 「test」コマンドで1日後が1日であれば(-eq 1)月末あると判定
55 23 28-31 * * /usr/bin/test $( date --date '+1 day' +\%d ) -eq 1 && 実行コマンド
BSD系のdateコマンドの場合は--dateオプションの代わりに「-v+1d」(1日後)といったように設定する必要があります。
55 23 28-31 * * /usr/bin/test $( date -v+1d +\%d ) -eq 1 && 実行コマンド
※情報元cron(crontab)で月末で指定する方法 ぎじゅっやさんさま(リンク切れ)
「最終金曜日」のみ実行する
毎週金曜日に実行し、testコマンドで「7日後は別の月(=今日の金曜日が今月最後)」であるかを判別して、最終金曜日かどうかの判定を行います。
0 0 * * 5 /usr/bin/test $( date +\%m ) -ne $( date --date '7 day' +\%m ) && 実行コマンド'
- 0 0 * * 5 金曜日の0時0分をスケジュール
- $( date +\%m ) で「現在の月」を取得
- $( date --date '7 day' +\%m ) で「7日後の月」を取得
- -ne(Not Equal)で2つの月を比較し、値が異なっていれば「最終金曜日」と判断
金曜日以外の判定を行いたい場合は、曜日を指定するフィールドを適宜変更してください。
BSD系のdateコマンドの場合は--dateオプションの代わりに「-v+7d」(7日後)といったように設定する必要があるそうです。
0 0 * * 5 /usr/bin/test $( date '+\%m' ) -ne $( date -v+7d '+\%m' ) && 実行コマンド
情報元Blog::Rescueさま(リンク切れ)
メールを出したくない場合
cron実行後の結果をメール送信させたくない場合は、crontabの先頭に以下の設定を入力することでメールが送信されなくなります。
MAILTO=""
特定のコマンドの通知先だけを変更したい場合
特定のスケジュールだけ別のアドレスにメールを飛ばしたい、あるいはエラーだけをメールしたい場合は、パイプとmailコマンドを組み合わせます。
0 2 * * * 実行コマンド 2>&1 | mail -s "件名" 送信先メールアドレス
複数のアドレスに飛ばしたいときは、カンマ区切りで複数メールアドレスを指定することができます。
システム再起動時に実行させる(@reboot)
日時の指定ではなく、サーバーが起動(再起動)したタイミングで自動実行させたい場合は「@reboot」と指定します。
@reboot 実行コマンド
サーバ起動後に任意の時間経過後に実行させたい
この場合は「sleep」コマンドと組み合わせると幸せになれるでしょう。
以下の場合、再起動後600秒(10分)スリープ(待機)してからコマンドを実行します。
@reboot sleep 600; 実行コマンド
その他の方法としては、実行させたい処理をシェルスクリプト等で作成して、最初に「sleep」コマンドで実行を待機させる方法もあります。
秒単位で実行スケジュールを組む
「crontab」は最低単位が「分」なので、秒単位での指定はできませんが、一工夫すると秒単位で実行させることが出来ます。
毎分「決まった秒数」に実行したい場合
「sleep」コマンドで待機させて時間をずらすことで、毎分決まった秒数にコマンド実行させることが出来ます。
例えば毎分10秒にコマンドを実行させたい場合は下記のように設定します。
* * * * * sleep 10; 実行コマンド
毎分30秒にコマンドを実行したい場合はこのように設定します。
* * * * * sleep 30; 実行コマンド
1分間の間に「何度も(一定の間隔で)」実行したい場合
2通りの方法を紹介します。
複数設定する力技
力技ですが「sleep」コマンドで待機させる時間をずらして複数行に分けて記述します。
これで毎分「0」秒から10秒ごとにコマンドが実行されます。
* * * * * 実行コマンド * * * * * sleep 10; 実行コマンド * * * * * sleep 20; 実行コマンド * * * * * sleep 30; 実行コマンド * * * * * sleep 40; 実行コマンド * * * * * sleep 50; 実行コマンド
ただし、この方法では1秒ごとにコマンドを実行させたい場合60行書く必要があるので設定がとても大変です。
for文を使用
for文とseqコマンドを使用して設定することで、一行で秒指定を行うことが出来ます。
間隔の部分にsleepさせたい秒数を設定してください。
* * * * * for i in `seq 0 間隔 59`;do (sleep ${i} ; 実行コマンド) & done;
例えば10秒毎に実行させたい場合は下記の通りになります。
* * * * * for i in `seq 0 10 59`;do (sleep ${i} ; 実行コマンド) & done;
誤操作による「crontab -r(全削除)」を未然に防ぐ設定
オプションの「-e」(編集)と「-r」(削除)はキーボードでは隣あわせなので、打ち間違えやすく誤削除の事故につながりやすいです。
そこで、ユーザーの環境設定ファイル(~/.bashrc)に alias(エイリアス) を設定しておくことで、削除時に必ず確認メッセージが表示されるようすることができます。
$ vi ~/.bashrc
以下の「alias」設定を追加することで、「crontab」コマンドを実行する場合に、自動的に「i」オプションが設定されるようになります。
alias crontab='crontab -i'
設定が完了しましたら、「source」コマンドで「.bashrc」を読み込んで設定を反映させます。
$ source ~/.bashrc
動作確認
設定が完了したら、安全のために現在の設定をバックアップしてから動作テストを行います。
正常に設定が書き出されていることが確認できたら、「-r」オプションを指定して削除を行った際に削除を行って良いかの確認メッセージが表示されれば設定完了です。
※「#」から始まる行は説明文なので、入力する必要はありません。
# 1.現在の設定をファイルにバックアップ $ crontab -l > ファイル # 2.バックアップ確認 $ cat ファイル # 3.削除を実行して確認メッセージが表示されるか確認 # really delete...? と確認プロンプトが出れば成功 $ crontab -r crontab: really delete tamohiko's crontab?
設定を削除する場合は「y」キーを入力、削除したくない場合は「n」キーを入力してください。
コメント