я бегу 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;
}
}
Вот что я получаю в браузере, если перехожу на URL 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
директивы, веб-сервер возвращает 403
. Вопрос в том ... как получилось?
php
хотя работает как положено: второй SCRIPT_FILENAME
отменяет первый.
Библиотека fastcgi просто передает любые параметры, которые ей были заданы, в environ
указатель. getenv()
как используется fcgiwrap
использует любую переменную среды, которая была первой (оптимизация?). Вероятно, что 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
дано что ли.