Slide 1

Slide 1 text

Nerves tips, /bin/sh & nerves_heart 2022/06/16 NervesJP #26

Slide 2

Slide 2 text

/bin/sh ● erlinit.config を使用することで、 Erlang VM の起動前後等で linux コマンド(ex. /bin/sh)を実行できる ● What’s erlinit ? ○ This is a replacement for /sbin/init that launches an Erlang/OTP release. ■ /sbin/init ? ● 他のプロセスを起動・管理する役割を持つ PID 1 の特別なプロセス ● What’s erlinit.config ? ○ erlinit の config ○ Where is erlinit.config on Nerves? ■ /etc/erlinit.config ● Let’s 論よりRUN ○ iex) cmd “ps -wlT” ○ iex) cmd “cat /etc/erlinit.config”

Slide 3

Slide 3 text

erlinit.config でできること ● ドキュメントを読もう! ○ https://github.com/nerves-project/erlinit#configuration-and-command-line-options ● Shell を起動するには? 以下が使えそう! ○ --pre-run-exec Run the specified command before Erlang starts ○ --run-on-exit Run the specified command on exit.

Slide 4

Slide 4 text

erlinit.config の設定方法は二通り 1. Overriding erlinit.config from Mix Config ○ config :nerves, erlinit: [hostname_pattern: "nerves-%s"] のリストに設定を追加 ○ This can be helpful when you want to alter a couple options without having to maintain a copy of the entire erlinit.config from the system. 2. Overwriting Files in the Root Filesystem ○ rootfs_overlay で、/etc/erlinit.config をまるっと上書きする ○ コピー元: deps/nerves_system_rpi4/rootfs_overlay/etc/erlinit.config ● 注意点: 両方同時には使えない! 理由は、やれば分かるので Let’s 論よりRUN

Slide 5

Slide 5 text

--pre-run-exec で /bin/sh を起動する ● rootfs_overlay/etc/erlinit.config の --pre-run-exec を ○ 変更前) --pre-run-exec /usr/sbin/rngd ○ 変更後) --pre-run-exec /bin/sh ; /usr/sbin/rngd ここからは、Linux の起動ログが見れたほうが状況が分かりやすいので、 Overwriting Files in the Boot Partition を利用して cmdline の quiet を外します。

Slide 6

Slide 6 text

--run-on-exit で /bin/sh を起動する(? ● rootfs_overlay/etc/erlinit.config の --run-on-exit を ○ 変更前) #--run-on-exit /bin/sh ○ 変更後) --run-on-exit /bin/sh そもそも --run-on-exit の “exit” ってどうする? ● :init.stop() ● exit() からの JCL Mode の quit

Slide 7

Slide 7 text

tty iex を “exit” する ● :init.stop(), same as :init.stop(0) ○ All applications are taken down smoothly, all code is unloaded, and all ports are closed before the system terminates by calling halt(Status). If command-line flag -heart was specified, the heart program is terminated before the Erlang node terminates. ● exit() ○ Exit the current IEx session ● Let’s 論よりRUN

Slide 8

Slide 8 text

tty iex で exit/0 すると Erlang の JCL Mode(Job Control Mode) に入る ● https://www.erlang.org/doc/man/shell.html#jcl-mode ● https://www.ymotongpoo.com/works/lyse-ja/ja/02_starting_out.html#id2 “quit erlang” すると Erlang VM が終了する。

Slide 9

Slide 9 text

どうなった? ● :init.stop すると ○ heart プロセスも terminate するので、ハードウェアウォッチドッグが Linux を reboot する ■ nerves_heart は nerves_system_br で Buildroot のパッケージとして取り込まれている の で、HW ウォッチドッグがあれば動作している(はず ● 使用されるHW ウォッチドッグ のデフォルトパスは /dev/watchdog0 ● exit から の JCL の quitをすると ○ heart プロセスが Erlang VM の 終了を検知してリブートする ■ see. https://github.com/nerves-project/nerves_heart/blob/ef5c20d7e939d52c1e81a0cd4 dfdfcf88515a961/src/heart.c#L444-L451 ● case では R_CLOSED が該当する heart プロセスとHW ウォッチドッグを止めることができれば、 --run-on-exit でも /bin/sh を起動できそう?

Slide 10

Slide 10 text

watchdog? heart?

Slide 11

Slide 11 text

watchdog ● Linux の仕組み ○ https://www.kernel.org/doc/html/latest/watchdog/watchdog-api.html#the-linux-watchdog -driver-api ○ A Watchdog Timer (WDT) is a hardware circuit that can reset the computer system in case of a software fault. You probably knew that already. ○ ソフトウェアの死活監視(?)検知(?)機能 ● 試してみよう!! ○ echo ‘’ > /dev/watchdog0 で起こす ■ 起こした後は定期的(タイムアウトする前に)になでてやらないとブチギレ発生 ■ タイムアウトは ○ echo ‘V’ > /dev/watchdog0 で寝かす

Slide 12

Slide 12 text

watchdog が寝かせられない!! ● Watchdog には Magic Close feature があり、 echo ‘V’ > [watchdog path]で止めることができます。 ● が、Nerves では無理です。 ○ > [ 180.633094] watchdog: watchdog0: nowayout prevents watchdog being stopped! ○ > [ 180.640316] watchdog: watchdog0: watchdog did not stop! これは CONFIG_WATCHDOG_NOWAYOUT=y としているから。

Slide 13

Slide 13 text

Erlang heart This modules contains the interface to the heart process. heart sends periodic heartbeats to an external port program, which is also named heart. The purpose of the heart port program is to check that the Erlang runtime system it is supervising is still running. If the port program has not received any heartbeats within HEART_BEAT_TIMEOUT seconds (defaults to 60 seconds), the system can be rebooted. Erlang VM Linux heart heartbeats 生きてる?もし、死んだ ら cmd しよう! Erlang VM の死活監視の仕組み $ erl -heart #別シェルで、確認できる $ ps auxw | grep heart

Slide 14

Slide 14 text

nerves_heart This is a replacement for Erlang's heart port process specifically for Nerves-based devices. Erlang VM Linux heart heartbeats heart と watchdog による二重の死活監視 Erlang VM と heart が同時にイカれても最後はワンワンがなんとかしてくれる watchdog pets If Erlang VM stopped its heartbeats, ● HEARTBEAT_TIMEOUT < WATCHDOG_TIMEOUT heart reboots the OS ● HEARTBEAT_TIMEOUT > WATCHDOG_TIMEOUT watchdog reboots the OS heartbeat が 来たら pet する

Slide 15

Slide 15 text

結局、--run-on-exit でも /bin/sh を起動できるの? ● 結論:できる! ○ heart プロセスが watchdog を起こすので、 heart を使わなければよい ■ 方法 ● rel/vm.args.eex の以下をコメントアウトする -heart -env HEART_BEAT_TIMEOUT 30 ● けど、開発中デバッグで必要になったら使うに留めるべし!!

Slide 16

Slide 16 text

まとめ ● erlinit.config のオプション、--pre-run-exec, --run-on-exit を利用することで、 /bin/sh を実行できることを紹介しました。 ● --run-on-exit では、 nerves_heart を無効化しないと /bin/sh/ を実行できないこ とを、 heart, nerves_heart の機能から説明しました。 Have nice Nerves days!!! Thank you!!