Lua脚本在执行无效的linux命令时无法检测/捕获错误

我有以下function,只要我给它一个有效的命令来执行就可以正常工作。 只要我给它一个不存在的命令,脚本就会被打断,并显示一条错误消息。

#!/usr/bin/lua function exec_com(com) local ok,res=pcall(function() return io.popen(com) end) if ok then local tmp=res:read('*a') res:close() return ok,tmp else return ok,res end end local st,val=exec_com('uptime') print('Executed "uptime" with status:'..tostring(st)..' and value:'..val) st,val=exec_com('zzzz') print('Executed "zzzz" with status:'..tostring(st)..' and value:'..val) 

当我运行上面的脚本时,我得到以下输出:

 Executed "uptime" with status:true and value: 18:07:38 up 1 day, 23:00, 3 users, load average: 0.37, 0.20, 0.20 sh: zzzz: command not found Executed "zzzz" with status:true and value: 

你可以清楚的看到,pcall()函数在执行奇怪的“zzzz”时仍然报告成功。

有人可以帮我devise一个方法来捕捉一个exception,当执行一个不存在或使用Lua脚本格式不正确的Linux命令? 谢谢。

编辑:重申我的要求澄清之后,pcall()按预期工作,并且问题是由于popen()无法引发错误。

我使用了一种类似于“临时解决方法”的方法,但它提供了更多信息:

 local cmd = "uptime" local f = io.popen(cmd .. " 2>&1 || echo ::ERROR::", "r") local text = f:read "*a" if text:find "::ERROR::" then -- something went wrong print("error: " .. text) else -- all is fine!! print(text) end 

如果你看看io.popen() ,你会发现它总会返回一个文件句柄。

在一个单独的进程中启动程序编程,并返回一个文件句柄 ,你可以使用这个句柄从这个程序读取数据(如果模式是"r" ,默认)或者写入数据到这个程序(如果模式是"w" )。

因为返回的文件句柄仍然是lua的有效值, pcall()pcall()的本地函数返回一个真正的值(并且错误没有被传播)。 从而给你一个真实的地位,没有输出。

我已经想出了自己的临时解决方法,将错误管理到/dev/null并基于从io.popen():read('*a')命令收到的文本确定执行命令的成功/失败。

这是我的新代码:

 #!/usr/bin/lua function exec_com(com) local res=io.popen(com..' 2>/dev/null') local tmp=res:read('*a') res:close() if string.len(tmp)>0 then return true,tmp else return false,'Error executing command: '..com end end local st,val=exec_com('uptime') print('Executed "uptime" with status:'..tostring(st)..' and value:'..val) st,val=exec_com('cat /etc/shadow') print('Executed "cat /etc/shadow" with status:'..tostring(st)..' and value:'..val) 

现在相应的输出是正确的:

 Executed "uptime" with status:true and value: 00:10:11 up 2 days, 5:02, 3 users, load average: 0.01, 0.05, 0.19 Executed "cat /etc/shadow" with status:false and value:Error executing command: cat /etc/shadow 

在我上面的例子中,我正在创建一个“通用”的错误描述。 这是一个中间修复,我仍然有兴趣看到替代解决方案,可以返回一个更有意义的错误信息,说明命令执行失败的原因。

而不是花时间读取整个文件到一个变量,为什么不检查文件是否是空的f:read(0)?

 Local f = io.popen("NotExist") if not f:read(0) Then for l in st:lines() do print(l) end else error("Command Does Not Exist") end 

从lua手册: 作为一个特例,io.read(0)作为文件结尾的测试:如果有更多的要读取,它将返回一个空字符串,否则返回零。