我正在运行Debian 6.0.3
( squeeze
)、nginx-0.7.67
、fcgiwrap-1.0-1+squeeze1
。以下是测试脚本:
#!/usr/bin/perl
use 5.010;
use warnings;
use strict;
use Data::Dumper;
print "Content-Type: text/html\n\n";
say Dumper {map {$_ => $ENV{$_}} 'SCRIPT_NAME', 'DOCUMENT_ROOT', 'WHATEVER'};
say "$<, $>, $(, $)";
配置如下nginx
:
server {
server_name domain.com;
root /home/yuri/6;
access_log /var/log/nginx/domain.com-access.log;
error_log /var/log/nginx/domain.com-error.log;
location /cgi-bin/ {
fastcgi_pass unix:/var/run/fcgiwrap.socket;
fastcgi_param DOCUMENT_ROOT $document_root;
fastcgi_param DOCUMENT_ROOT /home/yuri/7/;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
fastcgi_param WHATEVER 1;
fastcgi_param WHATEVER 2;
}
location /1.php {
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_param PHP_ADMIN_VALUE cgi.fix_pathinfo=1;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param SCRIPT_FILENAME whatever;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
以下是我访问网址时在浏览器中获得的结果http://domain.com/cgi-bin/1.pl:
$VAR1 = { 'SCRIPT_NAME' => '/cgi-bin/1.pl', 'DOCUMENT_ROOT' => '/home/yuri/7/', 'WHATEVER' => '2' };
看起来,它fcgiwrap
使用第一个DOCUMENT_ROOT
来查找脚本,但脚本获取参数的最后一个值。如果您更改DOCUMENT_ROOT
指令的顺序,Web 服务器将返回403
。问题是...为什么会这样?
php
尽管按预期工作:第二个SCRIPT_FILENAME
覆盖了第一个。
答案1
fastcgi 库只是将给定的任何参数传递给指针environ
。as getenv()
used byfcgiwrap
使用最先出现的任何环境变量(优化?)。PHP FPM 可能将此环境视为数组数据类型,任何后一个键都会覆盖第一个键。
您不应该依赖顺序,并确保只有一个键。我没有看过 FastCGI 规范,不知道是否记录了正确的行为。
至于为什么你得到 403,我猜是没有/home/yuri/7/1.pl
文件。(记住,第一个参数与 fcgiwrap 匹配)。由于它不可执行,fcgiwrap 返回 403。
测试
以下补丁打印出给定的环境FCGI_Accept()
:
diff --git a/fcgiwrap.c b/fcgiwrap.c
index e86ff9d..0dff2e6 100644
--- a/fcgiwrap.c
+++ b/fcgiwrap.c
@@ -470,6 +470,11 @@ static void inherit_environment(void)
char * const * p;
char *q;
+ for (p = environ; *p; p++)
+ fprintf(stderr, "ENV: %s\n", *p);
+
+ fprintf(stderr, "ENV[FOO] = %s\n", getenv("FOO"));
+
for (p = inherited_environ; *p; p++) {
q = strchr(*p, '=');
if (!q) {
测试所用的nginx配置:
events {
worker_connections 768;
}
pid pid;
error_log error_log;
http {
server {
access_log off;
listen 5555;
location / {
fastcgi_param FOO BAR;
fastcgi_param FOO BARRED;
fastcgi_pass unix:/tmp/sock;
}
}
}
启动服务器的命令(假设nginx.conf
在当前目录中):
$ nginx -p . -c nginx.conf
$ env -i ./fcgiwrap -p /dev/null -s unix:/tmp/sock
现在,运行curl http://localhost:5555/
并且 stderr 将打印:
ENV: FCGI_ROLE=RESPONDER
ENV: FOO=BAR
ENV: FOO=BARRED
ENV: HTTP_USER_AGENT=curl/7.30.0
ENV: HTTP_HOST=localhost:5555
ENV: HTTP_ACCEPT=*/*
ENV[FOO] = BAR
Cannot get script name, are DOCUMENT_ROOT and SCRIPT_NAME (or SCRIPT_FILENAME) set and is the script executable?
另外,这是一个开发版本。当前稳定版本 (1.1.0) 不包含-p
上述参数。对于结果来说,这并不重要,您也可以将其删除并收到未SCRIPT_NAME
给出任何错误之类的错误。