Posted at

crontabを使うときに、個人的に気を付けていることをまとめてみた


この記事について

Unix系OSでジョブの定時実行を行わせたいときに日々お世話になっているcrontab。

利用する際、個人的に気を付けていることを備忘も兼ねて、また案件への新規参画者が来た際に見せられるように

簡単にまとめてみることにした。

crontabとはそもそも何か?については以下のページを参照。


常時気を付けるべきと思う事項


"crontab -e"の使用は厳禁

頻繁に言われていることだとは思いますが改めて。

案件に参画されたばかりの方がcrontab -eを特に危機感を持たずに実行するのをよく見かけるので・・・。

crontab -e で、環境変数で指定されているエディタでcrontabファイルの編集ができるが

このときキーボードで"e"の隣にある"r"をタイプしてcrontab -rとしてしまうと

crontabに登録されている内容が警告なく全て消去されてしまう。

万が一これを本番環境でやってしまおうものなら・・・考えただけでも恐ろしい。

当然バックアップ等がなければ復元できない。リスク回避のためにも厳禁とすべきでしょう。

上記のミスタイプへの対策として、/var/spool/cron/[ユーザ名]を直接エディタで修正してジョブを登録するという話も聞いたことが有るが、これも推奨されないと思う。

crontab -eで編集した際に行われる構文チェックが行われないため。

個人的には以下の方法を推奨したい。

この方法なら構文チェックもきっちり行われる。

# 現在のcrontabの設定内容をファイルに出力

crontab -l > crontab.txt

# crontabの設定内容が出力されたファイルをエディタで編集
vi crontab.txt

# 編集したファイルの内容でcrontabの設定を上書き。もし構文にミスがあればエラーとなるので安心
crontab crontab.txt

設定を出力したファイル(上の例ならcrontab.txt)をバージョン管理等できれば万全だと思います。


0分ジャストで動くジョブの登録を控える

これもよく言われる事項。

0分ジャストで実行されるジョブの登録は控え、少し時間をずらして(○時05分とか、○時10分とか)実行させるようにすべき。

理由は0分ジャストで実行されるバッチ等はその環境に複数あることが想定され、複数同時に実行されるとサーバに負荷がかかるため。

# 少しずつ時間をずらして登録すべき

05 * * * * /home/hogeuser/foo.sh
10 * * * * /home/hogeuser/bar.sh
15 * * * * /home/hogeuser/baz.sh

ただし、その環境で作業する人が複数いたとして、全員が「○時05分」にジョブを登録していたりすると

結局複数のジョブが同時に実行されてしまい本末転倒。

作業者が複数人いる場合はバッティングしないように調整しておくべき。


"> /dev/null 2>&1"で実行結果を捨てるのは(基本的には)NG

実行結果がメールで通知されることへの煩わしさから、ジョブの実行結果を> /dev/null 2>&1で捨てることがあるが、

これではジョブの実行結果が意図したものではなかった場合に調査ができなくなってしまうので、基本的にはやめた方がいいと思う。

メールによる通知が不要なら、以下のようにファイルに実行結果を出力するなどすればよい。(放っておくとディスクフルになるので、ローテートの仕組みは別途必要)

# 推奨されない例

05 * * * * /home/hogeuser/foo.sh > /dev/null 2>&1

# 下記のように、ファイルに実行結果を出力するなどすべきと思う
10 * * * * /home/hogeuser/bar.sh >> /home/hogeuser/logfile.log

なお、> /dev/null 2>&1で結果を捨てるのが推奨されないのはジョブが失敗した場合の調査ができなくなるのを避けるためなので

別途、ジョブの実行結果がログとして出力されるような仕組みがあるのなら、> /dev/null 2>&1で捨ててしまってもよいと個人的には考えている。

もしも他に> /dev/null 2>&1を避けるべき理由があれば、コメント欄で教えていただけると非常にありがたいです。


crontabでスクリプトを実行する際に注意すべきと思う事項

crontabの用途として多いのがスクリプトの定期実行だと思うので・・・。


実行時の環境変数は、手動で実行する場合と一致させておく

つい先日、これでハマってしまったばかりです・・・。

crontabによるジョブ実行時の環境変数は、crontabの設定ファイル /etc/crontabに記載されたものである。

これが手動での実行時と一致していないと、意図しない結果となることがある。

crontabでenvコマンドを実行させて、その結果を確認してみると、環境変数が違っていることが確認できる。


/etc/crontab

SHELL=/bin/bash

PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
HOME=/

/etc/crontabの設定を変更すればよいのだが、

複数人で使用している環境で、既に他の人がcrontabのジョブを登録している場合

うかつに変更すると、影響が出てしまうことが考えられる。

その場合は、実行するスクリプトの1行目のシェバングに-lオプションをつけてあげればよい。

こうすると、そのスクリプトを実施する際の環境変数が手動の場合と同じになる。


example.sh

#!/bin/bash -l



おわりに

私が普段気を付けていることを書き出してみただけの記事ですが、間違っているところもあるかもしれません。

お気づきの点、「書いてないけどコレも気を付けた方がいいよ」ってのがあれば教えていただきたいです。

都度、追記していきたいと思います。


参考記事

Cronの使い方とテクニックと詰まったところ:https://qiita.com/UNILORN/items/a1a3f62409cdb4256219

crontabのガイドライン:https://qiita.com/onomame/items/71646c5517a39bcd01cc