问题:以下shell脚本在 www 用户下执行 sudo /usr/local/webserver/nginx/sbin/nginx -t 是有返回结果的,但用http://localhost/nginx.php?act=test 访问是看不到返回值,shell指令都没执行,safe-mode 是off的,不知为何,请教高人了?
nginx.php代码如下:
<?php
if(isset($_GET[‘act’])&&!empty($_GET[‘act’])){
if($_GET[‘act’]==’test’){
$message=shell_exec(“sudo /usr/local/webserver/nginx/sbin/nginx -t”);
echo “测试结果:”.$message;
}elseif($_GET[‘act’]==’restart’){
$message=shell_exec(“sudo /usr/local/webserver/nginx/sbin/nginx -s reload”)
;
echo “重启结果:”.$message;
}
}else{
header(“Status: 404 Not Found”);
}
?>

回复:我一开始也为这个问题迷惑不解,为何 php cgi以www用户执行sudo ls -al / 命令就可以正常输出,而执行

sudo /usr/local/webserver/nginx/sbin/nginx -t 却没有输出?

没有任何输出,导致我们无法跟踪错误的原因,那么,使用Linux标准输出重定向,看看有无输出,我的php代码是(设置/wwwroot/log.txt权限为777):
/wwwroot/index.php
<?php
$s = shell_exec(“/usr/bin/sudo /home/nginx/sbin/nginx -t >/wwwroot/log.txt”);
echo $s;

请求http://localhost/index.php, 发现log.txt文件是空白的,即没有正常输出,那说明有可能发生了错误,为此,我再尝试使用Linux的标准错误输出重定向:
$s = shell_exec(“/usr/bin/sudo /home/nginx/sbin/nginx -t 2>/wwwroot/log.txt”);

注意重定向符号前的2

再请求index.php 这时,在log.txt中记录了详细的错误:
sudo: sorry, you must have a tty to run sudo

这个错误我没见过,大致意思说,当执行sudo时,必须要从终端登录(可能nginx本身的一些限制)

google搜索这个错误提示, 解决办法也很简单:
注释掉 /etc/sudoers中 ‘Defaults requiretty’ 这个就行,即前面加#

按这个办法处理,浏览器仍然没有任何输出,我的猜测:可能是nginx启动程序输出目标是终端,那么折衷的办法就是使用输出重定向了,所以,改造的代码如下:
index.php
<?php
$trace=”/wwwroot/log.txt”;

if(!is_writable($trace) || !is_readable($trace)) {
exit(“$trace must readable and writable”);
}

file_put_contents($trace,”);

echo `/usr/bin/sudo /home/nginx/sbin/nginx -t >$trace 2>&1`;

echo `top -b -n 1`;
echo file_get_contents($trace);

这是通过简接方式来观察输出的,类似这个现象的,还有使用top命令查看系统负载,top命令需要在终端窗口中执行,使用php执行shell_exec(“top -n 1”),给出的错误就是TERM environment variable not set. 解决办法就是使用-b参数执行top, 即shell_exec(“top -b -n 1”)

如果你有更好的方法,欢迎一起探讨,如果实验成功,也就可以通过web页面控制nginx了。