2012-01-03 63 views
4

我試圖創建一個程序在後臺運行一個shell併發送用戶命令給它執行並返回結果。這是代碼:交互式popen()Lua調用

--note: this runs on windows but I assume replacing "cmd" with "sh" it can run on linux as well 
exe,err=io.popen("cmd > stdout.txt 2> stderr.txt"); 
if not exe then 
    print("Could not run command. Error: "..err) 
    return 
else 
    print("Command run successfully... ready!") 
end 

stdout,err=io.open("stdout.txt","r") 
if not stdout then print("Could not open stdout: "..err) return end 
stderr,err=io.open("stderr.txt","r") 
if not stdout then print("Could not open stderr: "..err) return end 

function execute(str) 
    exe:write(str) 
    return stdout:read("*all") or stderr:read("*all") or "nil" 
end 

repeat 
    print("COMMAND: ") 
    userinput=io.read("*line") 
    print("You entered: '"..userinput.."'") 
    if userinput=="" then print "Empty line! Exiting program..." break end 
    print("Result: "..execute(userinput)) 
until true 

print "Closing..." 
execute("exit") 
print "1" 
exe:close() 
print "2" 
stdout:close() 
print "3" 
stderr:close() 
print "Finished!" 

問題:退出程序時,它掛在exe:close()調用。執行循環的表現也很奇怪(有時我必須按幾次輸入才能使userinput=io.read("*line")工作。

我用google搜索瞭解file:close()是否也適用於io.popen()的結果文件句柄但沒有發現任何東西,但這一呼籲並沒有失敗這只是掛斷換句話說程序的輸出是這樣的:。

Command run successfully... ready! 
COMMAND: 
dir 

dir 
You entered: 'dirdir' 
Result: Microsoft Windows [Version 6.1.7601] 
Copyright (c) 2009 Microsoft Corporation. All rights reserved. 

C:\lua> 
C:\lua> 
C:\lua> 
Closing... 
1 

回答

8

的Lua僅依賴於ANSI C的功能因此io.popen用途。 popen(3)功能。從其手冊引用:

由於pipe的定義是單向的,因此type參數可能只指定讀取或寫入,而不能同時指定;所得到的流是相應的只讀或只寫。

您嘗試通過將輸出重定向到文件並同時打開該文件並在執行命令後從中讀取該文件來解決此限制。但是,在這種情況下,您可能會遇到輸出緩衝問題 - 我認爲這是您正在經歷的問題。

,而不是試圖解決io.popen,您可以嘗試從Lua Ex APIwiki page here),它提供了一個替代的過程產卵的API,並允許你做這樣的事情:

-- popen2(), from http://lua-users.org/wiki/ExtensionProposal 
function popen2(...) 
    local in_rd, in_wr = io.pipe() 
    local out_rd, out_wr = io.pipe() 
    local proc, err = os.spawn{stdin = in_rd, stdout = out_wr, ...} 
    in_rd:close(); out_wr:close() 
    if not proc then 
    in_wr:close(); out_rd:close() 
    return proc, err 
    end 
    return proc, out_rd, in_wr 
end 
-- usage: 
local p, i, o = assert(popen2("wc", "-w")) 
o:write("Hello world"); o:close() 
print(i:read"*l"); i:close() 
p:wait()