Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Nerves tips, /bin/sh & nerves_heart

Nerves tips, /bin/sh & nerves_heart


June 16, 2022

More Decks by pojiro

Other Decks in Technology


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

  2. /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”
  3. erlinit.config でできること • ドキュメントを読もう! ◦ https://github.com/nerves-project/erlinit#configuration-and-command-line-options • Shell を起動するには? 以下が使えそう!

    ◦ --pre-run-exec <program and arguments> Run the specified command before Erlang starts ◦ --run-on-exit <program and arguments> Run the specified command on exit.
  4. 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
  5. --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 を外します。
  6. --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
  7. 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
  8. 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 が終了する。
  9. どうなった? • :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 を起動できそう?
  10. watchdog? heart?

  11. 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 で寝かす
  12. 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 としているから。
  13. 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
  14. 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 する
  15. 結局、--run-on-exit でも /bin/sh を起動できるの? • 結論:できる! ◦ heart プロセスが watchdog

    を起こすので、 heart を使わなければよい ▪ 方法 • rel/vm.args.eex の以下をコメントアウトする -heart -env HEART_BEAT_TIMEOUT 30 • けど、開発中デバッグで必要になったら使うに留めるべし!!
  16. まとめ • 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!!