routeros-scripting について
routeros-scriptingは、RouterOSスクリプトとCLI設定の作成・確認を支援するリファレンススキルです。変動する行番号、配列の扱い、権限要件など、言語固有の注意点を取り上げます。
主な機能
- 01RouterOSの構文とスクリプト作成の指針
- 02実行時に設定対象のオブジェクトを選択
- 03findの結果と出力の適切な処理
- 04変数、配列、ファイルの扱い方
- 05スクリプトポリシーとコマンドの検証
活用シーン
- 01スケジューラーやフック用のRouterOSスクリプト作成
- 02特定のオブジェクトを対象とする設定の生成
- 03RouterOS固有の誤りがないかスクリプトを確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ tikoci/ routeros-skills --skill routeros-scriptingインストール後、Claude Code で/routeros-scriptingを入力して読み込まれたか確認します。
同梱ファイルreferences/syntax.md
詳細
RouterOS スクリプトと CLI 設定
RouterOS スクリプト(.rsc、/system/script、スケジューラーの on-event、Netwatch フック、対話型 CLI スニペット)では、RouterOS 独自の言語を使用します。シェル、Lua、Python、Tcl ではありません。構文の基本については、references/syntax.md を参照してください。このスキルでは、LLM が自信満々に間違えやすい落とし穴に焦点を当てます。
スクリプトで対話型の行番号を使わない
対話型の print 出力には、現在のコンソールバッファー内の一時的な行番号(0、1、2...)が表示されます。これらは安定したオブジェクト ID ではなく、スクリプト内では使用できません。
# WRONG in scripts — "1" is only an interactive print-buffer row number
/ip/route/set 1 gateway=3.3.3.3
# Better — internal IDs have a * prefix, but can change if objects are removed/re-added
/ip/route/set *1 gateway=3.3.3.3
# Best — resolve the target at runtime
/ip/route/set [find dst-address="0.0.0.0/0"] gateway=3.3.3.3
生成する設定では、comment=、name=、一意のアドレスやリスト値など、安定したセレクターを使用してください。内部 ID は print as-value で .id=*HEX として確認できます。
[find] の結果は ID 配列として扱う
[find ...] は、内部 ID を 0 個、1 個、または複数個返します。多くのコマンド(set、remove、disable)はこの配列を直接受け取れますが、オブジェクトが 1 つだけ必要なコードでは、get の前に件数を確認してください。
:local ids [/interface/find where name="ether1"]
:if ([:len $ids] = 1) do={
:put [/interface/get ($ids->0) name]
} else={
:error ("expected exactly one interface, got " . [:len $ids])
}
冪等なクリーンアップには、[find comment="my-tool-tag"] を使用してください。無関係なユーザー設定を削除する可能性のある [find dynamic=no] のような広範なセレクターは避けてください。
find / where では IP プレフィックスを引用符で囲む
RouterOS は積極的に型変換を行いますが、必ずしも期待どおりの方向に変換されるとは限りません。/ip/address では、address プロパティはプレフィックス長を含む文字列として保存されます。111.111.1.1/24 のように引用符で囲まれていないリテラルは IP プレフィックス値として扱われ、何も一致しないことがあります。
# WRONG — can silently return nothing
/ip/address/print where address=111.111.1.1/24
# Correct
/ip/address/print where address="111.111.1.1/24"
# Correct when value came from a variable
:local prefix 111.111.1.1/24
/ip/address/print where address=[:tostr $prefix]
クエリが予想外に何も返さない場合は、保存されている型を確認してください。
:put [:typeof ([:pick [/ip/address/print as-value] 0]->"address")]
print as-value は通常、マップの配列を返す
print as-value where ... は、一致する行が 1 つだけの場合でも {{...}; {...}} を返します。プロパティにアクセスする前に、行を選択してください。
# WRONG — tries to read "gateway" from the outer array
:put ([/ip/route/print as-value where gateway="ether1"]->"gateway")
# Correct — pick the first map, then read the property
:put ([:pick [/ip/route/print as-value where gateway="ether1"] 0]->"gateway")
get のないコマンドでは、スクリプトで扱いやすい出力を得る方法は、多くの場合 as-value だけです。
:put ([/tool/fetch url="https://example.com/file.txt" output=user as-value]->"data")
monitor コマンドには once do={...} が必要
monitor-traffic などのコマンドは、1 回だけ実行するよう指示しない限り、対話型ループになります。スクリプトで一時的な値を取得するには、once do={} を使用してください。ハイフンを含むフィールド名には $"name-with-hyphens" を使用します。
/interface/monitor-traffic ether1 once do={
:put ("rx=" . $"rx-bits-per-second")
}
ターミナルが接続されていないスケジューラーやフックスクリプトでは、:put だけでなく :log を使用してください。
グローバル変数は読み取る場所で再宣言する
グローバル変数やグローバル関数は、別のスクリプトや関数本体から自動的に参照できるわけではありません。読み取ったり呼び出したりする前に、:global name; でアクセスを宣言してください。
:global state "ready"
:global showState do={
:global state
:put ("state=" . $state)
}
:global addOne do={ :return ($1 + 1) }
:global caller do={
:global addOne
:return [$addOne 5]
}
一意の変数名を使用してください。dst-address など、RouterOS のプロパティと名前が重複するものは避けてください。そのような変数にアクセスする必要がある場合は、引用符付きの変数構文($"dst-address")を使用してください。
配列は JavaScript の配列とは異なる
# Empty array: {} is a syntax error
:local arr [:toarray ""]
# Indexing and assignment use ->
:set ($arr->"name") "router1"
:put ($arr->"name")
文字列連結で . を使用すると、事前に変換しない限り配列の各要素に適用されます。
:local arr {"a"; "b"}
:put ("value=" . $arr) # two outputs: value=a and value=b
:put ("value=" . [:tostr $arr]) # one output: value=a;b
名前付きキーはアルファベット順に並べ替えられます。名前のない要素は挿入順を保ちますが、キー付き要素の前に移動します。
ファイルには CLI 固有の制限がある
RouterOS には、「空のファイルを作成する」または追記するための直接的なプリミティブはありません。ドキュメントで説明されている回避策では、print file=... でファイルを作成してから、contents= に書き込みます。
/file/print file=myFile
/file/set myFile.txt contents=""
追記するには、既存の内容を読み取り、連結して、ファイル全体を書き戻してください。大きなファイルやバイナリコンテンツは RouterOS スクリプトには適していません。可能であれば、/tool/fetch、REST、SCP/SFTP、または外部ツールを使用してください。
スクリプトポリシーは正確な動作に欠かせない
スケジューラー、Netwatch、PPP の on-up などのフックは、制限されたポリシーで実行されます。スクリプトでファイル、バックアップ、パスワード、スニッフィング、または再起動の権限が必要な場合、呼び出し元にも対応するポリシーが必要です。
/system/script/add name=backup policy=read,write,ftp,sensitive source={
/system/backup/save name=daily
}
dont-require-permissions=yes の使用には注意してください。権限の低い呼び出し元でも、スクリプト独自のポリシーセットでスクリプトを実行できるようになります。意図的に範囲を限定したスクリプトにのみ使用してください。
実行前にコマンドの形式を検証する
不明な属性、フラグ、パッケージに依存するコマンドについては、次の手順に従います。
- まず、新しい MikroTik マニュアルの CLI リファレンスを確認してください。 https://manual.mikrotik.com/docs/CLI%20Reference/
- 実機のルーターや特定の RouterOS バージョンについては、
/console/inspectが正確な情報源です。routeros-command-treeスキルを参照してください。 - 利用できる場合は、実行前に
rosettaMCP(routeros_explain_command、routeros_command_tree)を使って読み取り専用で確認してください。 - 確信が持てず、ローカルに CHR がある場合は、スクリプトを公開する前に、使い捨てインスタンスで
quickchr exec <name> '<command>'を実行してください。
最初に確認する公式ドキュメント
- 新しい RouterOS マニュアルのホーム:https://manual.mikrotik.com/ — 旧 Confluence ベースの
help.mikrotik.comドキュメントは、今後こちらに置き換えられます。 - スクリプトのヒントとテクニック: https://manual.mikrotik.com/docs/Developer%20Guides/Scripting/scripting-tips-and-tricks/
- スクリプトの例: https://manual.mikrotik.com/docs/Developer%20Guides/Scripting/scripting-examples/
- CLI リファレンス:https://manual.mikrotik.com/docs/CLI%20Reference/ — パッケージとコマンドパスごとに整理された、閲覧可能なコマンド/プロパティのスキーマです。