スターサーバーのCronを利用して定期的にPythonコードを実行する方法

レンタルサーバーの Cron を利用すると、定期的に Python コードを実行することができます。サーバーで動作するため、自分のパソコンが起動していない時でも実行できて便利です。スターサーバーさんでは、ライトプラン以上の契約で Cron を利用することができます。

Cron の一例として、Python の公式RSSに更新があった場合にメールで通知されるようにしてみたいと思います。


  1. 実行するファイル(.py)のアップロード
  2. パーミッション設定
  3. Cron の設定
  4. RSSを取得するサンプルコード

1. 実行するファイル(.py)のアップロード

まずは、実行するファイル(.py)をサーバーにアップロードします。サンプルコードは最後に載せてあります。

サーバー管理ツールにログインし、「FTPアカウント設定」から WebFTP にログインします。初期設定FTPアカウントが初めから1つ用意されていますので、これを利用しましょう。

WebFTPへのログイン

ファイルマネージャーが開いたら、任意の場所にファイルをアップロードします。特に決まりはありませんが、他のファイルと混同しないよう、ルートディレクトリに Cron 専用のディレクトリを作成することをお勧めします。

ファイルマネージャーの使い方は特に難しくないと思います。詳しくは マニュアル > ファイルマネージャー をご参照ください。


2. パーミッション設定

Cron で実行するファイルは、オーナーが読み込みできれば充分です。グループやその他に読み込み権限を与える必要はありません。そのため、ファイルマネージャーの歯車アイコンから以下のようにパーミッションを変更します。

対象パーミッション設定初期設定
Cron 専用ディレクトリ700705
Cron で実行するファイル600604

これで、その他に与えられていた権限が取り除かれ、オーナーしか読み込みができなくなります。


3. Cron の設定

サーバー管理ツールに戻り、「Cron設定」から「通知先の設定」および「CRON追加」を行います。

CRON設定

「通知メールアドレス」には、実行結果の標準出力と標準エラーとが通知されます。そのどちらもない場合には、何も通知されません。実行するコードの中で必要な場合にのみ標準出力を行うことで、毎回メールが送られてくるのを避けることができます。

「CRON追加」タブでは、実行するタイミングやコマンドを指定することができます。

CRON編集

タイミングの設定は、数値もしくは「*」を入力するだけです。「*」は毎分、毎時間といった意味になります。便利な使い方として、カンマ区切りで複数のタイミングを指定することができます。上図では「時」に「6,18」と入力していて、こうすると毎日6時および18時に実行されます。

「コマンド」には、実行するコマンドを入力します。Windows のコマンドプロンプトで .py を実行するのと同じように、Python 本体に .py を渡す形式で記述します。

/user/bin/python3.6 /home/(サーバーID)/ekapyw.byte.jp/public_html/Cron専用ディレクトリ/実行ファイル.py

「/user/bin/python3.6」の部分が Python 本体です。これは マニュアル > WEBサーバーの仕様 を見ればコマンドパスとして載っています。

半角スペースを空けて .py ファイルのパスを記述します。先にアップロードしたファイルのパスを指定するだけですが、ファイルマネージャーで表示されたルートディレクトリに至るパス(/home ~ /public_html の部分)も書かなければいけないので、それを調べます。

「FTPアカウント設定」の「FTPアカウント一覧」を開きます。FTPアカウントの「編集」ボタンを押すと「FTPアカウント編集」画面になります。「パス」に記載されているのがルートディレクトリのパスです。ファイルマネージャーでは、一見ドメイン名がルートディレクトリかのように表示されますが、実際には「public_html」が入ります。

ルートディレクトリの調べ方

4. RSSを取得するサンプルコード

最後にサンプルコードを示します。Python の公式RSSに更新があった場合にのみ、その日時とタイトルを標準出力に書き出します。

#! /usr/bin/python3 -I -S
"""When Python release news is updated within 12 hours, the information is
    printed to standard output.
"""


from calendar import month_abbr
from datetime import datetime, timedelta
from traceback import print_exc
from urllib.request import urlopen
from xml.etree import ElementTree


# ==============================
def main():
    _now = datetime.now()
    _published, _title = _python_release_news()

    if (_now - _published) <= timedelta(hours=12):
        print(f'[{_published}] {_title}')


# ==============================
def _python_release_news() -> tuple:
    """Returns the datetime and title of the latest Python release news."""
    _url = 'https://blog.python.org/feeds/posts/default?alt=rss'

    try:
        with urlopen(_url) as _response:
            _xml = ElementTree.parse(_response).getroot()
    except:
        print_exc()
    else:
        for i in _xml.iter('item'):
            _pubdate = i.find('pubDate').text
            _week, _day, _month, _year, _time, _zone = _pubdate.split()
            _datetime = datetime(
                int(_year),
                list(month_abbr).index(_month),
                int(_day),
                *[int(t) for t in _time.split(':')],
            )
            return (_datetime, i.find('title').text)

    return (datetime.min, '')


# ==============================
if __name__ == '__main__':
    main()

これを Cron で実行すると、RSSに更新があった場合、もしくは何らかのエラーが起きた場合にのみメールが来るようになります。何もないときはメールが来ません。

信頼できるソースからのRSSは xml.etree.ElementTree で処理できます。_python_release_news() で、「pubDate」から日時を、「title」からタイトルを取得し、datetime オブジェクトとタイトル文字列を返しています。

19行目で現在日時と更新日時を比較し、その差が12時間以内のときに標準出力を行っています。ここは、Cron 設定の「時」で1日2回実行する設定をしていますので、その間隔と合わせるようにします。

このサンプルでは、RSSをイテレーションした最初の項目、つまり最新の投稿をそのまま出力しています。必要に応じて、タイトルの文字列でフィルタリングするなど、出力する項目を選別すると良いでしょう。

Leave a comment

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

19 + 2 =