Edited at

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

More than 1 year has passed since last update.

前回記事→ 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が表示されます。

設定ファイルの作成。以下のコマンドを実行します。

[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を喋らせるめちゃ速レシピ