津村彰氏によるコラム第12回「 Luaスクリプトで運用を簡略化しよう! – 第2回 常駐スクリプト入門」

1. はじめに

ヤマハ ルーターによるLuaスクリプト入門では、3回に分け、最終的にヤマハ ルーターからヤマハ スイッチ(SWX2200シリーズ)をスクリプトによりコントロールする事を目標に、Luaスクリプト実行機能を掘り下げてみたいと思います。

2回目は「常駐プログラム」です。一般的なプログラムでは必ず終わりがあり、言語によりガベージコレクション(メモリの開放)などの処理が行われて終了しますが、常駐型プログラムの場合は基本的に無限ループであり、電源断やプログラムの強制終了が無い限り終了する事はありません。故に、OSやCPUへの負荷、およびメモリの使用量などを考えながら実装を進める必要があります。

今回はかんたんなサンプルスクリプトをベースに、ヤマハ ルーターの動作原理を学びながらLuaスクリプトによる常駐プログラムを作成してみたいと思います。

【注意】
実運用中のルーターでのスクリプト実行は、通信障害などの障害となる可能性がある為、お止め下さい。検証用ルーターでの実行を推奨します。
本コラムに掲載のスクリプトを実行した結果について、一切の責任を負いかねます。
2. 常駐プログラムの基本構造

Luaによる無限ループの実行には、Luaそのものの制御命令と、ヤマハ ルーター拡張命令の両方を使う必要があります。
以下のスクリプトは、ヤマハ ルーターにおける無限ループの必要最小限のLuaスクリプトです。

while (1) do
 -- <ここにスクリプトを実装する>
 -- CPU負荷を抑制する為、1秒間スリープ
 rt.sleep(1)
end -- 無限ループおわり

「rt.sleep」はヤマハ ルーターの拡張命令であり、指定した秒数スクリプトの実行を停止させ、ルーター自身に処理を受け渡します。この命令が無い、もしくはループを間違えた場合、スクリプトは暴走し、CPUを専有します。(即ち通信障害が発生します。)
その為、このサンプルコードはとても大事です。

3. 通信障害を検出してビープ音で通知するスクリプト

今回のサンプルスクリプトは、PINGの失敗を検出してビープ音で通知するスクリプト「fail2beep.lua」です。
以下の要素を組み合わせたサンプルスクリプトになります。

  • 無限ループ
  • 環境変数
  • コマンドの実行および実行結果の受け渡し
  • ヤマハ ルーターのハードウェア制御
-- --------
-- 指定したIPアドレスへリーチャビリティが無くなると
-- ビープ音で通知する常駐スクリプト
-- fail2beep.lua 2017.04.28 A.Tsumura
-- --------
-- 【環境変数】
-- set PINGADDR=[PING先IPアドレス]
-- (宣言が無い場合は8.8.8.8を暗黙的に指定)
--
-- 【起動方法】
-- (手動起動)lua /fail2beep.lua 
-- (自動起動)schedule at 1 startup * lua /fail2beep.lua
-- --------
 
-- 無限ループ
while (1) do
 
 -- 環境変数を取得
 adr = os.getenv("PINGADDR")
 
 -- 暗黙的なアドレスの宣言(Google Public DNS)
 if adr == "" then
  adr = "8.8.8.8"
 end
 
 -- adrにpingを1回投げる
 ping_cmd = string.format("ping -c 1 -w 0.5 %s", adr)
 rtn, str = rt.command(ping_cmd)
 
 -- エラー(スクリプトのエラー)
 if (not rtn) or (not str) then
  bz, err = rt.hw.open("buzzer1")
  bz:tone("B4")
  rt.sleep(1)
  bz:tone("B3")
  rt.sleep(1)
  bz:off()
  bz:close()
 end
 
 -- エラー(リーチャビリティに問題がある場合)
 flg = string.find(str , "Request timed out.")
 if (flg ~= nil) then
  bz, err = rt.hw.open("buzzer1")
  bz:tone("B4")
  rt.sleep(1)
  bz:off()
  bz:close()
 end
 
 -- CPU負荷を抑制する為、3秒間スリープ
 rt.sleep(3)
 
end -- 無限ループおわり

前回を参照の上、USBメモリ等を用いてLuaスクリプトをヤマハ ルーターに転送します。
併せて、以下のコンフィグを投入します。

set PINGADDR=<ping先IPアドレス>

この設定を変えることで、スクリプトを再起動する事なく、疎通テスト先を変える事ができます。設定されていない場合、暗黙的にGoogle Public DNS(8.8.8.8)が設定されます。

スクリプトを実行し、以下のように挙動が確認できれば成功です。

  • Ping成功時 – 何もしない
  • Ping失敗時 – ビープ音が3秒おきに鳴る
4. Luaスクリプトのステータスの確認および強制停止

Luaスクリプトの実行状態は、コンソールより以下のコマンドの実行にて確認できます。

# show status lua
Luaライブラリバージョン:        Lua 5.1.5
Luaスクリプト機能バージョン:    1.07
 
[running]
LuaタスクID (状態):  1  (SLEEP)
走行トリガー:        'lua' コマンド
コマンドライン:      lua usb1:/fail2beep.lua
スクリプトファイル:  usb1:/ fail2beep.lua
開始日時:            2017/04/28 01:34:17
経過時間:            38分9秒
(以下略)

Luaスクリプトの実行状態は、コンソールより以下のコマンドの実行にて確認できます。

# terminate lua 1 (タスク番号を指定した停止)
# terminate lua all (すべてのタスクの停止)
5. Luaスクリプトの自動実行

Luaスクリプトは手動起動の他、「起動時」「DOWNLOADボタンの押下」「通信イベントの発生時」といったトリガーでの自動起動が可能です。
例えば、以下は、/fail2beep.luaを起動時に自動起動するコンフィグになります。

schedule at 1 startup * lua /fail2beep.lua
6. 次回予告

今回のコラムで、監視系プログラムの基礎である、無限ループを用いたプログラミングについて理解できたかと思います。
繰り返しになりますが、本運用を行っているルーター上でのスクリプトのデバッグは行わないようにして下さい。

次回はLuaスクリプト及びL2MSを用いて、SWX2200シリーズをコントロールするスクリプトを作成してみたいと思います。