/etc/rc.localを使ったRaspberry Piのプログラムの自動起動

Raspberry Piにはプログラムを自動起動する方法がいろいろありますが、今回は、「/etc/rc.local」を使ってRaspberry Piのプログラムを自動起動します。Raspberry PiのOSは、「2018-04-18-raspbian-stretch」を使用します。

/etc/rc.localを使った自動起動(基本的な説明)

「/etc/rc.local」を使ってプログラムを起動するには、次のviコマンドでroot権限で「/etc/rc.local」を開き、すでに記述されている「exit 0」の前に、プログラムを実行するコマンドをフルパスで記述します。

$ sudo vi /etc/rc.local

コマンドにより記述が終了すると再起動します。これにより記述されたプログラムがroot権限を持って起動されます。うまくプログラムが起動しない時は、次のチェックを行います。

  • プログラムはフルパスで記述します。
  • ファイルのアクセスについてもプルパスで行います。
  • ファイルのアクセス権限をroot権限でもアクセスできるようにします。

「sudo raspi-config」した上で”Wait for Network at Boot” -> ” Slow Wait for network connection before completing boot”をチェックすると、システムの起動の際、ネットワークに接続されるまで待機するようになります。ただし起動が遅くなります。

ソケット通信を行うPythonスクリプトを自動起動(自動起動実施例)

自動起動用のPythonスクリプト「testserver.py」を次の仕様で作成し、「/etc/rc.local」に登録して自動起動します。

  • TCPポート「50000」を使ってソケット通信を行うサーバプログラムを作成します。
  • クライアントからデータを受け取ると、折り返しそのデータをクライアントに送信します。
  • 起動時に現在時刻をログ「log/text.txt」に出力する。また、クライアントからのアクセスがあると、クライアントのアドレスと受信したデータをログ「log/text.txt」に出力します。
  • syslog.syslogメソッドを利用して、「/var/log/syslog」にログを出力する。

作成した「testserver.py」を次に示します。

#!/usr/bin/env python3

# socket サーバを作成
import socket 
import datetime
import syslog

f = open('/home/pi/startuptest/log/text.txt', mode='a') # 書き込みモードで開く
f.write(datetime.datetime.now().strftime("%Y/%m/%d %H:%M:%S")+"\n") # シーケンスが引数。
f.close()
syslog.syslog('syslog test:'+datetime.datetime.now().strftime("%Y/%m/%d %H:%M:%S")+"\n")

# AF = IPv4 という意味
# TCP/IP の場合は、SOCK_STREAM を使う
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    # IPアドレスとポートを指定
    s.bind(('192.168.10.6', 50000))
    # 1 接続
    s.listen(1)
    # connection するまで待つ
    while True:
        # 誰かがアクセスしてきたら、コネクションとアドレスを入れる
        conn, addr = s.accept()
        with conn:
            while True:
                # データを受け取る
                data = conn.recv(1024)
                if not data:
                    break
                f = open('/home/pi/startuptest/log/text.txt', mode='a') # 書き込みモードで開く
                f.write("data : {}, addr: {}".format(data, addr)+"\n") # シーケンスが引数。
                f.close()

                conn.sendall(b'Received: ' + data)

クライアント側のPythonスクリプト「testclient.py」を次に示します。

# クライアントを作成
import socket

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    # サーバを指定
    s.connect(('192.168.10.6', 50000))
    # サーバにメッセージを送る
    s.sendall(b'hello')
    # ネットワークのバッファサイズは1024。サーバからの文字列を取得する
    data = s.recv(1024)
    #
    print(repr(data))

「/etc/rc.local」の内容を次に示します。python3による「testserver.py」の起動コマンドを記述しています。「echo “I do nothing.”」により、「I do nothing.」が、起動時に「/var/log/boot.log」に出力されます。

$ cat /etc/rc.local
#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.

# Print the IP address
_IP=$(hostname -I) || true
if [ "$_IP" ]; then
  printf "My IP address is %s\n" "$_IP"
fi
echo "I do nothing."
/usr/bin/python3 /home/pi/startuptest/testserver.py &
exit 0

各プログラムとログフォルダのパーミッションと所有者を次に示します。

$ ls -all
合計 20
drwxr-xr-x  3 pi pi 4096  7月 22 19:01 .
drwxr-xr-x 29 pi pi 4096  7月 22 19:05 ..
drwxrwxrwx  2 pi pi 4096  7月 22 19:05 log
-rw-r--r--  1 pi pi  404  7月 22 19:01 testclient.py
-rw-r--r--  1 pi pi 1177  7月 22 19:01 testserver.py

ログフォルダ内のパーミッションと所有者を次に示します。ログファイル「text.txt」の所有者がrootになっています。

$ ls -all
合計 12
drwxrwxrwx 2 pi   pi   4096  7月 22 19:05 .
drwxr-xr-x 3 pi   pi   4096  7月 22 19:01 ..
-rw-r--r-- 1 root root   67  7月 22 19:07 text.txt

次のコマンドでTCPポート「50000」のサーバが立ち上がっているかを確認します。

$ sudo lsof -i
    ・・・
python3    517  root    3u  IPv4  13584      0t0  TCP 192.168.10.6:50000 (LISTEN)
    ・・・
    ・・・

次のコマンドでプロセスを確認します。

$ ps -aux
    ・・・
root       510  0.3  0.8  11632  8048 ?        S    17:36   0:00 /usr/bin/python3 /home/pi/startuptest/testserver.py
    ・・・
    ・・・

次のコマンドであらかじめ作成したクライアントスクリプト「testclient.py」を実行します。クライアントから送信したデータがエコーバックされています。

$ python3 testclient.py
b'Received: hello'

ログファイル「text.txt」を確認します。

2018/07/22 19:05:55
data : b’hello’, addr: (‘192.168.10.6′, 54912)
data : b’hello’, addr: (‘192.168.10.6′, 54914)
2018/07/22 20:13:31
data : b’hello’, addr: (‘192.168.10.6’, 42674)
2018/07/23 11:31:02

「/var/log/syslog」には次の内容がログされています。

    ・・・
Jul 23 18:27:29 raspberrypi /testserver.py: syslog test:2018/07/23 18:27:29
    ・・・
    ・・・