新たに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
or
開始コマンド:
sudo /etc/init.d/cron start

cronのストップ方法

停止コマンド:
sudo systemctl stop cron
or
停止コマンド:
sudo /etc/init.d/cron stop

cronのリブート

再起動コマンド:
sudo systemctl restart cron
or
再起動コマンド:
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/crontabrootシステムジョブ「vi /etc/crontab」
/etc/cron.hourlyroot毎月、毎週、毎日、毎時、毎分実行タスクの設定ファイル
/etc/cron.dailyroot毎日実行タスクの設定ディレクトリ
/etc/cron.monthlyroot毎月実行タスクの設定ディレクトリ
/etc/cron.weeklyroot毎週実行タスクの設定ディレクトリ
/etc/cron.drootその他タスクの設定ディレクトリ

特に意識しておく必要もないのですが、上記のように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
or
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]: 
viエディタなど初回に選択したエディタが立ち上がるので編集を行っていきます。

編集/設定例:
# 毎日5時にlogにHELLO WORLDを出力
00 05 * * * echo "HELLO WORLD" > ~/hello.log 2>&1
このようにcrontabファイル末尾に記載することで、毎日朝5時にホームディレクトリに作成されるhello.logというファイルに対してechoコマンドの出力、「HELLO WORLD」を書き込む処理を行うようスケジュールすることができます。

以下設定項目とスケジュール単位の設定方法

スケジュール単位設定方法
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
※いきなりwhich python3としても適切な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を追記していくことができます。


以上



参考:
このエントリーをはてなブックマークに追加