プログラムを書いたらやはり「システム起動時に自動的に実行」ということがしたくなる。
pythonの場合、プログラム自体はシェルから
python sample.py
とすると実行できるが、実行中は他の作業が出来ない。
ctrl+zで一時停止させて
jobs
で表示されたナンバーを
bg 1
等とするとバックグラウンドで実行されるが面倒くさい。
元々
python sample.py&
とすると最初からバックで実行されるようになるが、ユーザーがログアウトしたら終了してしまう(のかな?)
最初から自動的にバックグラウンドアプリとして実行させるには「デーモン」というプログラムにする必要がある。
(こりゃデビルか・・・)
Linuxではデーモンとして作ってサービスに設定することでシステム起動時に自動で実行したり、killされた場合は再度実行されたり、システム終了時に自動で読み出すように設定することも可能なようだ。
デーモンプログラムは名前の最後に「d」を付けるのが一般的なようでsample.pyではなく、sampled.pyのように名付けるそうだ。
こちらのブログを参考にさせていただいた。というかそのまま。
https://glorificatio.org/archives/1965
-- sampled.py --
import os
import sys
import time
def sample():
while 1:
time.sleep(5)
print "sample-daemon"
def fork():
pid = os.fork()
if pid > 0:
f = open('/var/run/gpio_fan_controld.pid','w')
f.write(str(pid)+"\n")
f.close()
sys.exit()
if pid == 0:
sample()
if __name__=='__main__':
fork()
5秒ごとに「sample-daemon」と出力するだけのプログラム。
fork()でPID(プロセスID)をファイルに保存し、デーモンとして実行された時に追跡(?)出来るらしい。
このデーモンとして作ったプログラムをデーモンとしてシステムに登録することでデーモンプログラムとしてシステムから実行出来る。
デーモンプログラムを含め、各プロセス管理システムをサービスと呼ぶ。
ちなみに、sample.pyをデーモンとして実行させた場合、リモートでは実行されているかわからない。
Linuxでは標準出力したものはログファイルに残るようになっている。
なので確認は
sudo nano /var/log/syslog
で確認することが出来る。
Raspbianではinit.dで管理しているサービスとsystemdで管理しているサービスがある。
これらはディストリビューションにより異なる。
init.dはWheezy以前の比較的古いシステム、systemdはJessie以降の比較的新しいで採用されている。
僕の場合、幸運なことに一台目でWheezy、二台目でJessieと2つとも触ることが出来たのでinit.dとsystemdの書き方を両方残しておく事にする。
sampled.pyのプログラム自体は変える必要はない。
==== まず、新しいsystemdの書き方 ====
サービスの設定ファイルを置く場所
cd /usr/lib/systemd/system
へ移動
sudo nano sampled.service
でサービス設定ファイルを作る
(/usr/lib/systemd/system/より、/etc/systemd/system/ のが優先的に使われるようです。)
中身はこんな感じ
-- sampled.service --
[Unit]
Description=Sample Daemon[Service]
ExecStart=/usr/local/lib/sampled.py
Restart=always
Type=forking
PIDFile=/var/run/sampled.pid[Install]
WantedBy=multi-user.target
Unitはデーモンの説明
Serviceが設定
ExecStartでシステム起動時にsampled.pyを起動するよう設定している。
(余談)ExecStopPost=/usr/local/lib/end.pyのように指定するとsampled.py終了時にend.pyプログラムを実行することが出来るようだ。
Restartはプロセスが終了した場合の再起動条件
Typeはサービス起動完了の判定方法
PIDFileはsampled.pyで生成したPIDファイルの場所
その他、こちらのブログに詳しく書いてあるので割愛
Systemd入門(4) - serviceタイプUnitの設定ファイル - めもめも
上記のサービス設定ファイルが書けたら保存して
サービスの再読み込みをする。
sudo systemctl daemon-reload
サービスをスタート
sudo systemctl start sampled
動いているか確認
systemctl status sampled
システム起動時に自動的に実行させる
sudo systemctl enable sampled
起動時に実行する設定が有効かチェックする
systemctl is-enabled sampled
起動時に実行する設定を取り消す
systemctl disable sampled
その他systemdの使い方参考サイト
<追記>Systemdだけで運用する場合、つまりinit.dとの互換性を保つ必用の無い場合は下URLの方法が楽です。
==== init.dでの書き方 ====
/etc/init.d/skeleton が起動スクリプトのサンプルなのでコピーして書き換える
sudo cp /etc/init.d/skeleton /etc/init.d/sampled
sudo nano /etc/init.d/sampled
4カ所書き換える
-- sampled --
### BEGIN INIT INFO
# Provides: sample daemonDESC=”sample_daemon”
NAME=sampled
DAEMON=/usr/local/lib/$NAME.py
Provides:名前(?)
DESC プログラムの説明
NAME プログラム名
DAEMON NAMEで設定したpythonファイルのある場所
実行権をつける
chmod 755 /etc/init.d/sampled
サービス登録する
sudo insserv sampled
正しく登録されているか確認する
sudo find /etc/ -name "*sampled"
ランレベルごとのディレクトリにsampledが正しく入っていれば成功。
登録削除は
insserv -r sampled
サービスの起動
sudo /etc/init.d/sampled start
サービス一覧表示
service --status-all
ステータス表示
service sampled status