盆暗の学習記録

データサイエンス ,エンジニアリング,ビジネスについて日々学んだことの備忘録としていく予定です。初心者であり独学なので内容には誤りが含まれる可能性が大いにあります。

cronでプログラムを定期的に自動実行させる

かなり詰まったのでメモ。

環境

cron

cronの設定方法は2つある

  • crontabコマンドを使う方法
  • /env/cron.dにcrontabファイルを置いておく方法

crontabコマンドを使う方法

概要

この方法のメリット

  • 簡単で、管理者でなくても設定できる

この方法のデメリット

  • ユーザーごとに単一のcrontabファイルを使うため、もし誤ってcrontab -rで削除してしまうと全部消える(人によってはこちらは非推奨とするらしい)

コマンド

# crontabを閲覧
crontab -l
# crontabを編集
crontab -e

設定方法

# m h  dom mon dow   command
分 時 日 月 曜日  コマンド

例えば次のような感じに書く。

# 全部* → 1分ごと
* *    * * *  [command]

# 毎時0分に実行
0 *    * * *  [command]

# 毎日0:00に実行
0 0    * * *  [command]

また、5つの*の部分の代わりに@monthlyなどの書き方をしても良い (Ubuntu Manpage: crontab - cron を駆動するための一覧表

cronの起動

sudo service cron start

/etc/cron.dに置く方法

概要

この方法のメリット

  • タスクのジャンルごとにcrontabファイルを分けられるので、本格的な使用に向く
  • あやまって削除してしまうなんてことは起こりにくい

この方法のデメリット

  • 管理者権限で操作する必要がある

crontabファイルの準備

/etc/crontabのフォーマットを使うのが楽なので、/etc/cron.dというディレクトリにコピーして編集する。

# test_cronという名前でコピーする場合
cp /etc/crontab /etc/cron.d/test_cron

この際、ファイル名に拡張子をつけない(.が含まれるファイルは実行されないらしい)

設定方法

crontabコマンドを使う場合と少し異なり、userのフィールドがある。

# m h dom mon dow user  command
分 時 日 月 曜日 ユーザー コマンド

例えば次のように書く。

# m h dom mon dow user  command
* *     * * *   user   echo "test" >> ~/test.log

私が詰まったポイント

私の場合、userをrootにしていたときはcronが動作しなかった。

自分がログイン中のユーザー名にしたところ、ちゃんと動作するようになった。

cronの起動

sudo service cron start

cronの再読み込み

cronデーモンは/etc/cron.d内のファイルや/etc/crontabの変更を監視しており、変更はすぐ再読み込みしてくれるはずだが、手動でやる場合は以下のようなコマンドが使える。

# cronの再起動
sudo service cron restart
# cronの状態を確認する
sudo service cron status

crontabの設定を楽にするサイト

f:id:nigimitama:20191110182341p:plain

f:id:nigimitama:20191110195920p:plain

参考になるサイト

cron力をつけよう!全てのcrontab入門者に贈る9個のテクニック · DQNEO起業日記

↑実践的な話でとてもよかった

追記:cronに環境変数を渡す

cronは通常のbashとは異なる環境変数の下で動いている。そのため、Dockerのコンテナに与えた環境変数などがcronのジョブ内で使えない問題が発生する。

そこで、cronを設定する時に

declare -p | grep '\-x' > /cron.env

みたいな感じに必要な環境変数をファイルに書き出しておいて、cronの設定ファイル内で

BASH_ENV=/cron.env
DIR=/path/to/workdir
# m h dom mon dow user command
* * * * *   root    /bin/bash "${DIR}/main.sh" > "${DIR}/cron.log" 2>&1

のようにして読み込むことで環境変数を渡すことができる。

参考

cron — CronジョブからDockerセットの環境変数にアクセスするにはどうすればよいですか