cronとcrontabの基本とcron力を上げるテクニック

# はじめに

cronは、指定した時間や間隔で自動的にコマンドやスクリプトを実行するためのUnix系システムのデーモンです。定期的なタスクの自動化には非常に便利で、サーバーのメンテナンスや定期的なデータバックアップなどに使用されます。この記事では、cronとその設定ファイルであるcrontabの基本的な使い方について解説し、いくつかの便利なテクニックも紹介します。

## cronとは？

cronはUnix系OSの標準機能として提供されているタスクスケジューラーです。指定した日時に定期的にコマンドを実行することができます。cronを利用するためには、`crontab`という設定ファイルを編集して、どのタイミングでどのコマンドを実行するかを指定します。

## crontabとは？

`crontab`は、cronで実行するタスク（ジョブ）を設定するためのファイルです。このファイルには、実行するコマンドとその実行タイミングを記述します。各ユーザーが自身のcrontabファイルを持つことができ、ユーザーごとに異なるタスクを設定することが可能です。

### crontabの基本書式

`crontab`の各行には、以下の形式で実行するコマンドとそのスケジュールを指定します。

```
分 時 日 月 曜日 コマンド
```

各フィールドの意味は次のとおりです：

- **分**: コマンドを実行する分（0 - 59）
- **時**: コマンドを実行する時間（0 - 23）
- **日**: コマンドを実行する日（1 - 31）
- **月**: コマンドを実行する月（1 - 12）
- **曜日**: コマンドを実行する曜日（0 - 7、日曜日は0または7）

例えば、毎日午後1時にスクリプト`/home/user/script.sh`を実行したい場合、crontabに以下のように記述します。

```
0 13 * * * /home/user/script.sh
```

### 特殊な文字の使い方

crontabでは、以下の特殊な文字を使用して柔軟なスケジュール設定が可能です。

- `*` : すべての値を指定する（例：毎分、毎時など）
- `,` : リストを指定する（例：`1,2,3`は1分、2分、3分に実行）
- `-` : 範囲を指定する（例：`1-5`は1から5まで）
- `/` : 間隔を指定する（例：`*/5`は5分毎に実行）

例：月曜から金曜の毎朝9時に`/home/user/backup.sh`を実行する場合は、次のように設定します。

```
0 9 * * 1-5 /home/user/backup.sh
```

## crontabの管理コマンド

以下のコマンドを使用して、crontabの内容を編集・確認・削除できます。

- **crontab -e** : 現在のユーザーのcrontabを編集します。
- **crontab -l** : 現在のユーザーのcrontabの内容を表示します。
- **crontab -r** : 現在のユーザーのcrontabを削除します。


## cronテクニック
### crontab -e で直接編集しない

有名な話ですが、`crontab -r`とやってしまうと全てが一瞬で消え去ります。`crontab -e`と`crontab -r`は隣同士にあるため、編集と削除のコマンドを間違えて実行してしまうことがあります。これを防ぐために、`crontab -e`を使用して直接編集するのではなく、ローカルファイルに設定を書いてからそれを反映させる方法をお勧めします。

以下の手順で設定を行いましょう：

```bash
$ crontab -l > ~/crontab  # 現在の設定をバックアップ
$ vi ~/crontab            # ローカルファイルを編集
$ crontab < ~/crontab     # ローカルファイルを反映する
```

この方法を使用すると、間違えてcrontabを削除してしまうリスクを減らすことができます。

### crontab設定をバージョン管理する

crontab設定をGitなどのバージョン管理システムで管理することを強くお勧めします。これにより、誰がいつどのように設定を変更したのかを追跡することができ、トラブル発生時に直近の変更内容を簡単に確認できます。

### MAILTOを必ず設定する

cronジョブの出力を受け取るメールアドレスを設定しないと、サーバー内のユーザーのローカルのメールボックスにメールが届いてしまいます。これでは管理が不便ですので、アラート受信用の専用のメールアカウント（例：会社や部署のメーリングリスト）を用意し、`crontab`の冒頭で`MAILTO`を設定しておきましょう。

```bash
MAILTO="メールアドレス"
```

### 標準出力は捨てない (> /dev/null してはダメ)

cronジョブのログは非常に重要です。`command > /dev/null`などで標準出力を捨ててしまうと、トラブルシューティングの際に情報が得られなくなります。ログは必ずファイルに出力するようにし、以下のように専用のログファイルに追記しましょう。

```bash
command >> /path/to/logfile
```

ログファイルが肥大化しないように、別途ログローテーションの仕組みを作っておくことも大切です。

### エラーメッセージは標準エラー出力に吐く

スクリプト内でエラーが発生した際のエラーメッセージは、標準エラー出力に出力するようにしましょう。標準出力にエラーメッセージを出力してしまうと、エラーと正常なメッセージの区別がつきません。良い例として、以下のようにします。

```bash
echo "error message" 1>&2
```

または

```bash
echo "error message" > /dev/stderr
```

### コマンド重複をまとめる

同じスクリプトを複数回実行する場合、例えば朝と夕に1日2回実行する場合など、2行に分けて記述するのではなく、1行にまとめて記述しましょう。

悪い例：

```bash
0  11 * * * /bin/bash /home/user/bin/script.sh 
0  17 * * * /bin/bash /home/user/bin/script.sh
```

良い例：

```bash
0  11,17 * * * /bin/bash /home/user/bin/script.sh
```

## パス名の重複をまとめる

スクリプトの実行パスやログの保存先など、繰り返し使用するパス名は環境変数を使ってまとめると、スクリプトがすっきりし、メンテナンスが楽になります。

悪い例：

```bash
0   9 * * * /bin/bash /home/user/bin/script1.sh >> /home/user/logs/script1.log
0  10 * * * /bin/bash /home/user/bin/script2.sh >> /home/user/logs/script2.log
```

良い例：

```bash
BIN_DIR="/home/user/bin"
LOG_DIR="/home/user/logs"

0   9 * * * /bin/bash $BIN_DIR/script1.sh >> $LOG_DIR/script1.log
0  10 * * * /bin/bash $BIN_DIR/script2.sh >> $LOG_DIR/script2.log
```

### 実行時間を0分きっかりにしない

多くのcronジョブが同じ0分に実行されると、サーバーに過負荷がかかる可能性があります。できるだけ実行時間を微妙にずらすことで、負荷の分散を図りましょう。

悪い例：

```bash
0   * * * * /bin/bash $BIN

_DIR/script1.sh >> $LOG_DIR/script1.log
30  * * * * /bin/bash $BIN_DIR/script2.sh >> $LOG_DIR/script2.log
```

良い例：

```bash
3   * * * * /bin/bash $BIN_DIR/script1.sh >> $LOG_DIR/script1.log
33  * * * * /bin/bash $BIN_DIR/script2.sh >> $LOG_DIR/script2.log
```

### 定期的な監視とログ確認

cronの設定は一度作ったら終わりではありません。定期的にジョブの実行状況を確認し、ログをチェックしてエラーがないか確認しましょう。特にcronジョブが多い場合は、専用の監視ツールを導入することも考慮に入れると良いでしょう。

---

以上がcronとcrontabの基本的な使い方といくつかのテクニックの紹介です。皆さんの環境でcronをうまく活用して、日々の運用をより効率的にしてください。