LoginSignup
102
123

More than 5 years have passed since last update.

pythonをデーモン化するメモ

Posted at

pythonで書いたものをデーモンにしたい

さくらのVPSにてpythonで書いたプログラムを常に走らせたかった。
おまけにsystemctlで操作できるので楽ちん。
やり方は以下のパクリ。
Systemdを使ってさくっと自作コマンドをサービス化してみる

環境

  • さくらのVPS
  • CentOS 7

How to

プログラム

/opt/python_daemon.py
#!/usr/bin/env python
import time
import os
import sys

def main_unit():#10秒おきに時刻を書き込む
    while True:
        filepath = '/opt/pydmon.log'
        log_file = open(filepath,'a')
        try:
            log_file.write(time.ctime()+"\n")
        finally:
            log_file.close()
            time.sleep(10)

def daemonize():
    pid = os.fork()#ここでプロセスをforkする
    if pid > 0:#親プロセスの場合(pidは子プロセスのプロセスID)
        pid_file = open('/var/run/python_daemon.pid','w')
        pid_file.write(str(pid)+"\n")
        pid_file.close()
        sys.exit()
    if pid == 0:#子プロセスの場合
        main_unit()

if __name__ == '__main__':
    while True:
        daemonize()

Shebangを指定しましょう。

先頭に#!/usr/bin/env python#!/usr/bin/pythonを加えます。
#!/usr/bin/env python$PATHの先頭にあるpythonを優先して使うそうです。
対して、#!/usr/bin/pythonは直接/usr/bin/配下にあるpythonを指定しているらしい。
バージョンが違うと不都合がおきるかもしれないです。

Stack overflowに詳しいことがありましたので、興味の有る方は参考にしてみてください。
Why do people write #!/usr/bin/env python on the first line of a Python script?

daemonize()について

プロセスをforkして、親プロセスは変数pidに返った子プロセスIDをpidファイルに書き込んで消えます。
一方、子プロセスはmain_unit()を10秒おきに無限ループで実行します。

保存したら実行権限を与えましょう。

sudo chmod 755 /opt/python_daemon.py
これで実行権限が付与されたはずです。

ユニット定義ファイルを作る

/usr/lib/systemd/system/pythondaemon.service
[Unit]
Description=PythonDaemon

[Service]
ExecStart=/opt/python_daemon.py
Restart=always
Type=forking
PIDFile=/var/run/python_daemon.pid

[Install]
WantedBy=multi-user.target

Daemonの定義ファイルです。
ExecStartとPIDFileが帳尻合えばあとはコピペでも大丈夫かと思います。

デーモンを起動する

sudo systemctl daemon-reload
sudo systemctl start pythondaemon.service

デーモンをリロードしたら、新しく作ったpythondaemon.serviceが認識されます。
そしてstartで起動させます。

結果

$ sudo systemctl status pythondaemon.service


● pythondaemon.service - PythonDaemon
   Loaded: loaded (/usr/lib/systemd/system/pythondaemon.service; disabled; vendor preset: disabled)
   Active: active (running) since 月 2017-09-11 00:35:12 JST; 10s ago
  Process: 4633 ExecStart=/opt/python_daemon.py (code=exited, status=0/SUCCESS)
 Main PID: 4634 (python)
   CGroup: /system.slice/pythondaemon.service
           └─4634 python /opt/python_daemon.py

うごいた!

pydmon.logもこんな感じ

$ cat pydmon.log 
Mon Sep 11 00:35:12 2017
Mon Sep 11 00:35:22 2017
Mon Sep 11 00:35:32 2017
Mon Sep 11 00:35:42 2017
Mon Sep 11 00:35:52 2017
Mon Sep 11 00:36:02 2017
Mon Sep 11 00:36:12 2017
Mon Sep 11 00:36:22 2017
Mon Sep 11 00:36:32 2017
Mon Sep 11 00:36:42 2017
Mon Sep 11 00:36:52 2017
Mon Sep 11 00:37:02 2017

感想

systemctlで管理ができるので楽ちんだし、何か感動する

102
123
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
102
123