我有这个 PHP 代码:
$execout=exec('ssh [email protected] "sudo /etc/init.d/smokeping reload"',$output1,$result);
if($result !=0){
echo"that can't reload";
}
else{
echo "successfully reloaded";
}
在此代码中,始终给出$result = 0
.这是为什么?有时如果smokeping有错误,在命令行中输入以下命令时会显示该错误,
ssh [email protected] "sudo /etc/init.d/smokeping reload"
然后它给出这个错误消息。
* Reloading latency logger daemon configuration...
ERROR: can't open /etc/smokeping/devices/errorfilename: No such file or directory
...done.
所以它有一个错误,但$result
每次都给出与 0 相同的值。 (是否有错误)
为什么 exec 命令的行为是这样的(在 php 和 CLI 中)?
答案1
在
ssh [email protected] "sudo /etc/init.d/smokeping reload"
你的壳
(1) (或者在您的示例中,由 PHP 启动的 shell exec()
)将解析该命令行,如果找到则执行ssh
(2) 将联系的命令sshd
(3)xxx.xxx.xxx.xx
认证成功后调用的服务器shell
(4) 它将解释该sudo
命令行并运行sudo
(5) 检查权限后将运行的命令/etc/init.d/smokeping
(6) 它本身可能是一个运行多个命令的 shell 脚本。
有几件事可能会失败。如果所有步骤 1 到 5 均成功,则 的退出状态/etc/init.d/smokeping
将报告给您的 shell,因为它sudo
会报告其运行的命令的退出状态,并且远程 shell 将以其运行的最后一个命令的退出状态退出并ssh
报告远程 shell 的退出状态。
现在,按照惯例,命令会返回非零退出状态,以向调用者报告他们尚未完成要求执行的操作。
在您的情况下,要么/etc/init.d/smokeping
认为发生的任何错误都不足以保证非零退出状态,要么脚本编写不正确,并且在失败时无法以非零退出状态返回(或者涉及不当行为或某些病态情况)ssh
或sudo
远程 shell的配置错误)。
/etc/init.d
脚本通常是用set -e
.启用该标志后,解释脚本的 shell 将在运行命令失败时默认退出(失败命令的退出状态为非零),这让我认为我们可能处于第一种情况:“冒烟”确实决定报告它已成功重新加载。
病态情况的一个例子可能是:bash
用作远程 shell(即使它们不是交互式 shell,在调用时bash
也会读取),并且具有类似以下内容的内容:~/.bashrc
ssh
~/.bashrc
trap 'whatever...; exit 0' EXIT
ssh
这将导致交互式 shell 或 shell 重新启动或rsh
始终为 的退出状态0
。
答案2
2>&1
我找到了一个小答案。对于我放在最后的上面的代码。作为
$execout=exec('ssh [email protected] "sudo /etc/init.d/smokeping reload 2>&1"',$output1,$result);
当我要重新加载(smokeping)的应用程序中发生错误时,print_r($output);
给出的错误为
Array ( [0] => * Reloading latency logger daemon configuration... [1] => ERROR: can't open /etc/smokeping/devices/errorfilename: No such file or directory [2] => ...done. )
现在我可以从这里处理了。谢谢大家。