今日はMacでのcrontab(クーロンタブ)の初期設定を紹介します。
これをうまく起動させるために、かなりの壁にぶつかったので、これを全て紹介します。
これでゼロからcrontabでpythonなり、なんなりを動かせます。
Crontabとは
Crontabはcron(クーロン)とも呼ばれ、Linux、Unix、Macなどに初期からあるコマンド(=機能)で、時間と読み出しプログラムをしているすると、指定通り定期的にそのプログラムを起動できる。
例えば、毎日8時にニュース一覧をダウンロードしてくるとか、1時間ごとにPCに接続された温度計の値を読むとか、というのができるようになる。
このcrontabの設定は簡単で、コマンドラインで
username$ crontab -e
と入力した時に現れるファイル編集において次のように書き込めば良い。
#crontab content
0 8 * * * get_news.sh
基本的にこれですが、実際には設定がいくつか必要です。
特にPATHの設定や権限の設定などです。
準備: 編集テキストエィタの変更
cronの設定は次のコマンドで行う。(cron…以降を入力する。”username$”はターミナルということを意味しているだけ)
username$ crontab -e
ただ、これをそのままターミナルで起動すると、viが編集エディタとして立ち上がってしまう。
emacsをよく使う私としては、emacsで立ち上がって欲しいので、ターミナルで次のようにします。
username$ export EDITOR="emacs"
これで基本エディタをemacsに変えることができます。
(もちろんviのままが良い人は何もしなくて良いですが。)
設定 1: 動かしたいプログラムの「実行許可」を出す
定期的に動かしたいプログラム(これを例えば「program.sh」とする)に実行許可を出しておかないといけません。
次のようにします。
username$ chmod 744 program.sh
これなら自分には実行許可が出たことになる。「744」のところを「755」とすれば、他のユーザーにも実行許可が出せる。
これを行わないと、次のように許可がないと怒られます。
username$ Permission denied
設定 2: crontabの実行シェルをbashにする
crontabでスクリプトが実行される時に使用される「実行シェル」はいつもいつも使っているものとは限らないので、それを設定しておく必要があります。
私はいつもbashを使っているので、これに設定しなおします。
ターミナルで
username$ crontab -e
とすると、先ほど設定したテキストエィタでcrontabの設定ファイルが開きます。
ここに次のように書き込みます。
#shell setting
SHELL=/bin/bash
これでbashが使われるようになります。
いったんこれを保存後閉じて、もう一回同じコマンドで開いても設定は残っています。
設定 3: PATHの設定
次にPATHを設定します。
これをしないと例えば次のようなエラーを吐き出す。(呼び出した先のbashファイルでpython3コマンドが使われている例)
username$ -bash: python3: command not found
crontabが起動する時、PATHは何も設定されていません。
ですので、基本中の基本のコマンドしか呼び出した先(program.shなど)で使えません。
pythonも使えません。
これでは不便ですのでちゃんとPATHを設定します。
まずは自分のPATHにどのようなものが設定されているのかを確認します。
ターミナルで
username$ echo $PATH
と入力すると、現在の設定されているPATHが全て表示されます。
ですので、これをそのままcrontabの設定でも使えば良いです。
私の場合には、次のようになっています。
username$ echo $PATH
username$ /Library/Frameworks/Python.framework/Versions/3.8/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin
ここでの2行目の内容がPATHの内容なので、これをcrontabにもそのまま設定します。
先と同様に
username$ crontab -e
でcrontabの設定ファイルを開きます。
次の1行を書き加えます。
#PATH setting
PATH=/Library/Frameworks/Python.framework/Versions/3.8/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin
ここでの注意点は「=」の前後にスペースを入れてはいけないという点。
bashの場合変数への代入を行う時は、スペースを入れないというルールがある。
ここでは実はpython関連のPATHも設定されるため、これをやらないと、次のようにpythonをcrontabで動かす時にimport先が見つからないと言われます。
username$ No module named 'numpy'
crontabでbashファイルを呼び出して、その中からpythonを呼び出しても同様な現象になります。
設定 4: 呼び出し先の設定
crontabでの実行はhomeディレクトリで行われます。
なので、crontab内での呼び出し先の設定は絶対パスである必要があります。
さらに呼び出し先のプログラム(例えばprogram.sh)ではhomeディレクトリにいる前提で書いておく必要があります。
これを簡単にするために、crontabではbashファイルを呼び出すようにして、その呼び出し先のbashファイルの最初にcd移動コマンドを設定しておきます。
例えば次のように。
#program.sh
cd /Users/username/Documents/cron_test/
python3 program_py.py
ここでは、/Users/username/Documents/cron_test/内に、program.shとprogram_py.pyがあるという状態を想定しています。
crontabによってprogram.shが呼び出されると、最初の行でcd移動が行われて、program_py.pyがあるディレクトリに移動します。
このcd移動の1行がないと、homeで実行していることになりますので、そこにはprogram_py.pyはないため次のようにエラーが出ます。
username$ No such file or directory
crontabでの実行プログラムの設定
では、上記の準備、設定ができたら、いよいよcrontab内でのプログラムの登録を行います。
username$ crontab -e
で設定ファイルを開きます。
そこに例えば次のように書き込みます。
#shell setting
SHELL=/bin/bash
#PATH setting
PATH=/Library/Frameworks/Python.framework/Versions/3.8/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin
0 8 * * * /Users/username/Documents/cron_test/program.sh
最初の4行(コメント行含)は先述の設定部分で書き入れた箇所です。
最後の1行が、呼び出すタイミングと、呼び出すプログラムが書かれています。
呼び出すタイミングは5つ区画で決定されます。
それぞれは
[分] [時] [日] [月] [曜日]
を表しています。上記の例だと、毎日の8時0分に実行されることになります。
呼び出すプログラムは絶対パスで書かないといけません。
先ほど説明したようにcrontabの実行場所はhomeディレクトリなので、そこからの相対パスでも可能なはずですが絶対パスの方が無難でしょう。
この1行を書いてファイルを保存すれば、登録が完了したことになり、時間になるとcrontab自動で動いて呼び出してくれます。
以上のように準備、設定、登録を行えば時間を指定して自動で任意のプログラムを走らせることができるようになります。
実例: crontabからpythonを呼び出す
以上のまとめも兼ねて、実例を1つ示したいと思います。
この例では、各プログラムの置き場所などの状況としては次のようになっています。
Crontab上での設定内容
username$ crontab -e
で呼び出したcrontabの設定は次のようにします。
#shell setting
SHELL=/bin/bash
#PATH setting
PATH=/Library/Frameworks/Python.framework/Versions/3.8/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin
0 8 * * * /Users/username/Documents/cron_test/program.sh
先に説明したように、shell setting部分では、使用するシェルを指定し、PATH setting部分では利用するコマンドのPATHを設定します。
そして最後の一行で、起動する時間とプログラムを指定します。
呼び出し先のbashの内容
呼び出し先のbashであるprogram.shが次のような内容になります。
#program.sh
cd /Users/username/Documents/cron_test/
python3 program_py.py
先に説明したように、最初の部分はcrontabの実行場所がhomeなので、それを変更するためのcd移動です。
で、次が実際のプログラムが書かれた部分の実行になります。
crontab実行時のエラーやログ
crontabは、指定時間になると勝手に動き出して、勝手に終了します。
つまりエラーやログはその場では表示されません。
実行するプログラム中にログを書き残すような仕掛けをしておけば、良いですが、実行時のエラーは通常確認できません。
では、crontab実行のエラーやログはどこに残っているかというと、実は次のところに記載されます。
/var/mail/username
これはテキストファイルで、emacsやviで読めます。
エラーもここに出るので、確認してデバックを行うことができます。
まとめ
定期的に動かしたいプログラムがある時には、crontabを利用すると自動化が可能です。
ただし、crontabを正しく実行するためには、実行許可の設定が必要であることに加え、homeディレクトリでの実行を考慮した設定、実行シェルやPATHの設定が必要です。
crontabでの実行時のログやエラーは`/var/mail/username`に収められているので、うまく動いていないような気がした場合にはこれを確認すればOK
みなさんもどうぞ仕事の自動化をしていきましょう!
コメント