首页 文章

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

提问于
浏览
3

我使用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

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

  • 创建一个管道

  • 前叉

  • 如果孩子,

  • 关闭读取管道末端

  • dup2(write_end,stdout)

  • exec()到所需的进程

  • 如果是父母

  • 关闭写管道末尾

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

我错过了什么吗?

1 回答

  • 2

    你应该看一下这个问题的答案How do you construct a read-write pipe with lua?

    了解实现这一点的困难 . 令我印象深刻的是,似乎没有人能够只使用 one 子进程 .

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

    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
    

    这甚至没有经过测试,但你应该明白这个想法 .

相关问题