cron
Linux上でプログラムの実行をスケジュールするためのプログラム。
独自の書式をもつcrontabファイルでスケジュールを設定する。
想定環境
Ubuntu 20.04
/etc/crontab
SHELL=/bin/bashPATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/binMAILTO=# Example of job definition:# .---------------- minute (0 - 59)# | .------------- hour (0 - 23)# | | .---------- day of month (1 - 31)# | | | .------- month (1 - 12) OR jan,feb,mar,apr ...# | | | | .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat# | | | | |# * * * * * user-name command to be executed17 * * * * root cd / && run-parts --report /etc/cron.hourly25 6 * * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )47 6 * * 7 root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )52 6 1 * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )
crontabの時刻形式は独特で、複雑な設定を新しく書き起こすのは面倒くさい。
デフォルトの/etc/crontab
では、/etc/cron.hourly
、/etc/cron.daily
のようなディレクトリの内部の実行ファイルを
定期実行するように設定されているので、ここに雑にシェルスクリプトを入れると簡単にcronを体験できる。
run-parts
は、指定したディレクトリ内の実行ファイルを、ファイル名でソートした順番で実行する。
以下のように、ファイル名にソートを考慮した番号付けをすることで、ジョブの実行順を制御できる(10-my-job
→20-your-job
→33-goma
の順で実行される)。
10-my-job20-your-job33-goma
cronが正しく動作しているか確認するには、journalctl
を使うとよい。
journalctl -u cron.service -f -n 20
cronにより実行されたプログラムの標準出力や、標準エラー出力を取得するのは手間がかかる。
cronは、プログラムの出力をメールで送るという動作をするが、メールを送信できるように設定しておかなければならない。
上のcrontabファイルでは、MAILTO
を空にすることでメールの送信を試みないようにしている(送信できなかったメールが/var/spool/mail
に蓄積されてストレージを圧迫するため)。
ログを確認するには、プログラム中でファイルに書き出すようにする方法をとることになる。
シェルスクリプトからSlackに通知を送るには、以下のようにするとよい(sudo apt install curl jq
)。
#!/bin/bashWORKDIR=/workWEBHOOK_URL=https://hooks.slack.com/services/***cd "$WORKDIR"ERROR=$(mycommand 2>&1 | tee /dev/stderr)if [[ $? -ne 0 ]]; thenSHORT_ERROR=${ERROR:0:1000}DATA=$(jq --arg key0 "text" --arg value0 "ERROR: $SHORT_ERROR" '. | .[$key0]=$value0' <<< '{}')curl -X POST -H 'Content-type: application/json' --data "$DATA" "$WEBHOOK_URL"fi
/etc/cron.d
crontab形式の設定を複数のファイルに分けて配置するためのディレクトリ。
例えば、/etc/crontab
を直接編集せずに、アプリケーションごとにcrontabを配置するようなことができる。
また、実体を別の場所においておいて、シンボリックリンクを/etc/cron.d
以下に配置することもできる(後述の権限設定に注意)ので、設定のgit管理にも便利(リポジトリ内のMakefileで、/etc/cron.d/
以下からシンボリックリンクを張るようにしておくなど)。
crontabファイルを一から書くのは慣れが必要なので、上の/etc/crontab
をコピーし、
もともとの設定を#
でコメントアウトしておいて、改変しながら使うのが便利だと思う。
なお、crontabファイルの所有者はroot
で、所有者以外に書き込み権限があってはならない(chmod 644 crontab
または chmod 600 crontab
)という制約があるので注意。
また、SHELL
・PATH
のような設定は、/etc/crontab
とは独立しているので、改めて記述しなければならない。
例えば、デフォルトでは、SHELL
は/bin/sh
であり、PATH
に/usr/local/bin
が含 まれていない。
PATH
をそれぞれのcrontabファイルで設定しないと、ターミナルで動かしたときと違って特定のコマンドが動かない、というような問題が起こることがある。
例えば、docker-compose
は/usr/local/bin
によくインストールされるので、docker-compose
コマンドを含むジョブがうまく動かない、ということがある。