うたカモ技術ブログ

Lua

Luaプログラミング   Luaから外部ソフトウェアを実行して結果を取得する方法

post: 

この記事では、LuaスクリプトからLinuxコマンドなどの外部ソフトウェアを実行して、その処理結果を取得する方法について紹介します。

Luaは外部ソフトウェアの実行プロセスを作成し、その処理結果をLua変数にパイプすることができます。

外部ソフトウェアの実行プロセスの作成は入出力モジュール(io)のpopen関数、その実行結果の取得はファイルハンドル モジュール(handle)のread関数を呼び出すこと可能です。

ここでは、サンプルコードとその実行結果を掲載して説明します。

#実行環境OS
ubuntu 22.04 LTS 64bit
#Lua
Ver 5.4.4

サンプルコードの紹介

今回は冒頭で処理の流れをほとんど説明しました。

なので早速、サンプルコードを掲載します。 これは外部ソフトウェアを実行して処理結果を返すexecute_cmd関数を定義してそれを呼び出すコードです。

--sample.lua

--[今回のテーマ!!] プロセスを作って外部ソフトウェアを実行して結果をパイプで取得する関数
local execute_cmd = function(cmd)
    local handle = io.popen(cmd) --環境によっては実行できないこともあるそうです
    local result = handle:read('*a')
    handle:close()
    
    return result
end

local active_ifs = execute_cmd("ip link show up | awk '/^[0-9]+: / {print substr($2, 1, length($2)-1)}'")

--アクティブなインタフェースの名前を取得して表示
--まずは結果を1つの変数に格納するパターン
print(active_ifs)

このコードは、ipとawkコマンドを実行します。これによって取得できたアクティブなインタフェースの名前一覧を文字列としてactive_ifs変数に格納し、その内容を表示します。

実行結果は次の通りです。私の環境では、3つのアクティブなインタフェースの名前が1行ごとに表示されることが分かります。

[注意] 実行結果は環境に依存します。
kamo@kamo:~$ lua sample.lua
lo
eth0
wlo0

ここで、インタフェース名を別々の変数で管理させたいという要求があれば、次のように処理結果を分割してLuaテーブルの各要素に 振り分ける方法があります。

[実行結果を分割してLuaテーブルの各要素に振り分ける]
次のコードは、文字列分割用関数のsplitを新たに定義し、それを利用してactive_ifs変数が持つ複数のインタフェース名をactive_iflistテーブルに展開 します。コマンドの実行結果であるインタフェース名は改行で区切られますのでデリミタとして、splitの第2引数に'\n'を指定します。

--sample.lua

--[今回のテーマ!!] プロセスを作って外部ソフトウェアを実行して結果をパイプで取得する関数
local execute_cmd = function(cmd)
    local handle = io.popen(cmd)
    local result = handle:read('*a')
    handle:close()
    
    return result
end

--文字列分割関数
local split = function(inputString, delimiter)
    local result = {}
    local pattern = string.format("([^%s]+)", delimiter)
    
    for match in inputString:gmatch(pattern) do
        table.insert(result, match)
    end
    
    return result
end

--1つの変数に入った結果を分割するパターン
local active_ifs = execute_cmd("ip link show up | awk '/^[0-9]+: / {print substr($2, 1, length($2)-1)}'")
local active_iflist = split(active_ifs, '\n')

for i = 1, #active_iflist  do
    print('active_iflist[' .. i .. '] = ' .. active_iflist[i])
end

実行すると、アクティブなインタフェースがテーブルの各要素に振り分けられました。

[注意] 実行結果は環境に依存します。
kamo@kamo:~$ lua sample.lua
active_iflist[1] = lo
active_iflist[2] = eth0
active_iflist[3] = wlo0

おわりに

このように、Luaでは簡単に外部ソフトウェアを実行して結果を得ることができます。 C言語からLuaを呼び出す方法と合わせ、今回紹介した内容を利用すると非常に強力です。

次回記事では今回取り上げた処理を利用して、C言語ソフトウェアにIPアドレスやMACアドレスなどの情報を渡す処理をまとめますので、 興味があったら読んでみてください。

参考文献