ローカル環境でcronを使ってpythonを自動実行させる方法
スクレイピングなど使用する時は、本当はVPSサーバーなどに契約して実行した方がいいのですが、お金使いたくないしローカル環境で完結させたいならこの方法で十分です。
1.Pythonスクリプトの準備
import datetime
# 現在の日付と時刻を取得
current_datetime = datetime.datetime.now()
# ファイルに書き込む内容
content = "現在の日付と時刻: " + str(current_datetime)
# テキストファイルに保存
with open("/home/user/current_datetime.txt", "w") as file:
file.write(content)
print("日付と時刻が 'current_datetime.txt' に保存されました。")
簡単に現在の日付と時刻をテキストファイルに保存するコードを用意しました。
これをcornで自動的に実行させるように設定していきます。
2.cronジョブの設定
操作方法がわからない方は、下の cronジョブの編集方法 を見てください。
仮に毎日午前3時に実行するとしたら、以下のように設定します。
0 3 * * * /usr/bin/python3 /home/user/myscript.py
コマンドを解説します。
'0 3 * * *' の部分は時間設定です。それぞれ 分、時、日、月、曜日 を表します。以下に詳細を説明しますね。
分 (0 - 59):
どの分にジョブを実行するかを指定します。
例: 0 は毎時0分に実行を意味します。
時 (0 - 23):
どの時間にジョブを実行するかを指定します。
例: 3 は午前3時に実行を意味します。
日 (1 - 31):
月のどの日にジョブを実行するかを指定します。
例: 15 は毎月15日に実行を意味します。
月 (1 - 12):
どの月にジョブを実行するかを指定します。
例: 6 は6月に実行を意味します。
曜日 (0 - 6):
週のどの日にジョブを実行するかを指定します(0は日曜日、1は月曜日、...、6は土曜日)。
例: 1 は毎週月曜日に実行を意味します。
特殊文字
* (アスタリスク): すべての値を意味します。例えば、月フィールドに*を置くと、毎月実行されます。
, (カンマ): 複数の値を指定します。例: 1,3,5 は月曜日、水曜日、金曜日に実行します。
- (ハイフン): 範囲を指定します。例: 1-5 は月曜日から金曜日まで実行します。
/ (スラッシュ): 繰り返しを指定します。例: */10 は10分ごとに実行します。
'/usr/bin/python3' はPythonインタープリタのパスです。これはシステムによって異なるので、'which python3' コマンドで確認してください。
which python3
# /usr/bin/python3
'/home/user/myscript.py' は実行したいファイルの絶対パスを指定してください。
cronジョブの編集方法
ターミナルを開いて、crontab -e コマンドを実行します。
これにより、cronジョブを編集するためのエディタが開きます。
crontab -e
編集モードに入る: ファイルが開いたら、編集するには i キーを押して「挿入(Insert)モード」に入ります。
編集モードを終了する: 編集が終わったら Esc キーを押して、通常モードに戻ります。
ファイルを保存して終了する: :wq と入力して Enter キーを押します。これは「Write and Quit」の略で、変更を保存してエディタを閉じます。
ファイルを保存せずに終了する: もし変更を破棄してエディタを閉じたい場合は、:q! と入力して Enter キーを押します。
※なお、基本はこちらの操作方法で動きますが、エディタによって異なる場合がありますのでご注意ください。
最後に 'crontab -l' コマンドを使用して、変更が適切に反映されたかを確認できます。
crontab -l
# 0 3 * * * /usr/bin/python3 /home/user/myscript.py
3.Cronジョブのログ設定方法
上記の設定で一通り終わりですが、Cronジョブはバックグラウンドで動作するため、通常のターミナルセッションではそのログは直接表示されません。
今の状態だと、ちゃんと出力されているのか、エラー等の確認ができません。
なので、ジョブの実行結果を追跡するために、Cronジョブの出力をファイルにリダイレクトし、エラーやその他の実行結果を確認できるようにしていきます。
以下に、ログ設定の方法を説明します。
標準出力のリダイレクト:
Cronジョブの出力(標準出力と標準エラー出力)をファイルにリダイレクトするには、ジョブのコマンドの末尾にリダイレクト命令を追加します。
例: 0 3 * * * /usr/bin/python3 /home/user/myscript.py >> /home/user/myscript.log
この例では、/home/user/myscript.py の出力が /home/user/myscript.log に追記されます。
標準エラー出力のリダイレクト:
標準エラー出力も同じファイルにリダイレクトするには、2>&1 を追加します。
例: 0 3 * * * /usr/bin/python3 /home/user/myscript.py >> /home/user/myscript.log 2>&1
このコマンドは、標準出力と標準エラー出力の両方を myscript.log に追記します。
異なるファイルへのリダイレクト:
標準出力と標準エラー出力を別々のファイルにリダイレクトすることもできます。
例: 0 3 * * * /usr/bin/python3 /home/user/myscript.py >> /home/user/myscript.log 2>> /home/user/myscript_error.log
この例では、標準出力は myscript.log に、標準エラーは myscript_error.log にリダイレクトされます。
今回は標準エラー出力も同じファイルにリダイレクトします。
なので設定は以下のようにします。
0 3 * * * /usr/bin/python3 /home/user/myscript.py >> /home/user/myscript.log 2>&1
ちなみに '>>' を '>' にすると上書き保存設定になるので、最新のログだけ必要であれば以下のログローテーションは設定する必要はありません。
0 3 * * * /usr/bin/python3 /home/user/myscript.py > /home/user/myscript.log 2>&1
ログローテーションの設定方法
こちらは手動でもファイルを消せるので必須ではありませんが、せっかくの自動化なのでこちらも設定していきましょう。
ログローテーションは、ログファイルのサイズが大きくなりすぎるのを防ぐための設定です。(ログファイルが肥大化すると、ディスクスペースを消費し、管理が困難になる可能性があります)
方法としては主に3つあります。
Linuxのlogrotateツールを使用:
多くのLinuxディストリビューションでは、logrotateというツールがログローテーションに使用されています。
logrotateはログファイルのサイズなどに基づいて、自動的にログをアーカイブし、古いログを削除します。
logrotateの設定は通常、/etc/logrotate.confファイルや/etc/logrotate.d/ディレクトリにある設定ファイルで行われます。
カスタムスクリプトを作成:
特定の要件に合わせて、カスタムスクリプトを作成してログローテーションを行うこともできます。
このスクリプトは、特定のサイズや日付に達したらログファイルをアーカイブし、古いファイルを削除するように設計できます。
このスクリプトをcronジョブとして設定して定期的に実行することができます。
アプリケーションレベルでのローテーション:
アプリケーションがログを出力する際に、ログローテーションの機能を組み込むことも可能です。
例えば、Pythonのloggingモジュールはログファイルのローテーション機能を提供しています。
今回はLinuxのlogrotateツールを使用について解説します。
まずは、ターミナルを開き、テキストエディタで設定ファイルを開きましょう。
Linuxでは一般的にnano、vi、またはvimなどのエディタが利用可能です。
今回は vi を使用します。操作方法に関しては先ほどのcronジョブの編集方法と同じです。
設定ファイルの作成または編集
logrotateの設定は通常、/etc/logrotate.conf ファイルと/etc/logrotate.d/ディレクトリ内の個別の設定ファイルで行います。
グローバル設定は/etc/logrotate.confに記述され、特定のアプリケーションやサービス固有の設定は/etc/logrotate.d/ディレクトリ内のファイルに記述されます。
sudo vi /etc/logrotate.conf
設定ファイルの書式
ファイルを開いたら、
/home/user/*.log {
weekly
rotate 1
nocompress
delaycompress
missingok
notifempty
}
このように設定してみました。
簡単に解説します。
設定ファイルは、ローテーションを行いたいログファイルのパスで始まり、その後に中括弧{}で囲まれた設定オプションが続きます。
主な設定オプション:
daily, weekly, monthly: ログのローテーションが行われる頻度。
rotate [数]: ローテートされる前に保持されるログファイルの数。
compress, nocompress: 古いログファイルを圧縮するかどうか。
delaycompress: 最新のローテートされたログファイルの圧縮を1サイクル遅らせます。
missingok: ログファイルが存在しない場合にエラーを出さない。
notifempty: ログファイルが空の場合にはローテートを行わない。
create [モード] [所有者] [グループ]: ローテート後に新しいログファイルを指定のパーミッション、所有者、グループで作成する。(今回はローカルで個人で使うのでcreateは省きます。)
cronをフルディスクアクセスに追加する
ローカルでcronを使うには、フルディスクアクセスにcronを追加しなければいけません。
厄介なのが、普通じゃ見つけられないところです。
『システム設定』⇨『プライバシーとセキュリティ』⇨下の方にある『+』ボタンを押す⇨『shift+command+g』を同時に押すとpathの入力画面が表示されるので『/usr/sbin/cron』と入力⇨cronが表示されるのでenterで追加
これでフルディスクアクセスの追加ができました。
実行権限の付与
フルディスクアクセスをしたのにcronが実行されない場合は、pythonファイルに実行権限がない可能性があります。
まずは以下のコマンドでpythonファイルに実行権限があるか確認しましょう。
ls -l /home/user/myscript.py
以下のように表示されたら実行権限がありません。
-rw-r--r-- 1 user staff 1224 1 6 00:00 /home/user/myscript.py
'-rw-r--r--'この部分に注目してください。
これはファイルのパーミッションを示しています。
- 最初の文字はファイルタイプを示しています。ここでは - なので通常のファイルを意味します(d だった場合はディレクトリ)。
rw- 次の3文字はファイル所有者(user)のパーミッションです。読み取り(r)と書き込み(w)が許可されていますが、実行(x)は - なので許可されていません。
r-- 続く3文字は同じグループのユーザー(staffグループ)のパーミッションで、読み取りのみが許可されています。
r-- 最後の3文字はその他の全てのユーザーのパーミッションで、同じく読み取りのみが許可されています。
この場合は、以下のコマンドを実行して権限を付与してください。
chmod +x /home/user/myscript.py
もう一度確認して、以下の状態になればOKです。
-rwxr-xr-x 1 user staff 1224 1 6 00:00 /home/user/myscript.py
注意点
フルパス(絶対パス)で書く
実行環境がローカルではないため、今回のようにコードの中で別ファイルを呼び出す場合はフルパスで書く必要があります。
"/home/user/current_datetime.txt"⭕️
"current_datetime.txt"❌
PCが稼働しているときにのみ実行される
cronジョブはコンピューターが稼働しているときにのみ実行されます。
もしコンピューターの電源が切れていたり、システムがダウンしている間に実行されるべきcronジョブのスケジュール時刻が来た場合、そのジョブは実行されません。
何回も実行する場合はVPSなどサーバーを借りて実行した方がいいです。
実行中システムリソースを消費もしてしまうので。
もしVPSを使うのであればおすすめはConoHa VPSがおすすめです! 私もConoHa使ってます。安くてサーバーが安定してるので^^
荒技ですが、私は普段使ってないPCをずっとつけっぱなしにしてずっと稼働状態みたいなこともしてました笑
まとめ
これでPythonスクリプトをcronジョブとして設定する準備が整いました。
最後に流れを説明します。
1.Pythonスクリプトを準備
2.cronジョブを設定する。必要であればログも出力。
crontab -e
0 3 * * * /usr/bin/python3 /home/user/myscript.py >> /home/user/myscript.log 2>&1
ログを上書きする場合は、ログローテーションを設定不要です。
0 3 * * * /usr/bin/python3 /home/user/myscript.py > /home/user/myscript.log 2>&1
3.ログローテーションを設定(必要であれば)
sudo vi /etc/logrotate.conf
/home/user/*.log {
weekly
rotate 1
nocompress
delaycompress
missingok
notifempty
}
4.cronをフルディスクアクセスに追加する
5.実行権限の付与(必要であれば)
以上になります。
これで実行時間に時刻がファイルに保存され、log結果がlogファイルに出力されます!
pathを書き換えて使ってみてください。
最初は難しいかもしれませんが、出来たらあとは楽なので是非自動化してみてください。
ちなみにVPS上でもこの記事の通りにすれば、設定できますので参考にしてみてください。
ではでは ノシ