lua - 您如何正确使用带有 lua 的管道来获取程序的输出?

标签 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. 创建单个管道

  2. fork

    • 如果是 child ,

      1. 关闭管道的读取端

      2. dup2(write_end, stdout)

      3. exec() 到所需进程

    • 如果父级

      1. 关闭管道的写入端

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

我错过了什么吗?

最佳答案

你应该看看这个问题的答案 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

这甚至没有经过测试,但您应该明白了。

关于lua - 您如何正确使用带有 lua 的管道来获取程序的输出?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21038018/

相关文章:

c++ - 如何关闭cerr

c - 在 C 中,为什么我的程序在尝试通过管道传输多个命令时卡在 wait() 上?

linux - 在管道 grep 到 grep 后保留颜色

C 管道 : Parent to read from child before child ends

lua - lua and_index 函数中的元表

lua - 从字符串中删除除 "a","b","c","d"之外的所有字符

ssl - NodeMCU Lua Websockets 安全不适用于 2.0 基线

lua - 尝试调用全局 'this'(零值)

c++ - 在 POSIX 中,我可以保存信号以供调用条件等待的其他线程使用吗? (这些线程来自同一个进程)

string - 使用 X""测试空字符串