У меня есть сценарий с nginx/1.4.6
работает на Ubuntu 14.04
но с php/5.2.10
внутри chroot Ubuntu 9.10
(Кармическая коала).
Моя проблема в том, что все запросы к файлам php приводят к ужасному "No input file specified.
"
У меня есть сайт, хранящийся внутри chroot, поэтому его можно читать как с php внутри chroot jail, так и с nginx за пределами jail с этой настройкой:
From nginx' point of view:
/var/chroot/karmic/var/www/domains/dummysite/web:
. www-data:www-data drwxr-xr-x
index.php www-data:www-data -rw-r--r--
test.jpg www-data:www-data -rw-r--r--
И внутри chroot
From php's point of view:
/var/www/domains/dummysite/web:
. www-data:www-data drwxr-xr-x
index.php www-data:www-data -rw-r--r--
test.jpg www-data:www-data -rw-r--r--
И index.php
мертво просто!
<?php
echo '<h1>Hello World</h1> Foo bar...';
?>
Я запустил php-fcgi с spawn-fcgi из lighttpd, используя эту команду:
LANG=C chroot /var/chroot/karmic /usr/bin/spawn-fcgi -C 12 -a 127.0.0.1 -p 9000 -u www-data -g www-data -f /usr/bin/php5-cgi -P /var/run/fastcgi-php.pid
Nginx может успешно обслуживать статический test.jpg, но php-fcgi не может прочитать index.php
# /etc/nginx/site-enabled/dummysite -> /etc/nginx/site-available/dummysite:
server {
listen 80;
root /var/chroot/karmic/var/www/domains/dummysite/web;
server_name dummysite.wtf;
location / {
try_files $uri $uri/ /index.php?q=$uri&$args;
index index.php index.html;
allow all;
}
location ~ ^/index\.php {
fastcgi_pass 127.0.0.1:9000;
fastcgi_intercept_errors on;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
fastcgi_param SCRIPT_FILENAME /var/www/domains/dummysite/web$fastcgi_script_name;
fastcgi_param DOCUMENT_ROOT /var/www/domains/dummysite/web;
include fastcgi_params;
}
}
Насколько я понял, это должен быть правильный синтаксис. Я также пробовал с некоторыми вариациями, такими как $document_root$fastcgi_script_name
, без SCRIPT_NAME
или DOCUMENT_ROOT
набор и с SCRIPT_FILENAME
относительно DOCUMENT_ROOT
или root
внутри server
блок.
У меня нет open_basedir
ограничения, установленные в php.
Несмотря на то, что в php и nginx включено максимальное ведение журнала, я не получаю работоспособной информации ни в php.log, ни в nginx.error.log, ни в dummysite.wtf.error.log.
Я прибег к подключению к php-fcgi напрямую через cgi-fcgi
утилита напрямую, и я получаю такой ответ:
env -i SCRIPT_NAME=index.php DOCUMENT_ROOT=/var/www/domains/dummysite/web SCRIPT_FILENAME=/var/www/domains/dummysite/web/index.php QUERY_STRING= REQUEST_METHOD=GET cgi-fcgi -bind -connect 127.0.0.1:9000
Status: 404 Not Found
X-Powered-By: PHP/5.2.10-2ubuntu6
Content-type: text/html
No input file specified.
Тот же результат применяется ко всем вызовам с SCRIPT_FILENAME
установлен в
И я пробовал то же самое с различными DOCUMENT_ROOT
.
/etc/nginx/sites-enabled/dummysite -> /etc/nginx/sites-available/dummysite
...
location ~ \.php {
root /var/www/domains/dummysite/web;
fastcgi_pass 127.0.0.1:9000
include fastcgi_params;
}
...
И
/etc/nginx/fastcgi_params
...
fastcgi_param SCRIPT_NAME $document_root$fastcgi_script_name;
...
Хорошо, вот как я это решил (думал, может кому-то пригодится). Поскольку php-cgi не очень подробный, я прибег к использованию strace для записи файловых операций php на диск.
sudo strace -p <pid-of-first-php-process> -p <pid-of-2nd-php> ... -p <pid-of-nth-php> -e trace=all -s 4096
Затем я вызвал php-fcgi напрямую с помощью:
env -i SCRIPT_NAME=index.php DOCUMENT_ROOT=/var/www/domains/dummysite/web SCRIPT_FILENAME=/var/www/domains/dummysite/web/index.php QUERY_STRING= REQUEST_METHOD=GET cgi-fcgi -bind -connect 127.0.0.1:9000
И интересные строки в strace были
[pid 24822] read(3, "\v\tSCRIPT_NAMEindex.php\r\33DOCUMENT_ROOT/var/www/domains/dummysite/web\17%SCRIPT_FILENAME/var/www/domains/dummysite/web/index.php\f\0QUERY_STRING\16\3REQUEST_METHODGET\0", 152) = 152
[pid 24822] lstat("/var", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
[pid 24822] lstat("/var/www", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
[pid 24822] lstat("/var/www/domains", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
[pid 24822] lstat("/var/www/domains/dummysite", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
[pid 24822] lstat("/var/www/domains/dummysite/web", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
[pid 24822] lstat("/var/www/domains/dummysite/web/index.php", {st_mode=S_IFREG|0644, st_size=31, ...}) = 0
[pid 24822] open("/index.php", O_RDONLY) = -1 ENOENT (No such file or directory)
Хорошо, ясно, что он успешно попытался lstat [...]/web/index.php
(который имеет правильные разрешения 0644), но затем он попытался открыть /index.php
. Это привело меня к эксперименту с SCRIPT_NAME
, и вуаля!
env -i SCRIPT_NAME=/var/www/domains/dummysite/web/index.php DOCUMENT_ROOT=/var/www/domains/dummysite/web SCRIPT_FILENAME=/var/www/domains/dummysite/web/index.php QUERY_STRING= REQUEST_METHOD=GET cgi-fcgi -bind -connect 127.0.0.1:9000
X-Powered-By: PHP/5.2.10-2ubuntu6
Content-type: text/html
<h1>Hello World!</h1> Foo bar...
Так что мой первый проблема заключалась в том, что моя конфигурация nginx должна была читать
fastcgi_param SCRIPT_NAME /var/www/domains/dummysite/web$fastcgi_script_name;
# see what i did here ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Если честно; Понятия не имею, почему это так. Я думал цель SCRIPT_NAME
не указывает на файл, а просто указывает имя файла. Но, наверное, я неправильно понял его цель.
Но, к сожалению, мои проблемы еще не закончились. Когда я пытался curl http://dummysite.wtf/
, он все еще сказал No input file specified.
Итак, еще раз, strace
для спасения!
[pid 24819] read(3, "\r\33DOCUMENT_ROOT/var/www/domains/dummysite/web\17%SCRIPT_FILENAME/var/www/domains/dummysite/web/index.php\v%SCRIPT_NAME/var/www/domains/dummysite/web/index.php\f\0QUERY_STRING\16\3REQUEST_METHODGET\f\0CONTENT_TYPE\16\0CONTENT_LENGTH\0177SCRIPT_FILENAME/var/chroot/karmic/var/www/domains/dummysite/web/index.php\v\nSCRIPT_NAME/index.php\v\1REQUEST_URI/\f\nDOCUMENT_URI/index.php\r-DOCUMENT_ROOT/var/chroot/karmic/var/www/domains/dummysite/web\17\10SERVER_PROTOCOLHTTP/1.1\21\7GATEWAY_INTERFACECGI/1.1\17\vSERVER_SOFTWAREnginx/1.4.6\v\tREMOTE_ADDR127.0.0.1\v\5REMOTE_PORT46644\v\tSERVER_ADDR127.0.0.1\v\2SERVER_PORT80\v\nSERVER_NAMEdummysite.wtf\17\3REDIRECT_STATUS200\17\vHTTP_USER_AGENTcurl/7.35.0\t\nHTTP_HOSTdummysite.wtf\v\3HTTP_ACCEPT*/*\0\0\0\0\0\0", 672) = 672
И вот ответ, SCRIPT_NAME
, SCRIPT_FILENAME
и DOCUMENT_ROOT
появляется два раза, первый раз правильные, второй раз неправильное значение. Оказывается include fastcgi_params
директива в nginx server
блок сам вставит эти переменные, и поскольку я помещаю этот оператор включения последним в моем location
block, он фактически отменял мои предыдущие настройки.
Вот как я это исправил:
/etc/nginx/sites-enabled/dummysite -> /etc/nginx/sites-available/dummysite
...
location ~ \.php {
root /var/www/domains/dummysite/web;
# ^ This line will set the $document_root variable used later on
fastcgi_pass 127.0.0.1:9000
include fastcgi_params;
}
...
И в файле fastcgi_params, который включен, я изменил одну строку на эту
/etc/nginx/fastcgi_params
...
fastcgi_param SCRIPT_NAME $document_root$fastcgi_script_name;
# This is needed for chroot to work -> ^$document_root^
...
И наконец, славный успех!
$ curl http://dummysite.wtf
<h1>Hello World!</h1> Foo bar...
Это один из способов запустить фатально старую версию php внутри chrooted jail поверх современного программного обеспечения, такого как ubuntu 14.04 LTS и nginx 1.4.x :-)