Pythonプログラムをデーモン起動する(Raspbian)

Pythonで実装したプログラムを、Raspberry Pi(Raspbian)でデーモン起動させるときのメモ。

python-daemonのインストール

python-daemonは、Pythonプログラムをdaemon化できるパッケージである。

sudo apt-get install python-daemon

デーモンプログラム

Pythonプログラムはこんな感じ。

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import serial
import time

from daemon import DaemonContext
from daemon.pidlockfile import PIDLockFile

if __name__ == '__main__':
        # 以下がデーモンプロセスとして実行される
        # pidfileが/tmpにないと、動作しないらしい
        with DaemonContext(pidfile=PIDLockFile('/tmp/serial-arduino.pid')):
                main()

起動スクリプト

サービス起動させるための起動デーモンは以下の通り。

$ sudo vi /etc/init.d/hoged

#!/bin/sh

### BEGIN INIT INFO
# Provides:        hoged
# Required-Start:  $local_fs $remote_fs $syslog
# Required-Stop:   $remote_fs
# Default-Start:   2 3 4 5
# Default-Stop: 
# Short-Description: Start hoged daemon
### END INIT INFO

PATH=/sbin:/bin:/usr/sbin:/usr/bin
# Source function library.
. /lib/lsb/init-functions

# Path to the script
DAEMON=/usr/local/sbin/python-hoge.py
PROG=serial-arduino
PIDFILE=/tmp/hoged.pid
LOCKFILE=/tmp/hoged.pid.lock

test -f $DAEMON || exit 0

lock_hoged() {
        if [ -x /usr/bin/lockfile-create ]; then
                lockfile-create $LOCKFILE
                lockfile-touch $LOCKFILE &
                LOCKTOUCHPID="$!"
        fi
}

unlock_hoged() {
        if [ -x /usr/bin/lockfile-create ] ; then
                kill $LOCKTOUCHPID
                lockfile-remove $LOCKFILE
        fi
}

case "$1" in
    start)
        log_daemon_msg "Starting $PROG server" "$PROG"
        lock_hoged
        start-stop-daemon --start --quiet --oknodo --pidfile $PIDFILE --startas $DAEMON -- -p $PIDFILE
        status=$?
        unlock_hoged
        log_end_msg $status
        ;;
    stop)
        log_daemon_msg "Stopping $PROG server" "$PROG"
        start-stop-daemon --stop --quiet --oknodo --pidfile $PIDFILE
        log_end_msg $?
        rm -f $PIDFILE
        ;;
    status)
        status_of_proc -p $PIDFILE $DAEMON $PROG
        ;;
    restart)
        stop
            start
        ;;
    *)
        echo "Usage: $PROG {start|stop|status|restart}"
        exit 1
        ;;
esac

最後に変更を反映。

sudo update-rc.d hoged defaults

Raspberry Piのインストール

Raspberry Piの起動と終了

Raspberry Piの起動

Raspberry Piは、電源を投入すると自動的に起動する
インストール時のログイン名/パスワードは、
以下の通り設定されていて、piユーザにはsudo権限が付与されている
+ user: pi
+ pass: raspberry
Guiを開始する場合は、以下のコマンドを実行する

$ startx

Guiの終了は、メニューからログアウトを選択する

Raspberry Piの終了

終了や再起動は、通常のLinuxと同じで、
以下のいずれかのコマンドを実行する

$ sudo reboot
$ sudo shutdown -h now

Rasbperianのセットアップ

Raspberianのインストール

まず、Raspberry Piで使用するSDカードを
SD Formatterを利用して初期化する
+ https://www.sdcard.org/downloads/formatter_4/
対象のSDカードを選択して、初期化を実行する
SDカードのフォーマット
初期化されたSDカードにNOOBSをコピーする
NOOBSのコピー

Raspberry Pi + Motion + WebCamで動体検知を行う

Raspberry Piに接続したWebCamから映像を取得可能なパッケージはいくつか有名なものが存在するようだが、今回はMotionという動体検知を行うことのできるパッケージを用いて、WebCamの映像を取得してみる。

パッケージのインストール

apt-getから取得することができる

sudo apt-get install motion

設定

今回はMotionをデーモン起動させて常時稼働させる。設定ファイルは以下のように変更した。

# Image width
width 640
# Image height
height 480
# Maximum number of frames to be captured per second.
# フレーム数を大きくしすぎるとRaspberry Piで処理しきれなくなる
framerate 3
# Output 'normal' pictures when motion is detected
# 動体検知時に画像を出力しない
output_pictures off
# Use ffmpeg to encode movies in realtime
# 動体検知時に動画を出力しない
ffmpeg_output_movies off
# Make automated snapshot every N seconds
snapshot_interval 1
# Locate and draw a box around the moving object.
# 動体マーカ
locate_motion_mode on
# Target base directory for pictures and films
target_dir /var/www/html
# File path for snapshots (jpeg or ppm) relative to target_dir
snapshot_filename snapshot
# Restrict stream connections to localhost only
# ローカルホスト以外からのアクセスを許可する
stream_localhost off
# Restrict control connections to localhost only
# ローカルホスト以外からのアクセスを許可する
webcontrol_localhost off

サービスの開始

USBカメラを繋ぎ、認識されていることを確認する。

lsusb

Bus 001 Device 015: ID 0c45:62e0 Microdia MSI Starcam Racer

設定ができたらサービスを開始する。でも正常にサービス開始しない。

sudo service motion start
Apr 20 18:42:55 raspberrypi motion[1410]: Not starting motion daemon, disabled via /etc/default/motion ... (warning).

/etc/default/motionも変更しないといけないらしい。

sudo vi /etc/default/motion

# set to 'yes' to enable the motion daemon
start_motion_daemon=yes

再度、サービス開始。
今度はちゃんと開始された。

sudo service motion start

以下のエラーが発生する場合は、画像の出力先のパーミッションに問題ある場合があるので、パーミッションを変更する。

Apr 20 19:28:15 raspberrypi motion[7929]: [1] [ERR] [ALL] put_picture: Can't write picture to file /var/www/html/snapshot.jpg - check access rights to target directory
                                          Thread is going to finish due to this fatal error:
Apr 20 19:28:15 raspberrypi motion[7929]: [1] [ERR] [EVT] event_image_snapshot: Could not create symbolic link [snapshot.jpg]: