2012-01-03 68 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()