“Nenhum arquivo de entrada especificado” ao executar o php em fastcgi dentro do chroot sob nginx fora do chroot

1

Eu tenho um cenário com nginx/1.4.6 sendo executado em Ubuntu 14.04 , mas com php/5.2.10 dentro de um chroot Ubuntu 9.10 (Karmic Koala).

Meu problema é que todas as solicitações para arquivos php resultam no " No input file specified. "

Eu tenho o site armazenado dentro do chroot, então é legível tanto do php dentro da jaula do chroot quanto do nginx fora da cadeia com esta configuração:

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--

E dentro do 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--

E index.php é muito simples!

<?php
    echo '<h1>Hello World</h1> Foo bar...';
?>

Eu iniciei o php-fcgi com o spawn-fcgi do lighttpd usando este comando:

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

O Nginx pode servir com sucesso o static test.jpg, mas o php-fcgi não consegue ler 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;
    }
}

Tanto quanto eu entendi, esta deve ser a sintaxe correta. Eu também tentei com algumas variações como $document_root$fastcgi_script_name , sem SCRIPT_NAME ou DOCUMENT_ROOT set e com SCRIPT_FILENAME relativo a DOCUMENT_ROOT ou root dentro do bloco server .

Não tenho restrições open_basedir definidas no php.

Apesar de ter log máximo ativado em php e nginx, não obtenho informações viáveis em php.log, nginx.error.log ou dummysite.wtf.error.log.

Eu tenho recorrido à conexão ao php-fcgi diretamente com o utilitário cgi-fcgi diretamente e esta é a resposta que recebo:

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.

O mesmo resultado se aplica a todas as chamadas com SCRIPT_FILENAME definido como

  • /index.php
  • /web/index.php
  • /dummysite/web/index.php
  • /domains/dummysite/web/index.php
  • /www/domains/dummysite/web/index.php
  • /var/www/domains/dummysite/web/index.php
  • /karmic/var/www/domains/dummysite/web/index.php
  • /chroot/karmic/var/www/domains/dummysite/web/index.php
  • /var/chroot/karmic/var/www/domains/dummysite/web/index.php

E eu tentei o mesmo com vários DOCUMENT_ROOT .

    
por Aron Cederholm 20.11.2014 / 12:55

1 resposta

3

TL; DR

/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;
}
...

e

/etc/nginx/fastcgi_params
...
fastcgi_param SCRIPT_NAME $document_root$fastcgi_script_name;
...

Solução longa

Ok, foi assim que resolvi (achei que poderia ser útil para alguém). Como o php-cgi não é muito detalhado, recorri ao uso do strace para capturar as operações de arquivos do php no disco.

 sudo strace -p <pid-of-first-php-process> -p <pid-of-2nd-php> ... -p <pid-of-nth-php> -e trace=all -s 4096

Então eu chamei o php-fcgi diretamente com:

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

E as linhas interessantes na strace eram

[pid 24822] read(3, "\v\tSCRIPT_NAMEindex.php\rDOCUMENT_ROOT/var/www/domains/dummysite/web%SCRIPT_FILENAME/var/www/domains/dummysite/web/index.php\f
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...
QUERY_STRINGREQUEST_METHODGET
        fastcgi_param SCRIPT_NAME /var/www/domains/dummysite/web$fastcgi_script_name;
#           see what i did here   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
", 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)

Ok, tão claramente, tentou com sucesso lstat [...]/web/index.php (que tem as devidas 0644 permissões), mas depois tentou abrir /index.php . Isso me levou a experimentar com SCRIPT_NAME e voila!

[pid 24819] read(3, "\rDOCUMENT_ROOT/var/www/domains/dummysite/web%SCRIPT_FILENAME/var/www/domains/dummysite/web/index.php\v%SCRIPT_NAME/var/www/domains/dummysite/web/index.php\f
/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;
}
...
QUERY_STRINGREQUEST_METHODGET\f
/etc/nginx/fastcgi_params
...
fastcgi_param   SCRIPT_NAME             $document_root$fastcgi_script_name;
# This is needed for chroot to work -> ^$document_root^ 
...
CONTENT_TYPE
$ curl http://dummysite.wtf
<h1>Hello World!</h1> Foo bar...
CONTENT_LENGTH77SCRIPT_FILENAME/var/chroot/karmic/var/www/domains/dummysite/web/index.php\v\nSCRIPT_NAME/index.php\vREQUEST_URI/\f\nDOCUMENT_URI/index.php\r-DOCUMENT_ROOT/var/chroot/karmic/var/www/domains/dummysite/webSERVER_PROTOCOLHTTP/1.1GATEWAY_INTERFACECGI/1.1\vSERVER_SOFTWAREnginx/1.4.6\v\tREMOTE_ADDR127.0.0.1\vREMOTE_PORT46644\v\tSERVER_ADDR127.0.0.1\vSERVER_PORT80\v\nSERVER_NAMEdummysite.wtfREDIRECT_STATUS200\vHTTP_USER_AGENTcurl/7.35.0\t\nHTTP_HOSTdummysite.wtf\vHTTP_ACCEPT*/*
/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;
...
 sudo strace -p <pid-of-first-php-process> -p <pid-of-2nd-php> ... -p <pid-of-nth-php> -e trace=all -s 4096
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
[pid 24822] read(3, "\v\tSCRIPT_NAMEindex.php\rDOCUMENT_ROOT/var/www/domains/dummysite/web%SCRIPT_FILENAME/var/www/domains/dummysite/web/index.php\f
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...
QUERY_STRINGREQUEST_METHODGET
        fastcgi_param SCRIPT_NAME /var/www/domains/dummysite/web$fastcgi_script_name;
#           see what i did here   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
", 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)
[pid 24819] read(3, "\rDOCUMENT_ROOT/var/www/domains/dummysite/web%SCRIPT_FILENAME/var/www/domains/dummysite/web/index.php\v%SCRIPT_NAME/var/www/domains/dummysite/web/index.php\f
/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;
}
...
QUERY_STRINGREQUEST_METHODGET\f
/etc/nginx/fastcgi_params
...
fastcgi_param   SCRIPT_NAME             $document_root$fastcgi_script_name;
# This is needed for chroot to work -> ^$document_root^ 
...
CONTENT_TYPE
$ curl http://dummysite.wtf
<h1>Hello World!</h1> Foo bar...
CONTENT_LENGTH77SCRIPT_FILENAME/var/chroot/karmic/var/www/domains/dummysite/web/index.php\v\nSCRIPT_NAME/index.php\vREQUEST_URI/\f\nDOCUMENT_URI/index.php\r-DOCUMENT_ROOT/var/chroot/karmic/var/www/domains/dummysite/webSERVER_PROTOCOLHTTP/1.1GATEWAY_INTERFACECGI/1.1\vSERVER_SOFTWAREnginx/1.4.6\v\tREMOTE_ADDR127.0.0.1\vREMOTE_PORT46644\v\tSERVER_ADDR127.0.0.1\vSERVER_PORT80\v\nSERVER_NAMEdummysite.wtfREDIRECT_STATUS200\vHTTP_USER_AGENTcurl/7.35.0\t\nHTTP_HOSTdummysite.wtf\vHTTP_ACCEPT*/*%pre%%pre%%pre%%pre%%pre%%pre%", 672) = 672
", 672) = 672

Então, meu primeiro problema foi que minha configuração do nginx deve ser lida

%pre%

Para ser honesto; Eu não tenho ideia do porquê disso. Eu pensei que o objetivo de SCRIPT_NAME não é apontar para o arquivo, mas apenas indicar o nome do arquivo. Mas acho que devo ter entendido mal o seu propósito.

Mas, infelizmente, meus problemas ainda não acabaram. Para quando eu tentei curl http://dummysite.wtf/ , ele ainda dizia No input file specified.

Então, mais uma vez, strace para o resgate!

%pre%

E aí está a resposta, SCRIPT_NAME , SCRIPT_FILENAME e DOCUMENT_ROOT aparecem duas vezes, a primeira vez que estão corretas, a segunda vez com um valor incorreto. Acontece que a diretiva include fastcgi_params no bloco nginx server irá inserir essas variáveis em si e, como coloquei essa instrução include por último no bloco location , ela estava efetivamente substituindo minhas configurações anteriores.

Foi assim que consertei isso:

%pre%

E no arquivo fastcgi_params que está incluído, eu mudei uma linha para esta

%pre%

E finalmente, sucesso glorioso !

%pre%

Esta é uma maneira de executar uma versão php fatalmente velha dentro de uma cadeia chrooted em cima de softwares modernos como o Ubuntu 14.04 LTS e o nginx 1.4.x: -)

    
por 20.11.2014 / 12:55