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でスクリーンショットを撮影する

Raspberianでスクリーンショットを撮るときは、Scrotがオススメ。

Scrotをインストール

$ sudo apt-get install scrot

ウインドウを指定してスクリーンショットを撮るときは、
sオプションを付けて実行し、該当のウインドウをクリックする

$ scrot -s

以上でスクリーンショットを撮影することができる

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]:

Raspberianをインストール後にすること

Raspberry PiにRaspberianをインストール後、まずすること。普段からDebianを使っている人は違和感ないのかもしれないけど、RHEL系で生きているとDebian系の使い勝手が分からなくて苦しい。

ロケールの変更

ロケールを日本語に設定すると文字化けでうまく表示されないので、en_US.UTF-8.UTF-8のままでよいかも。

$ sudo dpkg-reconfigure locales

タイムゾーンの変更

タイムゾーンを東京に変更する。

$ sudo cp -p /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
$ sudo vi /etc/timezone
Asia/Tokyo

キーボードの設定

日本語キーボードに対応する。

$ sudo vi /etc/default.keyboard

# KEYBOARD CONFIGURATION FILE

# Consult the keyboard(5) manual page.

XKBMODEL="jp106"
XKBLAYOUT="jp"
XKBVARIANT=""
XKBOPTIONS=""

BACKSPACE="guess"

ランレベルの設定

デフォルトだとXWindowが立ち上がるが、これをランレベル3に変更する。

sudo systemctl set-default multi-user.target

固定IPアドレスを設定

Raspbrianのバージョンによって設定方法が異なる。

Raspbrian jessie

固定IPの設定は、/etc/network/interfacesではなく、/etc/dhcpcd.confに追記する。

$ sudo vi /etc/dhcpcd.conf

interface eth0
static ip_address=192.168.0.10/24
static routers=192.168.0.1
static domain_name_servers=192.168.0.1

以下のコマンドをいろいろ試したけど、新しい設定が全く反映されない。

$ sudo service dhcpcd restart
$ sudo service dhcpcd reload
$ sudo service dhcpcd force-reload
$ sudo service networking restart
$ sudo service ifup@eth0 restart
$ sudo systemctl restart dhcpcd
$ sudo systemctl restart networking
$ sudo systemctl restart ifup@eth0

仕方ないので端末再起動。

$ sudo reboot

Raspbrian wheezy

固定IPの設定は、/etc/network/interfacesに追記する。

$ sudo vi /etc/network/intefeces

インストール直後には、DHCP設定となっているので、固定アドレスとする場合は以下のように変更する。

auto lo

iface lo inet loopback
iface eth0 inet static

address 192.168.0.2
netmask 255.255.255.0
gateway 192.168.0.1

allow-hotplug wlan0
iface wlan0 inet manual
wpa-roam /etc/wpa_supplicant/wpa_supplicant.conf
iface default inet dhcp

無線LANの設定

Raspberry Piに無線LAN接続する場合は、以下の手順で行う。今回は、PLANEXのGW-USNANO2Aを使用した。

  1. Raspberry PiのUSBポートに挿入
  2. wpa_passphraseコマンドを、/etc/wpa_supplicant/wpa_supplicant.confに出力する
  3. /etc/wpa_supplicant/wpa_supplicant.confに、認証方式などの情報を追記する

WPA2-PSK(AES)の場合は、以下の通りとなる。

$ sudo wpa_passphrase SSID PASS_PHRASE >> /etc/wpa_supplicant/wpa_supplicant.conf
$ sudo vi /etc/wpa_supplicant/wpa_supplicant.conf

country=GB
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
network={
        ssid="SSID"
        #psk="PASS_PHRASE"
        psk=xxxxxxxxxxxxxxxxxxxxxxxxxxx
        proto=RSN
        key_mgmt=WPA-PSK
        pairwise=CCMP
        group=CCMP
}

無線LANインタフェースの状況を確認するためには、

iwconfig wlan0

識別できているSSIDの一覧を取得するためには、

iwlist wlan0 scan | grep SSID

                    ESSID:"guest"
                    ESSID:"test"
                    ESSID:""
                    ESSID:"free"
                    ESSID:""

以下のファイルも変更する。
wlan0インタフェースを自動起動設定とし、wlan1インタフェースの無効化している。

$ sudo vi /etc/network/interfaces

# interfaces(5) file used by ifup(8) and ifdown(8)

Please note that this file is written to be used with dhcpcd
For static IP, consult /etc/dhcpcd.conf and 'man dhcpcd.conf'

# Include files from /etc/network/interfaces.d:
source-directory /etc/network/interfaces.d

auto lo
iface lo inet loopback

iface eth0 inet manual

auto wlan0
allow-hotplug wlan0
iface wlan0 inet manual
     wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf
 
#allow-hotplug wlan1
#iface wlan1 inet manual
#    wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf

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

必要なパッケージをインストールする。

$ sudo apt-get install chkconfig
$ sudo apt-get install screen
$ sudo apt-get install apache2
$ sudo chkconfig ntp off
$ sudo chkconfig apache2 on

パッケージの更新もしておく。

$ sudo apt-get update
$ sudo apt-get upgrade
$ sudo rpi-update

プロキシ環境でapt-getを実行する場合は、以下のファイルを変更する。

$ sudo vi /etc/apt/apt.conf.d/10proxy

追記内容は以下の通り。

Acquire::http::Proxy "http://192.168.x.x:8080";

Vimの起動モードを変更

Viで矢印キーを押したときにABCDと出てしまう問題は、VimをVi互換モードではなく通常モードで起動することで直る。

~/.vimrcに設定を保存できる。sudoでvimを使うときのために/root/.vimrcにも追記しておく。

$ vi ~/.vimrc

:set nocompatible
:set backspace=indent,eol,start
:set number

~/.vimrcに書ける便利な設定がいろいろあるみたい。

設定 内容
:set nocompatible 通常モード起動
:set backspace=indent,eol,start バックスペースキーの挙動を指定
:set number 行番号を表示

もしくは、Vimのインストールでも直る。

$ sudo apt-get install vim