- 前回の記事: 「スクリプト をサービス登録するテンプレート [
init.d
編]」 @ Qiita
「お前もデーモン登録してやろうか」〜俺様スクリプトのデーモン化〜
この記事では、init.d
もしくは SystemD
に「自作スクリプト(アプリ)を登録し、サービスとして自動起動する」までの手順を記載しています。
前回の init.d
の登録の仕方の記事を読んで、SystemD
でも自作スクリプトやアプリをデーモナイズ(デーモン化/サービス化)したいと思われたら参考ください。また、念のため init.d
の登録方法についても言及しているため、若干前回と重複します。
🐒 本記事は Dasher の著者から許可をいただいたので、Wiki にある「Running Dasher on a Raspberry Pi at startup」を翻訳する予定でした。ところが、ちんたらしてたら Dasher の開発自体が終了してしまいました。そのため Dasher に特化しない汎用的な記事として新たに書き起こしましたが、本記事は同じ MIT ライセンスとします。また、追記/誤記/誤字などありましたら遠慮なく編集リクエストください。
- 参考文献:「Running Dasher on a Raspberry Pi at startup | Dasher」@ GitHub
init.d と SystemD の違い
init.d
(もしくは SystemV init
)の方が古く、SystemD
の方が新しい仕組みです。共通することを先に説明します。
共通点
基本的に init.d
の init
プログラム、SystemD
の systemd
プログラムは、どちらも OS が最初に起動するプログラムです。
そして、どちらも「デーモン」として常駐し、サービス(常駐アプリ)となるプログラムやスクリプトの「起動」「終了」「再起動」などを管理したり、他のプロセスを監視する点でも同じです。親となるプロセスの総本山とも言えるものです。
そのため、このプログラム自体が起動できないとカーネル・パニックを起こします。
読み違えやすいのが、この全ての親プロセスを管理するプログラムを INIT
システムと総称したりもすることです。つまり、SystemD
のことを INIT
システムと呼ぶことがあります。そのため init.d
の init
と間違えないように、init.d
を SystemV init
と明示することもあります。
また、どちらもサービスごとに「設定ファイル」を用意しておき、専用のディレクトリに設置します。その後、それらをサービス登録することでサービスとしての利用が可能になります。
「サービス登録」と言っても、登録コマンドを叩くと設置したファイルのシンボリック・リンクがサービス登録用のディレクトリに作られるだけです。そして init.d
もしくは systemd
は起動時に、そのシンボリックリンクを起動して行きます。
また、「サービスとしての利用」と言っても、OS 起動後の自動起動や、start
や stop
コマンドなどによる管理ができると言うだけです。
ぶっちゃけ「デーモン」と「サービス」どちらも同じものです。
プロセス(メモリ上で展開している処理)のうち、一度起動すると終了シグナルを受け取るまで、何かしらのサービスを提供しつづけるタイプです。
「デーモン」(daemon
)とは demon
(悪魔)の古語で、常に存在しているが姿が見えず、良くも悪くも振る舞う、超自然的な精霊のような存在のことです。
深く悩まずに、Linux や macOS など UNIX 寄りの表現がデーモン、Windows 寄りの表現がサービス程度の認識でいいと思います。
Linux の記事なので、正しくは「デーモン」で統一すべきなのですが、恐らくこの記事が必要なユーザーは Windows や macOS ユーザーが多いと思うので、把握しやすいように「サービス」という言い方をしています。
ここで言う「サービス」は、いわゆる「ただの常駐アプリ」ではなく、OS が起動でき、終了・再起動といったシグナルも受け取ることを前提とした常駐アプリを指します。
initd と systemd の違い
init.d
と SystemD
の一番の違いは、サービスごとに必要な「設定ファイル」の中身です。
init.d
の本体となる init
プログラム自体は、以下のシンプルな動作しか基本的にできません。
- OS 起動時に、登録されたサービスの設定ファイルを
start
の引数を付けて実行する。 - OS シャットダウン時にはサービスの設定ファイルを
stop
の引数を付けて実行する。
ここで注目して欲しいのが「実行する」の部分です。
設定ファイルなのに「実行する」と言うのも、実はinit.d
のサービス設定ファイルは「実質的にシェルのスクリプト」です。
init.d
の設定ファイルの内容を見るとわかりますが、起動・終了などの処理が、普通にシェル・スクリプトで start
stop
の引数によって俺様アプリの起動と kill
を実行していることが確認できます。
例)cron サービスの設定ファイルの場合
以下は RaspberryPi OS の cron
サービスの設定ファイルです。
ここでは詳しく見る必要はなく、スクリプト末尾にある case "$1" in
のセクションに注目してください。スクリプトの第 1 引数($1
)によって実行内容を変えているのがわかります。
#!/bin/sh
# Start/stop the cron daemon.
#
### BEGIN INIT INFO
# Provides: cron
# Required-Start: $remote_fs $syslog $time
# Required-Stop: $remote_fs $syslog $time
# Should-Start: $network $named slapd autofs ypbind nscd nslcd winbind sssd
# Should-Stop: $network $named slapd autofs ypbind nscd nslcd winbind sssd
# Default-Start: 2 3 4 5
# Default-Stop:
# Short-Description: Regular background program processing daemon
# Description: cron is a standard UNIX program that runs user-specified
# programs at periodic scheduled times. vixie cron adds a
# number of features to the basic UNIX cron, including better
# security and more powerful configuration options.
### END INIT INFO
PATH=/bin:/usr/bin:/sbin:/usr/sbin
DESC="cron daemon"
NAME=cron
DAEMON=/usr/sbin/cron
PIDFILE=/var/run/crond.pid
SCRIPTNAME=/etc/init.d/"$NAME"
test -f $DAEMON || exit 0
. /lib/lsb/init-functions
[ -r /etc/default/cron ] && . /etc/default/cron
# Read the system's locale and set cron's locale. This is only used for
# setting the charset of mails generated by cron. To provide locale
# information to tasks running under cron, see /etc/pam.d/cron.
#
# We read /etc/environment, but warn about locale information in
# there because it should be in /etc/default/locale.
parse_environment ()
{
for ENV_FILE in /etc/environment /etc/default/locale; do
[ -r "$ENV_FILE" ] || continue
[ -s "$ENV_FILE" ] || continue
for var in LANG LANGUAGE LC_ALL LC_CTYPE; do
value=`egrep "^${var}=" "$ENV_FILE" | tail -n1 | cut -d= -f2`
[ -n "$value" ] && eval export $var=$value
if [ -n "$value" ] && [ "$ENV_FILE" = /etc/environment ]; then
log_warning_msg "/etc/environment has been deprecated for locale information; use /etc/default/locale for $var=$value instead"
fi
done
done
# Get the timezone set.
if [ -z "$TZ" -a -e /etc/timezone ]; then
TZ=`cat /etc/timezone`
fi
}
# Parse the system's environment
if [ "$READ_ENV" = "yes" ] ; then
parse_environment
fi
case "$1" in
start) log_daemon_msg "Starting periodic command scheduler" "cron"
start_daemon -p $PIDFILE $DAEMON $EXTRA_OPTS
log_end_msg $?
;;
stop) log_daemon_msg "Stopping periodic command scheduler" "cron"
killproc -p $PIDFILE $DAEMON
RETVAL=$?
[ $RETVAL -eq 0 ] && [ -e "$PIDFILE" ] && rm -f $PIDFILE
log_end_msg $RETVAL
;;
restart) log_daemon_msg "Restarting periodic command scheduler" "cron"
$0 stop
$0 start
;;
reload|force-reload) log_daemon_msg "Reloading configuration files for periodic command scheduler" "cron"
# cron reloads automatically
log_end_msg 0
;;
status)
status_of_proc -p $PIDFILE $DAEMON $NAME && exit 0 || exit $?
;;
*) log_action_msg "Usage: /etc/init.d/cron {start|stop|status|restart|reload|force-reload}"
exit 2
;;
esac
exit 0
このように、init.d
の設定ファイルはスクリプトであるため、挙動を柔軟に制御できる反面、スクリプトに問題があっても気付きにくいなど、いささか複雑です。しかも、下手するとカーネル・パニックを起こします。
対して、SystemD
の設定ファイルの場合は、設定のみが記載されたファイルです。
起動(start
)・終了(stop
)などの処理は、本体である systemd
に組み込まれているため、設定ファイルはサービスの起動に必要な情報だけで済みます。
つまり、SystemD
のサービス設定ファイルは、本当の意味で「設定だけのファイル」です。スクリプトよりは自由度は低いものの、記載がシンプルなぶん、安定した柔軟性があるという違いがあります。
例)sshd サービスの設定ファイルの場合
以下は RaspberryPi OS の sshd
サービスの設定ファイルです。
ここでは何をしているかよりも、パラメーターしか設定していないことに注目です。
[Unit]
Description=OpenBSD Secure Shell server
Documentation=man:sshd(8) man:sshd_config(5)
After=network.target auditd.service
ConditionPathExists=!/etc/ssh/sshd_not_to_be_run
[Service]
EnvironmentFile=-/etc/default/ssh
ExecStartPre=/usr/sbin/sshd -t
ExecStart=/usr/sbin/sshd -D $SSHD_OPTS
ExecReload=/usr/sbin/sshd -t
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure
RestartPreventExitStatus=255
Type=notify
RuntimeDirectory=sshd
RuntimeDirectoryMode=0755
[Install]
WantedBy=multi-user.target
Alias=sshd.service
実は、SystemD はプロセス管理以上の処理(プロセス間通信、ログインやネットワークの起動時処理など)も担えます。そのため、ユーザ・メリットが多くデフォルトの INIT
(最上位プロセス)システムとして SystemD
を採用しているディストロは多いです。
しかし init.d
(SystemV init
)に比べて SystemD
は多機能な反面、依存も多いので「1 つのことを行い、またそれをうまくやるプログラム」という Unix 哲学に反するとして init.d
系(SystemV init
系)を好むディストロも多くあります。
特に、使い勝手(多機能性や利便性)より、堅牢性を重視したディストロ(例えば Alpine Linux など)では OpenRC という、シンプル・軽量かつ堅牢な INIT
を採用していたりします。そのぶん SystemD
が担っていた処理を手前で行う必要があるため、より Linux の知識を必要とします。
とは言え、この違いは「良い」「悪い」ではなくポリシーの問題です。
かく言う Alpine Linux も、BusyBox という cd
や ls
などの本来個別である基本コマンドを 1 つのプログラムで動かせるようにしています。ロード時間のオーバーヘッド(読み込み回数の短縮)をカバーするものの、同様に「Unix 哲学うんぬん」と反発する人も多いです。
結局のところ、自分の好みにあったディストロが、どの INIT
システムを採用しているかを把握して、まずは使ってみるのがベストだと思います。
init.d
or SystemD
どちらのデーモンがメインに利用されているか確認したい場合、1番目のプロセス ID を確認するのが簡単です。
$ ps auxq 1
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.6 28208 6044 ? Ss 3月31 31:13 /sbin/init
上記の場合、/sbin/init
が PID 1 で実行されているため一般的には init.d
が使われていることになります。
しかし、OS によって注意する必要があります。RaspberryPi OS(旧 Raspbian)などの Debian/Ubuntu 系の一部の OS では両方が使われていることがあるからです。
RaspberryPi OS で具体的に確認してみてみましょう。
まずは、先の ps auxq 1
コマンドで確認した 1 番プロセス(PID 1
)の実行プログラム init
の確認です。
init
の本体のパスである /sbin/init
のファイルの詳細を ls -l
で見てみます。
シンボリック・リンクで、本体は別であることに注目です。
$ # PID1をPSコマンドで確認
$ ps auxq 1
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.6 28208 6044 ? Ss 3月31 31:13 /sbin/init
$ # init は systemd のシンボリック・リンクになっている
$ ls -l /sbin/init
lrwxrwxrwx 1 root root 20 7月 22 2019 /sbin/init -> /lib/systemd/systemd
このように、/sbin/init
の実体は /lib/systemd/systemd
なのがわかります。
つまり「init
と言いながら systemd
が動いている」と言うことです。この場合、OS は init.d
を呼び出す(実行する)も実質的に systemd
に処理を任せることになります。
この init
の皮をかぶった systemd
ですが、まず init.d
向けのサービスを替わりに起動します。次に、SystemD
向けのサービスを起動することになります。そのため、このような systemd
が init
を兼任して両方が使える OS があるので注意します。
逆に言えば、この仕組み(init.d
systemd
併用)の場合は、どちらのサービス設定ファイルを設置しても動くと言うことです。
どちらも使える OS の場合に、どちらの設定ファイルのサービスにしようか悩んだら、「起動するだけで十分」なら SystemD
、「起動前後にゴニョゴニョと処理をしたい」なら init.d
が良いと思います。
- 「init」@ Wikipedia /「systemd」@ Wikipedia
- 「What is the difference between /etc/init/ and /etc/init.d/? | Ask Ubuntu」@ StackExchange
俺様アプリの用意
init.d
にせよ SystemD
にせよ、まずは対象となる俺様アプリ(実行ファイルもしくはスクリプト)を事前に用意する必要があります。
🐒 本記事は「スクリプトをサービス(デーモン)として常駐させる」ことを目的としています。そのため、起動時に1回だけ実行させたいのであれば crond
にスクリプトを登録(crontab
に @reboot /path/to/myScript.py
などと記載)したほうが楽だと思います。一回きりの起動であれば、Raspbian/Debian ですが下記記事が参考になります。
他のサービス同様に「start
」や「stop
」(/etc/init.d/myService start
や /etc/init.d/myService stop
)などで起動・終了できるようにしたい場合は、本記事を参考にしてください。
俺様サービス作成時の注意事項
俺様サービスを Linux で作りたい場合、プログラム言語は問いません。つまり Bash でも PHP でも Go でも Python でも俺様サービスを作ることは可能です。
しかし、最低限以下の点を網羅する必要があります。
- コマンドラインから呼び出し/実行できる状態であること。
- プログラムは、呼び出されると中断シグナルを受け取るまで常駐(実行)すること。
- メモリの割り当てに注意すること。
まずは、1 の「呼び出し/実行できる状態」とは、ターミナルやコマンドラインから叩けば無限ループで実行される状態ということです。
$ python /path/to/myScript.py
$ php /path/to/myScript.php
$ ./path/to/myGoApp
などです。shebang
2 を付けて $ /path/to/myScript.rb
などと直接起動できるタイプでもかまいません。、コマンドを叩くと起動できるようになっているということです。
そして 2 番目の「呼び出されると常駐する」とは、実行されたら処理を終了させないようにループなどで継続させる必要があるということです。Web サービスのアプリなどがわかりやすいでしょうか。
最後の「メモリの割り当てに注意」とは、使用メモリが無駄に肥大化しないように注意して設計する、ということです。プログラムの組み方やプログラム言語にも依存するのですが。
例えば、ループ内でメモリを新規確保し続けないなどです。メモリがどんどん肥大化していくからです。
また、カウンターなど永遠とカウントアップさせていて、気付いたら(変数が)とんでもない数値になっていた、みたいなことにならないように注意します。
【注意点】
プロセスを終了させないことで常駐させるには、基本的に while(true){}
などの無限ループでスクリプトが終了しないようにすると思います。
この時、注意すべき基本が2つあります。
- 終了/中断シグナルの監視を忘れない
-
sleep
を入れることも検討する
通常、無限ループのスクリプトを強制終了させるには Ctrl+C
などの SIGINT
(2番シグナル)がスクリプトのプロセスに送られます。
しかし、OS の再起動時、シャットダウン時もしくは手動によるサービス停止などの場合に意図しないシグナルが送られることがあるので注意します。
例えば、サービスが停止されると kill <サービスの PID>
コマンドの SIGTERM
(15番シグナル)や SIGKILL
(9番シグナル)が実行中のスクリプトに送信されます。
そのため、ループ内での「終了シグナルの検知処理」などにも注意する必要があります。
特に、PHP の register_shutdown_function()
や Golang の defer
などの終了時に実行される関数は、SIGINT
や SIGTERM
による終了の場合、発火(実行)されません。ループ内でシグナルをチェックする必要があります。
この処理を意識しないと、ちゃんとシャットダウン・コマンドを実行して再起動しているのに、スクリプトからみると「急に PC の電源を引っこ抜かれた」時と同じ状態になります。「ファイルを閉じる」や「別プロセスを終了させる」などの処理が必要な場合は特に注意です。
その場合、例えば PHP の場合はプロセスのシグナルを検知・コントロールする pcntl_signal
を使う、などの工夫が必要です。
他にも注意しておく点として、sleep
があります。
ループ内で処理が発生しない場合、すぐに continue
をせずに sleep
などのクッションを入れることも検討してください。
while(true) {
if (isSomething() === false) {
continue; // ここで超高速な無限ループが発生しているため、他のプロセスが割り込む余地がない
}
doSomething();
}
上記のように、入力や状態監視をする際に、ループが高速すぎるため CPU 負荷が上がってしまうことがあります。
この場合、sleep
を一瞬でも入れることで、かなり CPU 負荷が減ります。
while(true) {
if (isSomething() === false) {
+ usleep(20000);
continue;
}
doSomething();
}
- 関連情報
- 「終了シグナル 受け取り SIGTERM」の Qiita 記事検索 @ Google
- Docker で CPU 使用率 100% のコンテナを軽減・回避する @ Qiita
登録したいプログラム/スクリプトを用意した次に必要なのが、そのスクリプトをサービスとして登録するための設定ファイルの作成とインストール(設定ファイルの適用)です。
init.d で起動時に任意のスクリプトをサービス実行する
RaspberryPi(Raspbian Jessie)などの System V 系の init
で登録する場合は、本項をご覧ください。SystemD
で登録したい場合は次項で説明しています。
サービス設定ファイル「init スクリプト」
init
のサービス用設定ファイルと言っても、前述したように実態は sh
などの shebang
付きのシェル・スクリプトです。
その設定ファイル(スクリプト)が実行される際に start
引数が付いていたら自分のプログラム(登録したプログラム/スクリプト)を起動し、stop
引数が付いていたらプロセスを探して終了させるだけのスクリプトです。意外に力技な仕組みなのです。
普通のシェル・スクリプトとの違いは、呼び出し元の init
プログラムに準拠したヘッダー情報(コメント行)および必須機能を含んでいることです。以降は、このサービス用設定ファイルを init
スクリプトと呼びます。
インストールは、必要事項を記載した init
スクリプトを /etc/init.d/
に設置し、登録コマンド update-rc.d
を実行することで行われます。
「登録コマンド」と言っても、具体的には /etc/rc[0-9S].d/
のディレクトリ内にエイリアス(シンボリック・リンク)を張るだけです。そして、init
プログラムが起動すると /etc/rc[0-9S].d/
にあるファイルを順番に実行して行きます。
init
スクリプト(サービス設定ファイル)は、他のサービスを参考にしても良いのですが、Felix H. Dahlke 氏 が GitHub で無償で提供しているテンプレートを使うと便利です。気に入ったら「いいね(「★Star」)」してあげてください。
なお、このテンプレートの使い方の詳細は前述の「スクリプト をサービス登録するテンプレート[init.d編]」@ Qiita をご覧ください。
Dasher
を init.d
でサービス登録する例
それでは init.d
に登録する例として、dasher
3 というコマンド・アプリをラズパイの init.d
にサービスとして登録したいと思います。
何度か言及していますが、起動したら Ctrl+C
の押下もしくはプロセスを kill
するまで動き続けるスクリプト or アプリであれば、プログラム言語問わず何でも登録可能です。dasher
を自身のスクリプト名に置き換えてお読みください。(詳しくは上記の「スクリプト作成時の注意点」をご覧ください。)
- テンプレートの生データを開き全体をコピーする。
- ラズパイ上の
/etc/init.d/
ディレクトリ内にファイルを作成する。(ファイル名はサービス名と同じにします。今回はdasher
) -
sudo
権限でファイルを開きペーストします。(nano
でもvim
でも可)
$ # ラズパイに SSH 接続する
$ ssh pi@raspberrypi.local
$
$ # sudo 権限でテキスト・エディタを開き dasher ファイルにコピー内容をペースト
$ sudo nano /etc/init.d/dasher
[クリップボードの内容を貼り付ける]
次に、ファイルの先頭にあるヘッダー情報を変更する必要があります。以下が一例です。
#!/bin/sh
### BEGIN INIT INFO
# Provides: dasher
# Required-Start: $network $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Start dasher daemon at boot time
# Description: Enable daemon service
### END INIT INFO
dir="/home/pi/dasher"
cmd="npm run start"
user="root"
dir
の項目に注目ください。これは、作業ディレクトリを dir
に変更します。ここでは Dasher
の本体が /home/pi/dasher/
ディレクトリに設置 or インストール済みであることを前提としています。
cmd
は実際の実行コマンドで、user
は実行するユーザーです。
セキュリティの問題で root
以外のユーザーに設定することもできますが、ユーザーの環境変数は読み込まないことに注意します。つまり、実行ユーザーの環境変数に追加したパスなども通っていないので、絶対パスで指定するか、実行スクリプト内で読み込む必要があります。
さて、今回使ったエディタは nano
であるため、保存するには CTRL + o
と入力してから Enter
を押し、CTRL + x
でエディタを終了します。
次に、ファイルのパーミッションを変更してスクリプトを 「インストール」(登録)します。
$ sudo chmod 755 /etc/init.d/dasher
$ sudo update-rc.d dasher defaults
以上でラズパイが再起動したときに実行されるはずです。他にも以下ように手動で起動することもできます。
$ sudo /etc/init.d/dasher start
実行中のログを表示するには、ログやエラーファイルを開いて確認します。ログはファイルの末尾に追加されていくので、最新のログを確認したい場合は tail
コマンドで出力ログまたはエラーログを表示します。
$ tail -f /var/log/dasher.log
$ tail -f /var/log/dasher.err
SystemD で起動時に任意のスクリプトをサービス実行する
init.d
同様に、SystemD
でサービス登録する場合も登録用の「SystemD Unit ファイル」の作成が必要です。
同じく、例として dasher
3 というコマンド・アプリをサービスとして登録したいと思います。
-
下記 Unit ファイルのサンプルをコピーする。
SystemDのサービス登録用のテンプレート(Unitファイル)[Unit] Description=Dasher After=network.target [Service] Type=simple # dasher のファイルにアクセスするユーザー User=root # dasher の本体および作業ディレクトリ WorkingDirectory=/home/pi/dasher # "which npm"コマンドで NPM の絶対パスを確認します ExecStart=/usr/local/bin/npm run start [Install] WantedBy=multi-user.target
-
ラズパイ上の
/etc/systemd/system/
ディレクトリ内に任意の<サービス名>.service
のファイルを作成します。(今回はdasher.service
) -
sudo
権限でファイルを開きペーストします。(nano
でもvim
でも可)ファイルの作成とエディタを開く$ # ラズパイに SSH 接続する $ ssh pi@raspberrypi.local $ $ # sudo 権限でテキスト・エディタを開き dasher.service ファイルにコピー内容をペースト $ sudo nano /etc/systemd/system/dasher.service [クリップボードの内容を貼り付ける]
今回使ったエディタは
nano
であるため、保存するにはCTRL + o
と入力してからEnter
を押し、CTRL + x
でエディタを終了します。 -
登録した Unit の再読み込み、自動起動設定および手動起動を行います。
$ sudo systemctl --system daemon-reload $ sudo systemctl enable dasher $ sudo systemctl start dasher
以上でサービスは起動し、再起動時にも起動するはずです。
すべての設定が正しく機能しているかどうかを確認するには、次のコマンドを使用します。
$ sudo systemctl status dasher
$ sudo journalctl -f -u dasher
-
【フォローアップ(Follow-up)とは】前回の不足分を補うための続報・追跡・追求・補足をすること。 ↩
-
【shebang(シバンまたはシェバン)とは】UNIX/linux のスクリプトの
#!
から始まる1行目のこと。スクリプトの実行に必要なインタプリタを指定します。shebang
なしの場合の呼び出しは「$ php /path/to/myScript.php
」となりインタプリタを指定する必要がありますが、shebang
ありの場合(スクリプト内の1行目に#!/usr/bin/env php
の記載がある場合)の呼び出しは「$ /path/to/myScript.php
」とインタプリタの指定が不要になります。環境変数のパスに指定されたディレクトリに設置されたスクリプトは、スクリプト名の指定だけ(パスの指定なし)で実行するためには必須でもあります。 ↩ -
【Dasher とは】ネットワークを監視し、特定の MAC アドレス(物理アドレス)からのブロードキャスト信号を検知すると、Web Hook を叩く(任意の URL にアクセスする) Node.js ベースのアプリケーションのこと。市販の Amazon Dash Button(ADB)を合法な状態(物理的なクラッキングをせずに) IoT のトリガー(ボタン)として使えるようにしたパイオニア的アプリケーションです。現在は開発を終了しており、後継ではないものの Python ベースの「Nekmo/amazon-dash」の利用が推奨されています。 ↩ ↩2