さくらVPSでcronを使いPythonファイルを定期的に実行する
さくらVPSでDjangoをデプロイし、そのアプリケーションの中でPythonファイルをcronで定期的に実行しました。
色々とハマりポイントもあったので備忘録を兼ねてメモ。
cronが使えるかどうかを確認
私の環境ではcronが使えなかったのでインストールしました。
お使いのサーバーでcronが使えるかは以下でチェック。
$ crontab -l -bash: crontab: command not found
ないので、インストール。
$ yum install crontabs
失敗したらroot権限で。
$ sudo yum install crontabs
cronが動いているか確認します。
sudo service crond status
Activeになっていると思いますが、動いてなければ起動します。
service crond start
cronの設定ファイルを書く
$ crontab -e
ここにcronの設定ファイルを書いていきます。私の場合、最初は空のファイルでした。
毎時間の10分にスクリプトを起動したかったので、以下のようなコードにしました。
10 * * * * /usr/bin/python3.6 /home/django/xxx/main.py
ちなみに編集が終わって画面から抜ける場合は ctr + c で編集モードを終了し、:wqを入力して保存します。
例えば、10時10分に起動したい時は以下となります。
10 10 * * * /usr/bin/python3.6 /home/django/xxx/main.py
/usr/bin/python3.6の部分はシンプルにpythonと書くこともできますがPython2系で実行したりエラーが起こる場合もあるので絶対パスでPython3.6を指定してあげます。
Pythonの絶対パスは以下のように探せます。
$ which python3.6 > /usr/bin/python3.6
cronの起動を確認する
設定した時刻にうまく動作したか確認します。
Djangoでは以下のスクリプトでも確認することができます。
vi /var/spool/mail/django
shift + gでviエディタの1番下に移動できます。
データベースに書き込みができない問題
とまあ、ここまで書くと簡単なような気もしますがcronが実行される度にエラーがぽこぽこと出てきました。
cronで実行するスクリプトは複数のサイトをクローリング→DBに登録というものですが、書き込み権限がないのでエラーが吐き出されていました。
いったん手動でsudo権限でスクリプトを実行→OK
あ〜、なるほどcronの実行ユーザーに権限がないわけですね。
$ sudo nano /var/log/cron
上記、コマンドでログを確認。
当然と言えば当然ですけど権限のないユーザーで実行されていました。
Dec 16 11:50:01 tk2-405-43613 CROND[5266]: (ユーザー名) CMD (/usr/bin/python3.6 /home/django/xxx/xxx.py)
crontab -eを実行してファイルを作成したユーザーの権限で実行されています。
cronは全てのコマンドがroot権限で実行されるのではなく、crontab -eを作成したユーザーの権限の範囲内で実行されます。
ここまでくると、選択肢は2つのような気がしました。
- ユーザーに権限を付与してcronを実行する
- rootユーザーでcronを実行する
まず、1を実行。
sudo visudo
ファイルに以下を追加。
Defaults:ユーザー名 !requiretty
しかし、また同じエラーが…
[Sy] cronでsudoが必要なコマンドを実行しようとしたらTTYないとダメだよとエラーになる場合の設定方法
というわけで2を実行。結果的にはこっちがうまくいきました。
$ sudo su
rootユーザーに変更。そして、crontab -eでcrontabを記述していきます。
内容は上記でcrontabに記述した内容と同じもの。これでrootユーザーの権限で cronが実行されます。
ユーザーを戻す時は、以下の通り。
$ su ユーザー名 #もしくは、 $ exit
これで無事にスクリプトが定期的に実行されるようになりました。