新たにcronジョブの使い方と設定方法について学んだので、備忘録的にまとめておきます。
情報収集や、会計管理、農業から工場のオートメーションまで毎日の繰り返し行われる定期的な処理を自動化するために使用することができます。
IoT技術の普及に伴ってRaspberry Piなど小型端末にも適用することで、身近な処理を自動化することができそうで夢が広がりますね!
動作確認した環境:
- Raspberry Pi4 model B/8GB(Raspberry Pi OS)
- WSL(Ubuntu)
cronでできること
cronはLinux標準の機能であり設定したジョブの実行をスケジュールするデーモン(常駐プログラム)です。任意の時刻にジョブをスケジュールし、実行することができるジョブスケジューラと言えます。
ジョブを指定した時間に実行する方法としては、「cron」「wfi」「Python内でsleep」などの方法が思いつきます。
消費電力の観点から見ると、WFI(Wait-For-Interrupt)による割り込み待ちによる処理の停止がプロセッサをアイドル状態に保つことができるため、最も低消費電力なような気がしますが、Pythonコード内でWhileループを回して時間による条件待ちを行う処理に比べると、常にタスクがプロセッサを占有しないのでcronによるスケジュールは消費電力が小さいと思われます。
もっとも、Raspberry Piに使用されているCPU(ARMプロセッサ)ではWFIが適切に使用できない?的な記事をどこかで見たような気がしますが、、
cronの使用方法など詳細は以下コマンドで基本的な設定方法などの解説を見ることができます。
Manualファイルを開くコマンド:
man 5 crontab
cron起動、停止、再起動
ステータスの確認
現在クーロンが、running状態にあるかどうかを確認するためのコマンドです。確認コマンド:
sudo /etc/init.d/cron status
cronのスタート方法
開始コマンド:sudo systemctl start cron
開始コマンド:
sudo /etc/init.d/cron start
cronのストップ方法
停止コマンド:sudo systemctl stop cron
停止コマンド:
sudo /etc/init.d/cron stop
cronのリブート
再起動コマンド:sudo systemctl restart cron
再起動コマンド:
sudo /etc/init.d/cron restart
cron環境設定方法
タイムゾーンの設定
コマンド:timedatectl set-timezone Asia/Tokyo
思った通りの時間に実行されない場合は、大体この設定が間違っていることが多いです。
設定したところで、以下のコマンドでcronの再起動を行います。
コマンド:
sudo systemctl restart cron
cron設定ファイルの種類
ファイル/ディレクトリ名 | ユーザー権限 | 説明 |
---|---|---|
/var/spool/cron/ | 全ユーザー | ユーザージョブ「crontab -u {user名} -e」 |
/etc/crontab | root | システムジョブ「vi /etc/crontab」 |
/etc/cron.hourly | root | 毎月、毎週、毎日、毎時、毎分実行タスクの設定ファイル |
/etc/cron.daily | root | 毎日実行タスクの設定ディレクトリ |
/etc/cron.monthly | root | 毎月実行タスクの設定ディレクトリ |
/etc/cron.weekly | root | 毎週実行タスクの設定ディレクトリ |
/etc/cron.d | root | その他タスクの設定ディレクトリ |
特に意識しておく必要もないのですが、上記のようにcronの設定ファイル・ディレクトリが構成されています。一般的に編集を行うのは「/var/spool/cron」以下に作成されるユーザー名のファイルになります。
crontab編集方法
以下で大まかにcrontabの書き方のフォーマットを知ることができます。
コマンド:
cat /etc/crontab
# 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 executed
17 * * * * root cd / && run-parts --report /etc/cron.hourly
25 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 )
#
クーロンジョブの編集
cronジョブ編集開始コマンド:crontab -e
crontab -u {user名} -e
初回起動時の使用エディタ選択:
no crontab for user_name - using an empty one
Select an editor. To change later, run 'select-editor'.
1. /bin/nano <---- easiest
2. /usr/bin/vim.basic
3. /usr/bin/vim.tiny
4. /bin/ed
Choose 1-4 [1]:
編集/設定例:
# 毎日5時にlogにHELLO WORLDを出力
00 05 * * * echo "HELLO WORLD" > ~/hello.log 2>&1
以下設定項目とスケジュール単位の設定方法
スケジュール単位 | 設定方法 |
---|---|
minute (0 - 59) | 0~59分を指定 |
hour (0 - 23) | 0~23時を指定 |
day of month (1 - 31) | 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 | 0:日,1:月,2:火,3:水,4:木,5:金,6:土, |
スケジュール単位毎の複数設定例 | 説明 |
---|---|
0,10,20 | フィールドに対して複数の値を設定可能。左例では分に設定に指定することで、0分、10分、20分に処理を実行 |
2-7 | 連続した時間を設定可能。左例では時間に設定することで2時~7時に処理を実行 |
3,6,7-9 | 上記2つの設定を左例のように両立も可能 |
1-9/3 | 時間の間隔を指定する。左例では時間に設定することで1-9時の間3時間おきに処理を実行 |
* | 設定フィールドに応じた間隔で毎回処理を実行 |
cronジョブの設定を確認
クーロンジョブを設定して保存したら、設定がなされていることを確認します。ファイル内容表示コマンド:
crontab -l
crontab削除コマンド:
crontab -r
cronによるPythonの実行
一般的なコマンドを実行できることが上記の例からも分かったと思うので、同じようにPythonのコードを定期実行するようにcrontabファイルに記載していきます。
設定例:
# PATHの設定
PATH=/home/username/...
# このように#でコメントを記載可能
30 9 * * * cd ~/src/ && . ~/src/venv/bin/activate && ~/src/venv/bin/python3 ~/src/main.py > ~/src/main.log 2>&1
# 毎週日曜午前4時にリブート
00 04 * * 0 /sbin/reboot
2行目:
cronでは環境変数のパスが通っていません。crontabファイルにPATHをできる限り記載しておくのが無難です。「echo $PATH」で設定されている環境変数PATHを確認して上記のように設定しておきましょう。
4行目:
行先頭に「#」を書くことでその行はコメント行とみなされます。
5行目:
記載しているコマンドの実行スケジュールを記載しています。複数のコマンドを連続して実行する場合コマンド間に「&&」とすることで複数のコマンドを記述できます。
ここでは、main.pyというコードをPythonの仮想環境(venv)を用いた環境で実行しています。(末尾のmain.logなどについての説明は以降にあります)
crontabファイル内のコマンドは絶対パスで記載するのが基本です。長くなる場合は変数を使ってパスをまとめると記述がシンプルになります。
仮想環境を用いたPython実行の注意点
Pythonコマンドのパスを調べるには「which python」や「which python3」コマンドを用いて、Pythonのパスを調べます。venvなどの仮想環境を用いてPythonのコードを実行する場合、venvをactiveにした状態で上記コマンドによりPythonのパスを取得しないと、仮想環境で使用されるPythonを使用することができませんので注意が必要です。
コマンド実行の順序:
# venvをアクティブにする
source {PATH}/venv/bin/activate
# pythonのパスを確認する
which python3
最後にcronrabファイルを記述する際に気を付けるポイントをまとめておきます。
POINT!
- PATHを記載しておくのが無難
- 絶対パスで記述しておくのが無難
- 「&&」で複数のコマンドを時系列で接続
- venvなど仮想環境を使用する時はPythonパスに気を付ける
- logの出力設定をしておくと実行確認に便利(以降に詳細記述)
cronジョブ実行の確認方法
cronは基本的に裏で実行されるので、通常ターミナルで実行した場合のように実行されてもコマンドラインになにも表示されません。
上手く動作しない場合などエラーの内容や、print()などで記載したコメントなどを表示するにはファイルにログを出力しておく必要があります。
先ほどから出てきてはいますが、「> ~/main.log 2>&1」のようにlogファイルに標準出力やエラー内容を記録するようにします。
crontabの記述例:
# 「>」でlogの上書き
0 15 * * * ~/src/venv/bin/python3 ~/src/main.py > ~/src/main.log 2>&1
# 「>>」でlogの追記
0 15 * * * ~/src/venv/bin/python3 ~/src/main.py >> ~/main.log 2>&1
このように「>」でlogの上書き、「>>」でlogを追記していくことができます。
以上
参考: