どうも、白夜霧(@KiRi_Byakuya)です。
今回はRaspberry Pi(ラズパイ)で、Pythonで作成したプログラムをデーモン化(常駐ソフト化)する方法の覚書。
目次
Raspberry Pi+Python開発&実行環境
lsb_release -a
No LSB modules are available.
Distributor ID: Raspbian
Description: Raspbian GNU/Linux 11 (bullseye)
Release: 11
Codename: bullseye
python --version
Python 3.9.2
ラズパイで任意のPythonのプログラムをデーモン化して、自動起動させる手段は?
pythonのプログラムをデーモン化(常駐ソフト化)する手段は「systemd」か「python-deamon」のいずれかが定番の模様。
私がやりたいのは「OSが起動したら、自動的に指定のプログラムが起動して、バックグラウンドで実行させ続けたい。」というもの。
今回は、OSの再起動でも自動的に起動する「systemd」でpythonのプログラムをデーモン化する手段の覚書。
「systemd」に関しては、下記記事を参考にさせて頂きましたm(_ _)m
ラズパイでPythonのプログラムをデーモン化して、systemdで自動起動させる方法
簡単な流れ
- ①自動起動させたいプログラム(サービス)を作る。
- ②サービスの設定ファイルを作成する。
- ③サービスを有効&実行する。
下記記事を参考にサンプルを作成。※というかほぼ丸パクリm(_ _;)m
1.Pythonのデーモン化サンプルプログラムを作成する
※3秒間隔で「hello world!」を出力するだけのプログラム
#!/usr/bin/env python3
import time
import os
import sys
def daemon_loop():
while True:
print('hello world!')
sys.stdout.flush()
time.sleep(3)
if __name__ == '__main__':
daemon_loop()
上記サンプルのソースファイルは、ホームディレクトリ→「py」に配置。
2.サービスの「設定ファイル」を作成する
①サービスの設定ファイルを保存する場所へ移動。
cd /usr/lib/systemd/system
②設定ファイルを作成。※ファイル名は任意。
sudo nano sample_daemon.service
③設定ファイルの中身
[Unit]
Description=Sample Daemon[Service]
ExecStart=/home/pi/py/sample_daemon.py
Restart=always
Type=simple[Install]
WantedBy=multi-user.target
参考
- Description : ユニットの説明。systemctl statusのときに表示される。
- ExecStart : 起動時に実行するコマンドを指定。今回の場合pythonのファイルパスを指定。
- Restart:プロセスが停止した時の再起動の条件。(always = 常に再起動)
- Type:プロセスの起動方法(simple=デフォルト値。プロセス起動時点で起動完了)
- WantedBy:サービスを有効にした際、どのTargetを前提とした設定にするかを指定する。(multi-user.target=通常のマルチユーザーモード)
色々と参考にさせて頂いた記事m(_ _)m
- 設定ファイルの各オプションについて:systemd のユニットファイルの作り方
- WantedByって何?:Systemd入門(1) - Unitの概念を理解する
- 「multi-user.target」はランレベル3→ランレベルとは?:ランレベルとは
3.サービス(Pythonのプログラム)を有効化&実行する
下記ではホームディレクトリに戻ってから実行してますが、戻らなくてもOK。
①デーモンの再読み込み
サービス作成後、下記コマンドでsystemctlにデーモンを再読み込みさせる。
sudo systemctl daemon-reload
②サービスを実行する
sudo systemctl start sample_daemon
③サービスの起動を確認する
sudo systemctl status sample_daemon
上記コマンドを実行すると、一定の間隔で「hello world!」を出力されているのがわかります。
sudo systemctl status sample_daemon
● sample_daemon.service - Sample Daemon
Loaded: loaded (/lib/systemd/system/sample_daemon.service; disabled; vendo>
Active: active (running) since Thu 2022-03-17 23:51:07 JST; 20s ago
Process: 2909 ExecStart=/home/pi/py/sample_daemon.py (code=exited, status=0>
Main PID: 2910 (python3)
Tasks: 1 (limit: 1597)
CPU: 294ms
CGroup: /system.slice/sample_daemon.service
mq2910 python3 /home/pi/py/sample_daemon.py
3月 17 23:51:06 raspberrypi systemd[1]: Starting Sample Deamon...
3月 17 23:51:07 raspberrypi sample_daemon.py[2910]: hello world!
3月 17 23:51:07 raspberrypi systemd[1]: Started Sample Deamon.
3月 17 23:51:10 raspberrypi sample_daemon.py[2910]: hello world!
3月 17 23:51:13 raspberrypi sample_daemon.py[2910]: hello world!
3月 17 23:51:18 raspberrypi sample_daemon.py[2910]: hello world!
3月 17 23:51:19 raspberrypi sample_daemon.py[2910]: hello world!
3月 17 23:51:22 raspberrypi sample_daemon.py[2910]: hello world!
3月 17 23:51:25 raspberrypi sample_daemon.py[2910]: hello world!
3月 17 23:51:28 raspberrypi sample_daemon.py[2910]: hello world!
④サービスの自動起動を有効にする。
sudo systemctl enable sample_daemon
Created symlink /etc/systemd/system/multi-user.target.wants/sample_daemon.service → /lib/systemd/system/sample_daemon.service.
⑤サービスの自動起動の状態を確認する
方法は2つ。サービス名を指定して確認。
systemctl is-enabled sample_daemon
enabled
もしくは、下記コマンドで全てのユニットファイルの自動起動の状態を確認する。
systemctl list-unit-files --type=service
上記を実行すると、下記のように表示されて有効/無効状態が一覧で確認できる。
一旦この状態でラズパイ本体を再起動させて、指定のプログラムが自動起動しているか確認することを推奨。
4.サービス(Pythonのプログラム)を無効化&停止する
①サービスを停止
sudo systemctl stop sample_daemon
サービス停止後、ステータスを確認すると下記のようになる。
sudo systemctl status sample_daemon
● sample_daemon.service - Sample Deamon
Loaded: loaded (/lib/systemd/system/sample_daemon.service; enabled; vendor>
Active: inactive (dead) since Fri 2022-03-18 00:46:32 JST; 41s ago
Main PID: 2910 (code=killed, signal=TERM)
CPU: 605ms
3月 18 00:46:13 raspberrypi sample_daemon.py[2910]: hello world!
3月 18 00:46:16 raspberrypi sample_daemon.py[2910]: hello world!
3月 18 00:46:19 raspberrypi sample_daemon.py[2910]: hello world!
3月 18 00:46:22 raspberrypi sample_daemon.py[2910]: hello world!
3月 18 00:46:25 raspberrypi sample_daemon.py[2910]: hello world!
3月 18 00:46:28 raspberrypi sample_daemon.py[2910]: hello world!
3月 18 00:46:31 raspberrypi sample_daemon.py[2910]: hello world!
3月 18 00:46:32 raspberrypi systemd[1]: Stopping Sample Deamon...
3月 18 00:46:32 raspberrypi systemd[1]: sample_daemon.service: Succeeded.
3月 18 00:46:32 raspberrypi systemd[1]: Stopped Sample Deamon.
①サービスの自動起動を無効にする
sudo systemctl disable sample_daemon
Removed /etc/systemd/system/multi-user.target.wants/sample_daemon.service.
以上、有難うございましたm(_ _)m
参考になったらポッチとお願いしますm(_ _)m