Node.js
RaspberryPi
ngrok
IoT

【Node.js】 RaspberryPiのプログラムを自動起動・永続化・SSH ログアウト後もプロセスを残す

前回記事→ LINE BOTでラズパイから部屋の温度を教えてもらう【Push API】【Node.js】

現状と課題

  • ラズパイにはMacからwifiでSSH接続している
  • SSH接続が切れる・Macがスリープするとプログラムも止まってしまう
    • Botが使えなくなる

要件

  • Nodeのプログラムを自動起動&永続化させる
  • RaspberryPiをサーバーに常時接続させる(ngrokの永続化)

ngrok(トンネリングツール)については→ ngrokでトンネリング

作業概要

  1. Foreverをインストールし、プログラムを自動起動&永続化
  2. 無線LANの省電力機能をオフ
  3. ngrokがタイムアウトしないようにする
  4. ngrokの永続化(screen コマンドの利用)

1. Foreverをインストールし、プログラムを自動起動&永続化

Raspberry Piにはプログラムを自動起動する方法がたくさんある

  • /etc/rc.local
  • autostart
  • crontab
  • /etc/init.d
  • systemd

など・・
参照記事 Raspberry Piでプログラムを自動起動する5種類の方法を比較・解説

今回はNodeのプログラムなので、foreverを利用します。
foreverとは、nodeをデーモンとして動かすためのモジュール。バックグラウンドでnodeを動作させるためにインストールします。

デーモン (英語: Daemon) は、UNIX, Linux, MacOSXなどUnix系ののマルチタスクオペレーティングシステム (OS) において動作するプロセス(プログラム)で、主にバックグラウンドで動作するプロセス。- Wikipedia

foreverのインストール
グローバルオプションをつけてインストールします。

$ sudo npm install -g forever

foreverのパスを確認

$ which forever

(例)もちさんの場合

/usr/local/nvm/versions/node/v10.0.0/bin/forever

/etc/rc.localを編集
rc.localはRaspberry Pi起動時に管理者権限で実行されるファイルです

$ sudo nano /etc/rc.local

下記のようなファイルです

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

exit 0

ファイル末尾「exit 0」の手前に起動時に実行したいプログラムを指定する

$ sudo -u [ユーザ名] [nodeのパス] [forever のパス] start -a -d [動かしたいスクリプトのパス]

rc.local
_IP=$(hostname -I) || true
if [ "$_IP" ]; then
  printf "My IP address is %s\n" "$_IP"
fi

sudo -u username /usr/local/nvm/versions/node/v10.0.0/bin/node /usr/local/nvm/versions/node/v10.0.0/bin/forever start -a -d /home/username/workspace/mylinebot/server.js

exit 0

正しく実行されるか確認

$ sudo /etc/rc.local

info:Forever processing file: 動かしたいスクリプトのパスと出たら成功!

$ sudo /etc/rc.local
My IP address is 192.000.0.0 000.00.00.00 
warn:    --minUptime not set. Defaulting to: 1000ms
warn:    --spinSleepTime not set. Your script will exit if it does not stay up for at least 1000ms
info:    Forever processing file: /home/username/workspace/mylinebot/server.js

Raspberry Piを再起動する

$ sudo reboot

再度ラズパイに接続し、サービスが起動しているか確認しましょう

Foreverのプロセスを確認するコマンド

$ forever list

失敗だと

$ forever list
info:    No forever processes running

成功

$ forever list
info:    Forever processes running
data:        uid  command                                       script                                     forever pid id logfile                        uptime       
data:    [0] f70E /usr/local/nvm/versions/node/v10.0.0/bin/node /home/username/workspace/mylinebot/server.js 770     941    /home/username/.forever/f70E.log 0:0:0:46.495 

参照記事 ラズパイ再起動時にNode.jsアプリを自動起動する

2. 無線LANの省電力機能をオフ

/etc/rc.localに以下を追記する

iwconfig wlan0 power off

無線LANの省電力機能の状態確認。 Power save: offと表示されたらOK

$ iw dev wlan0 get power_save
Power save: off

Raspberry Piを再起動、再接続し、状態確認しましょう

3. ngrokがタイムアウトしないようにする

ngrokは一定の時間が立つと、接続を解除してしまいます。
ngrokで無料のアカウントを作成し設定ファイルを作成すれば、時間がたってもトンネルが解除されなくなります。

ngrokでアカウントを作成 https://ngrok.com/

作成したアカウントでngrokのwebページへログインするとConnect your accoutというところにauthtokenが表示されます。
authtoken.png

設定ファイルの作成。以下のコマンドを実行します。
[ngrokのパス] authtoken [自分のアカウント用Authtoken]

$ ngrok authtoken XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

設定ファイルが、~/.ngrok2/ngrok.yml に作成されます。これでタイムアウトはなくなります!

$ ngrok authtoken XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Authtoken saved to configuration file: /root/.ngrok2/ngrok.yml

4. ngrokの永続化(screen コマンドの利用)

ngrok(トンネリングサーバー)を常時起動させてラズパイをグローバルに接続しっぱなしにしましょう

Linux では仮想端末を作成するscreenというコマンドがあります。
「SSH をログアウトしても仮想端末を残す」ことで、仮想端末上にプロセスを残すことができます。

参照記事 Raspberry pi で SSH ログアウト後もプロセスを残したい

インストール

$ sudo apt-get install screen

プロセスを残す

screen を起動

$ screen

ngrokを起動

$ ngrok http 3000(任意のポート)

ngrokのURLを確認。
Ctrl + A、Ctrl + Dで仮想端末からデタッチ(抜け出す)。デタッチ後もプロセスは残り続けます。
デタッチできたら以下のようなメッセージが出ます

[detached from 17974.pts-0.raspberrypi]

仮想端末の確認

$ screen -list

数字(この場合17974)がプロセス番号です

$ screen -list
There is a screen on:
    17974.pts-0.raspberrypimochi    (2018年06月22日 11時26分49秒) (Detached)
1 Socket in /var/run/screen/S-user.

仮想端末にアタッチ(再接続)したい時は

$ screen -r [プロセス番号]

# もし、セッションが1つだけの時は
$ screen -r

参照 screenコマンドの要点

完了です!
前回記事・LINE BOTで利用する場合は、このngrokのURLをLINE DevelopersのWebHookURLに登録すれば、常時BOTが使用できるようになります。

課題

  • サーバーを起動しなおしたり、RaspberryPiの再起動が発生したとき、ngrokのURLが変わってしまう
    • 有料アカウントにすれば固定ドメインが利用可能
    • とりあえず今は保留

参照記事
google-home-notifier周りをほぼ自動化した
10分でSlackからGoogleHomeを喋らせるめちゃ速レシピ