うたカモ技術ブログ

Linux OpenWrt

OpenWrt   シェルスクリプト専用UCI関数の使い方

post:     update: 

今回は、シェルスクリプト専用UCI関数について紹介します。

これらのシェル関数は主に、OpenWrt専用アプリケーションの初期化スクリプトで使用されています。 そのため、OpenWrtのソフトウェア開発に興味がある方は知っておいて損はありません。

この記事では、サンプルコードとその実行結果を掲載することで、シェルスクリプト専用UCI関数の使い方について説明します。

この記事を通して、読者の方がこれらの関数の使い方を理解し、対象のUCIコンフィグレーションファイルを難なく操作できる助けとなれば幸いです。

補足
この記事はOpenWrtドキュメントの「Configuration in scripts」を参考にしています。 こちらの内容も大変分かりやすく書かれていますので都度参照してみてください。

目次

  1. サンプルコード用UCIコンフィグレーションファイル(/etc/config/sample)
  2. UCI関数のインクルード方法
  3. シェルスクリプト専用UCI関数
    1. config_load
    2. config_get
    3. config_get_bool
    4. config_set
    5. config_list_foreach
    6. config_foreach
  4. イベントトリガー型コールバック関数
    1. config_cb
    2. option_cb
    3. list_cb

サンプルコード用UCIコンフィグレーションファイル(/etc/config/sample)

掲載サンプルコードの操作対象ファイルは、この記事のために作成したUCIコンフィグレーションファイル(/etc/config/sample)です。

このUCIコンフィグレーションファイルはUCIコマンドを使用して作成できます。 読者ご自身の環境で、サンプルコードを実行したい場合は、お手持ちのOpenWrtデバイスのコンソール上で次のコマンドを実行してください。

root@OpenWrt:~# touch /etc/config/sample
root@OpenWrt:~# uci batch << EOI
> set sample.bool_test=confirm1
> set sample.bool_test.flag1=on
> set sample.bool_test.flag2=true
> set sample.bool_test.flag3=yes
> set sample.bool_test.flag4=enabled
> set sample.option_test=confirm2
> set sample.option_test.value1=100
> set sample.option_test.value2=200
> set sample.option_test.value3=300
> set sample.list_test=confirm3
> add_list sample.list_test.items=1
> add_list sample.list_test.items=2
> add_list sample.list_test.items=3
> add_list sample.list_test.items=4
> add_list sample.list_test.items=5
> EOI
root@OpenWrt:~# uci commit

上記のコマンド実行後、catコマンドでsampleファイルの中身を見てみると、次のように表示されるはずです。

root@OpenWrt:~# cat /etc/config/sample

config confirm1 'bool_test'
        option flag1 'on'
        option flag2 'true'
        option flag3 'yes'
        option flag4 'enabled'

config confirm2 'option_test'
        option value1 '100'
        option value2 '200'
        option value3 '300'

config confirm3 'list_test'
        list items '1'
        list items '2'
        list items '3'
        list items '4'
        list items '5'

以上より、この記事では、/etc/config/sampleに対してUCI操作をするコードを掲載します。 これを通してシェルスクリプト専用UCI操作関数について、その使い方を理解して頂ければ幸いです。 それでは、次節から説明に入ります。

UCI関数のインクルード方法

シェルスクリプト上でUCI用シェル関数を使用するためのライブラリのインクルード方法は次の2パターンです。

  • ①通常のシェルスクリプト上で使用するためのインクルード
  • ②初期化スクリプト上で使用するためのインクルード

以下に、それぞれの方法について説明します。

①通常のシェルスクリプト上で使用するためのインクルード
次のように、シェルスクリプトの行頭で/lib/functions.shをインクルードしてください。

#!/bin/sh
. /lib/functions.sh

#以下、UCI操作用関数を記述する

これにより、UCI用関数を使用することが可能になります。

②初期化スクリプト上で使用するためのインクルード
初期化スクリプト上で使用する場合は、スクリプトの行頭に次のシェバン宣言を記述します。

#!/bin/sh /etc/rc.common

rc.commonは初期化スクリプトがサポートするstart、stop、restart、reloadなどの操作関数をコールする シェル関数ラッパーを提供します。このrc.commonの中で、/lib/functions.shを内部でインクルードしていますので 結果として上記①と同様の処理がされたことになります。

今回取り上げるサンプルコードは、通常のシェルスクリプトとして作成しています。 もちろん、シェルスクリプト専用UCI関数において、通常のシェルスクリプトと初期化スクリプトでの使用方法に違いはありません。

シェルスクリプト専用UCI関数

ここでは、UCIコンフィグレーションファイルをロードして配下のオプションやリストの値を取得・変更するシェルスクリプト専用UCI関数について紹介します。

config_load <package>
引数
  1. package: ロード対象のUCIコンフィグレーションファイル
説明
/etc/config内に存在するUCIコンフィグレーションファイルをシェルプロセスにロードします。 次はsampleコンフィグをconfig_loadでロードする例です。もちろん、このコードはプロセス に対してUCIコンフィグをロードするだけなので、このままでは意味はありません。
#!/bin/sh
. /lib/functions.sh
config_load sample
通常、続けてconfig_getやconfig_list_foreachでUCIコンフィグレーション中のオプションやリストを取得します。 また、config_loadはコールバック関数のconfig_cb、option_cb、list_cbのイベントトリガーになります。
config_get <arg> <section> <option> [<default>]
引数
  1. arg:       取得したオプション値を格納するシェル変数
  2. section: 取得対象のオプションを管理するセクション名
  3. option:  取得対象のオプション名
  4. default: オプション未取得の場合の返却値
config_loadでロードしたUCIコンフィグレーションファイルの任意オプションを取得します。 次はsample.option.value1の値を取得してコンソールに出力する例です。
#filename: config_get_test
#!/bin/sh
. /lib/functions.sh
config_load sample
config_get arg option_test value1
echo "value : ${arg}"
実行すると、次のような出力が得られます。
root@OpenWrt:~# chmod +x config_get_test
root@OpenWrt:~# ./config_get_test
value : 100
config_get_bool <arg> <section> <option> [<default>]
引数
  1. arg:       取得したオプション値を格納するシェル変数
  2. section: 取得対象のオプションを管理するセクション名
  3. option:  取得対象のオプション名
  4. default: オプション未取得の場合の返却値
説明
UCIコンフィグレーションファイルのオプション値を論理値として解釈し、取得します。 通常、UCIコンフィグレーションファイルのオプション値は全て文字列です。しかし、OpenWrtアプリケーションの中には特定文字列を 設定の有効・無効を示す論理値として扱うものがあります。config_get_boolは引数で与えられた文字列を論理値として0(false)・1(true) に変換し、これらのアプリケーションに提供します。
以下の表は論理値として変換される文字列を列挙したものです。 config_get_boolはこれらの文字列を0(false)・1(true)に振り分けます。
真(1) 偽(0) 空文字
onoff左記以外
truefalse
yesno
enableddisabled
次は、sampleコンフィグのboolセクションの各オプションをconfig_get_boolで論理値に変換するサンプルコードです。
#filename: config_get_bool_test
#!/bin/sh
. /lib/functions.sh

config_load sample

config_get_bool result1 bool_test flag1
config_get_bool result2 bool_test flag2
config_get_bool result3 bool_test flag3
config_get_bool result4 bool_test flag4

echo "result1 : ${result1}"
echo "result2 : ${result2}"
echo "result3 : ${result3}"
echo "result4 : ${result4}"
実行結果は次の通りです。boolセクションの各オプションの初期値が全て真(1)に変換される文字列("on", "true", "yes", "enabled")のため、出力結果は全て"1"となります。
root@OpenWrt:~# chmod +x config_get_bool_test
root@OpenWrt:~# ./config_get_bool_test
result1 : 1
result2 : 1
result3 : 1
result4 : 1
ここで例えば、「uci set sample.bool_test.flag1=off」とした後にもう一度サンプルコードを 実行すると次の結果が得られます。
root@OpenWrt:~# uci set sample.bool.flag1=off
root@OpenWrt:~# ./config_get_bool_test
result1 : 0
result2 : 1
result3 : 1
result4 : 1
config_set <section> <option> <value>
注意:現時点でこのスクリプトは正常に動作しません。 公式ではバグが存在するため、動作しない可能性があると記述されています。そのため、確認中です。 ちなみに、公式ドキュメントによると代わりにuci setコマンドを使うようにとのこと。
任意オプションの値を追記・変更します。次はsample.option_test.value1の値を'1000'にする例です。
#filename: config_set_test
#!/bin/sh
. /lib/functions.sh
config_load sample
config_set option_test value1 1000
config_list_foreach <section> <list> <func>
引数
  1. section: 取得対象のセクション名
  2. list:        取得対象のリスト
  3. func:     イテレータで実行する関数
UCIコンフィグレーションファイルのリスト用コールバックイテレータです。リストの要素数に応じて ループ処理をします。イテレータ内で処理する関数は第3引数で指定します。 次はsample.list.itemsリスト内の登録ntpサーバーを表示するコード例です。
#filename: config_list_foreach_test
#!/bin/sh
. /lib/functions.sh

index=0

output_list_item() {
    local item="$1"  #$1でリスト内のオプションを取得可能です。
    echo "[${index}]: ${item}"
    index=`expr $index + 1`
}

config_load sample
config_list_foreach list_test items output_list_item
実行結果として、次のような出力が得られます。
root@OpenWrt:~# chmod +x config_list_foreach_test
root@OpenWrt:~# ./config_list_foreach_test
[0]: 1
[1]: 2
[2]: 3
[3]: 4
[4]: 5
config_foreach <func>
引数
  • func: イテレータで実行する関数
UCIコンフィグレーションファイルのセクション用コールバックイテレータです。任意のUCIコンフィグレーションファイルが持つ セクション数に応じてループ処理をします。ループ内で実行される関数は第2引数で指定可能です。 次はsampleコンフィグをロードしたとき、各セクション毎にコールバック関数を実行してコンソールにタイプ情報を表示するサンプルコードです。
#filename: config_foreach_test
#!/bin/sh
. /lib/functions.sh

output_section() {
    local section="$1"
    local value="$2"

    echo "section-name: ${section}"
}

config_load sample
config_foreach output_section
root@OpenWrt:~# chmod +x config_foreach_test
root@OpenWrt:~# ./config_foreach_test
section-name: bool_test
section-name: option_test
section-name: list_test

イベントトリガー型コールバック関数

前節で紹介したconfig_loadの実行を契機として呼び出されるconfig_cb、option_cb、list_cbコールバック関数の定義を開発者側で編集できます。 これらのコールバック関数名は、あらかじめ予約された名前であり、UCIコンフィグレーションファイルのロード時に発生するイベントに応じて実行されます。 開発者はコールバック関数の定義を変更することで、自由にUCIコンフィグレーションファイルを操作できます。

config_cb
config_cbは、config_loadによるセクション読み込みを契機として実行されるシェル関数です。 次はsampleコンフィグをロードした時のコールバックにより、config_cbを実行するコードです。
#filename: config_cb_test
#!/bin/sh
. /lib/functions.sh

config_cb() {
    local type="$1"
    local name="$2"

    echo "section-type: ${type}, section-name: ${name}"
}

config_load sample #ここが実行されるとconfig_cbのトリガに発火します。
実行結果は次のようになります。
root@OpenWrt:~# chmod +x config_cb_test
root@OpenWrt:~# ./config_cb_test
section-type: confirm1, section-name: bool_test
section-type: confirm2, section-name: option_test
section-type: confirm3, section-name: list_test
section-type: , section-name:   <---読み込むセクションがなくなったところでもう1回呼ばれます。
各セクションの読み込み時に実行されていることが分かります。 ポイントは各セクションの読み込みイベントが終わったところでもう1回実行されるところです。 このとき、タイプ情報とセクション名はありませんので取得できません。 最後の1回では、何らかの後処理を実行すると良いでしょう。
option_cb
config_loadによるオプション読み込みを契機として実行されます。 第1引数にオプション名、第2引数にその値が格納されます。
#filename: option_cb_test
#!/bin/sh
. /lib/functions.sh

option_cb() {
    local option="$1"
    local value="$2"
    echo "option-name: ${option}, value: ${value}"
}

config_load sample
実行すると、結果は次のようになります。
root@OpenWrt:~# chmod +x option_cb_test
root@OpenWrt:~# ./option_cb_test
option-name: flag1, value: on
option-name: flag2, value: true
option-name: flag3, value: yes
option-name: flag4, value: enabled
option-name: value1, value: 100
option-name: value2, value: 200
option-name: value3, value: 300
section_cbとoption_cbを交互に実行させて、対象セクションとその配下のオプションのコールバック処理を まとめたい場合はsection_cb定義の中にoption_cbを定義しましょう。詳細は公式ドキュメントを参照してください。
list_cb
config_loadによるリストの読み込みを契機として実行されます。 次はsampleコンフィグをロードした時のコールバックにより、config_cbを実行するコードです。
#filename: list_cb_test
#!/bin/sh
. /lib/functions.sh

index=0

list_cb() {
    local option="$1"
    local item="$2"

    echo "${optiion}[${index}]: ${item}"

    index=`expr $index + 1`
}

config_load sample
実行結果は、次のようにsampleコンフィグのリストであるitemsの内容が出力されます。
root@OpenWrt:~# chmod +x list_cb_test
root@OpenWrt:~# ./list_cb_test
[0]: 1
[1]: 2
[2]: 3
[3]: 4
[4]: 5
section_cbとlist_cbを交互に実行させて、対象セクションとその配下のオプション、リストのコールバック処理を まとめたい場合は、section_cb定義の中にlist_cbを定義しましょう。

関連記事

参考文献