#pythonで書いたものをデーモンにしたい
さくらのVPSにてpythonで書いたプログラムを常に走らせたかった。
おまけにsystemctlで操作できるので楽ちん。
やり方は以下のパクリ。
Systemdを使ってさくっと自作コマンドをサービス化してみる
#環境
- さくらのVPS
- CentOS 7
#How to
##プログラム
#!/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
これで実行権限が付与されたはずです。
ユニット定義ファイルを作る
[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
で管理ができるので楽ちんだし、何か感動する