Apache 2.4 + PHP-FPM + ProxyPassMatch

我最近在本地机器上安装了Apache 2.4,并使用PHP-FPM与PHP 5.4.8一起安装。

一切都很顺利(过了一段时间…),但仍然有一个奇怪的错误:

我为这样的PHP-FPMconfiguration了Apache:

<VirtualHost *:80> ServerName localhost DocumentRoot "/Users/apfelbox/WebServer" ProxyPassMatch ^/(.*\.php(/.*)?)$ fcgi://127.0.0.1:9000/Users/apfelbox/WebServer/$1 </VirtualHost> 

它工作,例如,如果我打电话给http://localhost/info.php我得到正确的phpinfo() (它只是一个testing文件)。

如果我调用一个目录然而,我得到一个404身体File not found. 并在错误日志中:

 [Tue Nov 20 21:27:25.191625 2012] [proxy_fcgi:error] [pid 28997] [client ::1:57204] AH01071: Got error 'Primary script unknown\n' 

更新

我现在尝试使用mod_rewrite进行代理:

 <VirtualHost *:80> ServerName localhost DocumentRoot "/Users/apfelbox/WebServer" RewriteEngine on RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^/(.*\.php(/.*)?)$ fcgi://127.0.0.1:9000/Users/apfelbox/WebServer/$1 [L,P] </VirtualHost> 

但问题是:它总是redirect,因为在http://localhost/自动http://localhost/index.php被请求,因为

 DirectoryIndex index.php index.html 

更新2

好吧,所以我想“也许先检查一下是否有文件给代理服务器:

 <VirtualHost *:80> ServerName localhost DocumentRoot "/Users/apfelbox/WebServer" RewriteEngine on RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} -f RewriteRule ^/(.*\.php(/.*)?)$ fcgi://127.0.0.1:9000/Users/apfelbox/WebServer/$1 [L,P] </VirtualHost> 

现在完全重写不起作用了…

更新3

现在我有这个解决scheme:

 <VirtualHost *:80> ServerName localhost DocumentRoot "/Users/apfelbox/WebServer" RewriteEngine on RewriteCond /Users/apfelbox/WebServer/%{REQUEST_FILENAME} -f RewriteRule ^/(.*\.php(/.*)?)$ fcgi://127.0.0.1:9000/Users/apfelbox/WebServer/$1 [L,P] </VirtualHost> 

首先检查是否有文件传递给PHP-FPM(带有完整path和绝对path),然后进行重写。

在子目录中使用URL重写时,这不起作用,对于像http://localhost/index.php/test/这样的URL也失败了。


有任何想法吗?

    经过几个小时的search和阅读Apache文档,我想出了一个允许使用池的解决scheme,并且允许.htaccess中的Rewrite指令即使在URL包含.php文件时也可以工作。

     <VirtualHost ...> ... # This is to forward all PHP to php-fpm. <FilesMatch \.php$> SetHandler "proxy:unix:/path/to/socket.sock|fcgi://unique-domain-name-string/" </FilesMatch> # Set some proxy properties (the string "unique-domain-name-string" should match # the one set in the FilesMatch directive. <Proxy fcgi://unique-domain-name-string> ProxySet connectiontimeout=5 timeout=240 </Proxy> # If the php file doesn't exist, disable the proxy handler. # This will allow .htaccess rewrite rules to work and # the client will see the default 404 page of Apache RewriteCond %{REQUEST_FILENAME} \.php$ RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_URI} !-f RewriteRule (.*) - [H=text/html] </VirtualHost> 

    根据Apache文档,SetHandler代理参数需要Apache HTTP Server 2.4.10。

    我希望这个解决scheme也能帮助你。

    我昨天也遇到了这个问题–Apache 2.4从Debian /实验中移出Debian / unstable,迫使我处理这个新东西; 当然不在我们的生产服务器上)。

    在阅读了数以百万计的网站之后,Apache文档,错误报告和错误日志中的debugging输出,我终于得到了它的工作。 不, 没有套接字的FPM支持 。 Debian的默认configuration已经有一段时间了,所以Debian的用户也必须改变它。

    以下是适用于CakePHP站点和PHPMyAdmin(后者需要一些configuration,如果你使用Debian软件包,虽然),所以我可以确认, mod_rewrite仍然按照预期做的花式URL重写。

    通知DirectoryIndex index.php ,这可能是你的configuration没有为“文件夹”工作的原因(至less这是什么在这里不工作)。

    我仍然File not found. 对于目录,但只有在没有可以parsing的索引文件的情况下。 也想摆脱这一点,但现在并不那么重要。


     <VirtualHost *:80> ServerName site.localhost DocumentRoot /your/site/webroot <Directory /> Options FollowSymlinks DirectoryIndex index.php AllowOverride All Require all granted </Directory> <LocationMatch "^(.*\.php)$"> ProxyPass fcgi://127.0.0.1:9000/your/site/webroot </LocationMatch> LogLevel debug ErrorLog /your/site/logs/error.log CustomLog /your/site/logs/access.log combined </VirtualHost> 

    上面的虚拟主机和根目录下的.htaccess完全兼容,就像这样:

     <IfModule mod_rewrite.c> RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^(.*)$ index.php [QSA,L] </IfModule> 

    虽然我只是重写到根目录的index.php,但是我不完全明白你URL rewriting inside a subdirectory意思。


    (哦,您必须确保Xdebug不会与您的系统上的FPM冲突,他们希望使用相同的端口。

    这是我得到的。 这似乎工作确定。 我把Drupal放在一个子目录下,重写工作,目录索引工作,PATH_INFO工作。

     RewriteEngine On RewriteCond %{REQUEST_FILENAME} ^/((.*\.php)(/.*)?)$ RewriteCond %2 -f RewriteRule . fcgi://127.0.0.1:9000/%1 [L,P] RewriteOptions Inherit 

    我试图做这样的事情,而不重写(“如果”等),但我什么都不能工作。

    编辑:请注意,如果你要实现这个共享托pipe服务提供商,这可能是一个安全问题。 它将允许用户将PHP脚本传递给任意的fcgi代理。 如果每个用户都有一个独立的池,那么就会导致特权提升。

    所有你需要做的是设置:

      ProxyErrorOverride on 

    不要忘记设置客户页面:

     ErrorDocument 404 /path/to/error_page_file 

    解决这个问题的最佳方法是打开mod_proxy和mod_rewrite和php-fpm的debugging日志。 在apache 2.4中,现在只能打开特定模块的debugging日志。 http://httpd.apache.org/docs/current/mod/core.html#loglevel每个模块和每个目录的configuration可在Apache HTTP Server 2.3.6及更高版本中使用

    也许你在目录上双斜杠?

    这是我使用的,它工作正常:

     <LocationMatch ^(.*\.php)$> ProxyPass fcgi://127.0.0.1:9000/home/DOMAINUSER/public_html$1 </LocationMatch> 

    又一个解决scheme(需要Apache> = 2.4.10) – 在虚拟主机内部:

     # define worker <Proxy "unix:/var/run/php5-fpm-wp.bbox.nuxwin.com.sock|fcgi://domain.tld" retry=0> ProxySet connectiontimeout=5 timeout=7200 </Proxy> <If "%{REQUEST_FILENAME} =~ /\.php$/ && -f %{REQUEST_FILENAME}"> SetEnvIfNoCase ^Authorization$ "(.+)" HTTP_AUTHORIZATION=$1 SetHandler proxy:fcgi://domain.tld </If> 

    所以在这里,PHP的fcgi处理程序只有在文件存在并且名称与PHP文件扩展名匹配时才会被设置。

    顺便说一句:对于那些有想法将ProxyErrorOverride设置为On的请注意,这是一个坏主意。 这个指令的用法不是没有造成任何问题。 例如,任何发送诸如503的HTTP代码的PHP应用程序都会导致意外的结果。 在任何情况下,缺省的error handling程序都会涉及,而对于提供API的PHP应用程序来说,这确实是一个不好的行为。

    我在处理这个问题时遇到的一件事是,如果你使用以下的组合:

     chroot = /path/to/site chdir = / 

    在您的fpm池configuration中,不要将完整path传递给ProxyPass指令。

     ProxyPass fcgi://127.0.0.1:9020/$1 

    但是 – 只有 – 如果该端口上的池是chroot。

    Linode在这个问题上有一个很好的教程

    基本上你为整个服务器设置一个处理程序,它可以捕获任何php脚本并将它们传递给fast-cgi。

    我不确定问题是否有关系,但是我在这里find了一个部分工作的解决scheme:

    https://stackoverflow.com/questions/44054617/mod-rewrite-in-2-4-25-triggering-fcgi-primary-script-unknown-error-in-php-fpm

    这个技巧似乎在增加一个? 字符在.htaccess重写规则,例如使用:

     RewriteRule ^(.*)$ index.php?/$1 [L,NS] 

    代替:

     RewriteRule ^(.*)$ index.php/$1 [L,NS] 

    问题的根源似乎是Apache 2.4.25的mod_rewrite的一个变化。 我已经使用了Apache trace1日志级别来观察在通过index.php / $ 1之后传递$ 1到php-fpm的“循环”。 $ 1生成“AH01071:有错误”主脚本未知\ n'“错误。

    希望这个小小的消息帮助别人解决他们的问题。