你如何正确使用lua管道来获得程序的输出?

时间:2014-01-10 06:57:48

标签: lua posix pipe system-calls

我使用lua和luaposix库来获取某些命令的输出,有时候也会发送一些命令。我正在使用此代码或其中的变体来完成我的工作,但我有时会陷入posix.wait(cpid)或有时命令似乎没有完成。

-- returns true on connected, else false
function wifi.wpa_supplicant_status()
    -- iw dev wlan0-1 link
    local r,w = posix.pipe()
    local cpid = posix.fork()
    if cpid == 0 then --child writes to pipe
        --close unused read end
        local devnull = posix.open("/dev/null", posix.O_RDWR)
        posix.close(r)
        posix.dup2(devnull, 0)
        posix.dup2(w, 1)
        posix.dup2(devnull, 2)
        local dir = wifi.wpa_supplicant_dir()
        local iface = posix.basename(dir)
        iface = string.gsub(iface, "wpa_supplicant%-",'')
        posix.exec('/usr/sbin/iw', {'dev', iface, 'link'})
        posix._exit(-1)
    elseif cpid > 0 then
        --parent reads from pipe, close write end
        posix.close(w)
        local buf = ''
        while true do
            local tmp = posix.read(r, 100)
            if tmp ~= nil and #tmp > 0 then
                buf = buf .. tmp
            else
                break
            end
        end
        -- TODO, check exit value, to see if entry exists or not
        while posix.wait(cpid) ~= cpid do print("waiting in wpa_supplicant_status") end
        print("status is "..buf)
        if string.find(buf, "Connected to", 1, true) then
            return true
        else
            return false
        end
    end
end

这就是我理解我必须做的事情(只是获得输出):

  1. 创建单个管道

    • 如果孩子,

      1. 关闭管道末端

      2. dup2(write_end,stdout)

      3. exec()到期望的过程

    • 如果是父母

      1. 关闭管道末端

      2. 执行阻塞读取以读取管道末尾,直到读取0字节,这意味着子进程已终止,关闭管道

  2. 我错过了什么吗?

1 个答案:

答案 0 :(得分:2)

您应该查看此问题How do you construct a read-write pipe with lua?

中的答案

了解实施此问题的难度。令我印象深刻的是,似乎没有人能够只使用一个子进程来使用它。

但是,在你给出的例子中,似乎你只想得到命令的输出,所以我建议你这样做:

function os.capture(cmd)
    local f = assert(io.popen(cmd, 'r'))
    local s = assert(f:read('*a'))
    f:close()
    return s
end

function wifi.wpa_supplicant_status()
    local dir = wifi.wpa_supplicant_dir()
    local iface = posix.basename(dir):gsub("wpa_supplicant%-",'')
    local cmd = ('/usr/sbin/iw dev %s link'):format(iface)
    local buf = os.capture(cmd)
    return buf:find("Connected to", 1, true) ~= nil
end

这甚至没有经过测试,但你应该明白这一点。