Lua脚本无法检测/捕捉执行无效Linux命令时的错误。

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

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

用状态:true和值执行了" uptime "180738 1天,23:003个用户,负载平均值:0.370.200.20

sh:zzzz:未找到命令
用状态:true和值执行了" zzzz "

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

有人能帮我想出一种方法,使用Lua脚本捕获执行不存在或格式不正确的Linux命令的异常吗?谢谢。

编辑:在得到澄清之后重申了我的请求,即pcall()按预期工作,问题是popen()无法引发错误。

点赞
用户1190388
用户1190388

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

在一个单独的进程中启动程序 prog,返回一个文件句柄,可用于从该程序中读取数据(如果模式是"r",则是默认的)或将数据写入该程序(如果模式是"w")。

因此,由于返回的文件句柄仍然是 Lua 的有效值, pcall() 内部的本地函数会返回一个 true 值(没有错误传播),从而为您提供一个真实的状态和没有输出。

2014-06-15 01:26:49
用户657087
用户657087

我想出了自己的临时解决方案,将错误输入重定向到 /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,'执行命令出错:'..com
    end
end
local st,val=exec_com('uptime')
print('执行 "uptime" 的状态为:'..tostring(st)..',值为:'..val)
st,val=exec_com('cat /etc/shadow')
print('执行 "cat /etc/shadow" 的状态为:'..tostring(st)..',值为:'..val)

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

执行 "uptime" 的状态为:true,值为:00:10:11 up 2 days,  5:02,  3 users,  load average: 0.01, 0.05, 0.19
执行 "cat /etc/shadow" 的状态为:false,值为:执行命令出错:cat /etc/shadow

在上面的示例中,我创建了一个“通用”的错误描述。这是一个中间的解决方案,我仍然有兴趣看到其他的解决方案,可以返回一个更有意义的错误消息,描述为什么命令执行失败。

2014-06-15 04:19:36
用户1560821
用户1560821

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

local cmd = "uptime"
local f = io.popen(cmd .. " 2>&1 || echo ::ERROR::", "r")
local text = f:read "*a"

if text:find "::ERROR::" then
  -- 出现错误
  print("错误:" .. text)
else
  -- 一切正常!!
  print(text)
end
2014-06-15 07:44:07
用户8449645
用户8449645

将下面翻译成中文并且保留原本的 markdown 格式

Rather than taking the time reading the whole file into a variable, why not just check if the file is empty with f:read(0)?

为什么不直接使用 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 手册中可以看到:

s:read(0) 可以用于测试文件是否已经到达文件末尾,当文件未到文件末尾的时候,它会返回一个空字符串,否则返回 nil

2017-08-13 14:35:47