【转】在nginx上运行cgi程序

我们用到的很多开源程序比如mailman, nagios等等,都有WEB端管理界面。在那个Apache一家独大的年代,这个问题可以很好解决,因为apache本身可以运行cgi程序。但随着nginx服务器的大规模应用,而恰好nginx又没有cgi模块,所以我们不得不采用一些变通的手段来解决它。

在网上广为流传的解决方法是一个老外写的perl脚本,但这个脚本本身有很多问题,而且需要在后台启动一个守护进程,本人对用perl写的网络服务守护进程的稳定性很怀疑,在看了它的代码后,发现用PHP即可很好的解决这个问题。

首先我们要明白的是CGI其实本质上就是一个普通的二进制程序,你可以在后台直接运行它。而服务器要做的事就是将WEB传递的变量作为参数传递给这个程序并执行,而将执行返回的结果显示到页面上。

明白了这个道理,我们就可以开始着手解决这个问题了。其过程无非就是将PHP作为一个proxy,使其运行指定的程序,并把程序输出结果echo出来。

那么首先第一步,我们就需要把原来的cgi请求全部转发到指定的php上,这一点在nginx里用rewrite就可以很简单的做到。我们把这个PHP脚本命名为cgi.php,把它随便放到一个你认为合适的位置,然后用rewrite将后缀为cgi的请求都转发到cgi.php上。以下为参考的配置格式

#rewrite cgi请求到cgi.php上,并把cgi文件名作为php的pathinfo
rewrite ^/nagios/cgi-bin/(.*) /cgi.php/$1 break;
 
location /nagios/
{
    gzip off;
    alias /usr/local/nagios/share/;
    index index.html index.htm index.php;
}
 
location ~ .*\.php(\/.*)*$ {
    fastcgi_pass    127.0.0.1:9000;
    fastcgi_index   index.php;
    include fcgi.conf;
    fastcgi_param SCRIPT_FILENAME /usr/local/nagios/share$fastcgi_script_name;
 
    #pathinfo必须设置
    fastcgi_param  PATH_INFO $fastcgi_script_name;
 
    #以下两个为cgi.php需要用到的变量名,分别为cgi程序目录,和cgi默认index程序
    fastcgi_param  CGI_BASE  /usr/local/nagios/sbin;
    fastcgi_param  CGI_INDEX status.cgi;
}

这是nagios的配置文件。
注意上面配置文件的注释部分,在你自己设置的时候必须填上合适的值。下面就是最重要的cgi.php文件了

 0) {
    $cgi_path = $cgi_path . '/' . array_shift($cgi_file_levels);

    if (is_file($cgi_path)) {
        $cgi_file_exists = true;
        break;
    }
}

if (!$cgi_file_exists) {
    die('NOT EXISTS PAGE!' . $cgi_file);
}

$cgi_pathinfo = '';
if (!empty($cgi_file_levels)) {
    $cgi_pathinfo = '/' . implode('/', $cgi_file_levels);
}

if (is_readable($cgi_path)) {

    $descriptorspec = array(
        0 => array("pipe", "r"),  // stdin is a pipe that the child will read from
        1 => array("pipe", "w"),  // stdout is a pipe that the child will write to
        2 => array("file", "/tmp/error-output.txt", "a") // stderr is a file to write to
    );

    $cwd = $cgi_base;
    $env = $_ENV;

    $env['SCRIPT_FILENAME'] = $cgi_path;
    $env['SCRIPT_NAME'] = $cgi_file;
    $env['DOCUMENT_ROOT'] = CGI_BASE;
    $env['PATH_INFO'] = $cgi_pathinfo;

    // http auth support (nagios etc.)
    if (isset($_SERVER['PHP_AUTH_USER'])) {
        $env['REMOTE_USER'] = $_SERVER['PHP_AUTH_USER'];
    }

    $process = proc_open($cgi_path, $descriptorspec, $pipes, $cwd, $env);
    if (is_resource($process)) {
        $stdin = file_get_contents("php://input");
        
        if (!empty($stdin)) {
            fwrite($pipes[0], $stdin);
            fclose($pipes[0]);
        }

        //stream_set_blocking($pipes[1], 0);
        stream_set_timeout($pipes[1], 3);
        $result = stream_get_contents($pipes[1]);
        fclose($pipes[1]);
        $return_value = proc_close($process);

        list($header, $body) = preg_split("/\r?\n\r?\n/", $result, 2);

        $headers = explode("\n", $header);
        foreach ($headers as $line) {
            header(trim($line));
        }

        echo $body;
    } else {
        die('ERROR APPLICATION!');
    }

} else {
    die('ERROR PAGE!' . $cgi_path);
}

转自:http://joyqi.com/development/nginx-run-cgi.html

网上看到的一个不错的PHP可逆字符加密算法。

测试了下,在没有原$ikey以及$key的情况下是无法对加密后的字符串进行逆运算的。

 /*
     * 加密,可逆
     * 可接受任何字符
     * 安全度非常高
     */
    function encrypt($txt, $key = 'anihc ctI')
    {
        $chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.";
        $ikey ="-x6g6ZWm2G9g_vr0Bo.pOq3kRIxsZ6rm";
        $nh1 = rand(0,64);
        $nh2 = rand(0,64);
        $nh3 = rand(0,64);
        $ch1 = $chars{$nh1};
        $ch2 = $chars{$nh2};
        $ch3 = $chars{$nh3};
        $nhnum = $nh1 + $nh2 + $nh3;
        $knum = 0;$i = 0;
        while(isset($key{$i})) $knum +=ord($key{$i++});
        $mdKey = substr(md5(md5(md5($key.$ch1).$ch2.$ikey).$ch3),$nhnum%8,$knum%8 + 16);
        $txt = base64_encode($txt);
        $txt = str_replace(array('+','/','='),array('-','_','.'),$txt);
        $tmp = '';
        $j=0;$k = 0;
        $tlen = strlen($txt);
        $klen = strlen($mdKey);
        for ($i=0; $i<$tlen; $i++) {
            $k = $k == $klen ? 0 : $k;
            $j = ($nhnum+strpos($chars,$txt{$i})+ord($mdKey{$k++}))%64;
            $tmp .= $chars{$j};
        }
        $tmplen = strlen($tmp);
        $tmp = substr_replace($tmp,$ch3,$nh2 % ++$tmplen,0);
        $tmp = substr_replace($tmp,$ch2,$nh1 % ++$tmplen,0);
        $tmp = substr_replace($tmp,$ch1,$knum % ++$tmplen,0);
        return $tmp;
    }
    
    /*
     * 解密
     * 
     */
     function decrypt($txt, $key = 'anihc ctI')
     {
        $chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.";
        $ikey ="-x6g6ZWm2G9g_vr0Bo.pOq3kRIxsZ6rm";
        $knum = 0;$i = 0;
        $tlen = strlen($txt);
        while(isset($key{$i})) $knum +=ord($key{$i++});
        $ch1 = $txt{$knum % $tlen};
        $nh1 = strpos($chars,$ch1); 
        $txt = substr_replace($txt,'',$knum % $tlen--,1);
        $ch2 = $txt{$nh1 % $tlen};
        $nh2 = strpos($chars,$ch2);
        $txt = substr_replace($txt,'',$nh1 % $tlen--,1);
        $ch3 = $txt{$nh2 % $tlen};
        $nh3 = strpos($chars,$ch3);
        $txt = substr_replace($txt,'',$nh2 % $tlen--,1);
        $nhnum = $nh1 + $nh2 + $nh3;
        $mdKey = substr(md5(md5(md5($key.$ch1).$ch2.$ikey).$ch3),$nhnum % 8,$knum % 8 + 16);
        $tmp = '';
        $j=0; $k = 0;
        $tlen = strlen($txt);
        $klen = strlen($mdKey);
        for ($i=0; $i<$tlen; $i++) {
            $k = $k == $klen ? 0 : $k;
            $j = strpos($chars,$txt{$i})-$nhnum - ord($mdKey{$k++});
            while ($j<0) $j+=64;
            $tmp .= $chars{$j};
        }
        $tmp = str_replace(array('-','_','.'),array('+','/','='),$tmp);
        return trim(base64_decode($tmp));
    }

原地址:http://bbs.phpchina.com/thread-37376-1-1.html