Apache 2.4 + Windows XP上的多个PHP,带有一个核心API

问题描述 投票:0回答:1

为长时间阅读道歉,但我认为尽可能详细地包含尽可能详细的内容,而不是等待人们要求各种配置,日志等。

我有一台旧PC运行XP并安装了One Core API。

我正在使用它来测试具有多个PHP版本的Apache 2.4.38。一切都很完美,除了PHP 7.2和7.3为所有php文件返回404状态,并显示消息“未指定输入文件”。 Apache日志,如果我正确读取它们,则表明正在正确调用php-cgi.exe,并且即使文件存在也负责返回此状态。

SysInternals Process Monitor显示Apache的“httpd.exe”发现php文件没问题。在此之后,所有高达7.1的PHP版本都会检查“user.ini”和请求的php文件。然而,版本7.2和7.3仅检查“user.ini”,并且根本不尝试访问所请求的php文件。尽管如此,它们返回404错误,并显示消息“未指定输入文件”。

我现在已经将所有内容扩展到了一个简单的工作配置,如果有人想自己尝试一下,这些配置如下所示。 Apache和所有PHP版本都安装在根据其5位版本ID命名的文件夹中。有一个测试站点“test2.local”,其中包含一个索引文件。

  • 一切都是32位,所有PHP版本都是非线程安全(nts)版本。
  • Apache是​​Apache Lounge的当前版本(截至2019年2月8日)。
  • PHP <= 5.5是每个版本的最后一次构建。
  • PHP> = 5.6是所有当前版本(截至2019年2月8日)。
  • PHP构建都是来自php.net的预构建二进制文件。
  • 所有VC运行时都已安装并正常运行(2008,2012,2017)。
  • 为了简单起见,没有加载PHP扩展。
  • 所有PHP版本都在自己的文件夹中有自己的“php.ini”文件。
  • 所有二进制文件都已经过检查,除了通常的罪魁祸首(依赖于未安装的第三方软件的PHP扩展)之外,没有遗漏的依赖项。
  • 所有版本的“php.exe”和“php-cgi.exe”都可以从命令行完美运行,并且没有任何错误记录到PHP错误日志中。
  • 所有版本的“php-cgi.exe”高达7.1都与Apache完美配合,也没有记录任何错误。
  • “php-cgi.exe”的版本7.2和7.3显示Apache错误日志中所有php文件的404状态,但同样,不要将任何内容记录到PHP错误日志中。

文件夹结构:

Apache (Logs folder contains both Apache and PHP logs):
    2.4.38 ....... D:\www\APACHE\20438
    Logs ......... D:\www\APACHE\logs
PHP:
    5.2.17 ....... D:\www\PHP\50217
    5.3.29 ....... D:\www\PHP\50329
    5.4.45 ....... D:\www\PHP\50445
    5.5.17 ....... D:\www\PHP\50538
    5.6.40 ....... D:\www\PHP\50640
    7.0.33 ....... D:\www\PHP\70033
    7.1.26 ....... D:\www\PHP\70126
    7.2.15 ....... D:\www\PHP\70215
    7.3.02 ....... D:\www\PHP\70302
Virtual Hosts:
    test2.local .. D:\www\sites\test2  (contains 1 file: index.php)

“D:\ www \ sites \ test2 \ index.php”的内容:

<?php
echo <<<EOF
<!DOCTYPE html>
<html>
<head><meta charset="us-ascii"><title>test2.local</title></head>
<body><h1>test2.local</h1></body>
</html>
EOF;
?>

Apache配置尽可能小,我认为它可以是:

# Apache 2.4.38 Configuration

Define SRVROOT "D:\www\APACHE\20438"
Define LOGPATH "D:\www\APACHE\logs"
Define DOCROOT "D:\www\sites"

# Here I simply uncomment the PHP version I want to test and then restart Apache.
#Define PHPVER 50217
#Define PHPVER 50329
#Define PHPVER 50445
#Define PHPVER 50538
#Define PHPVER 50640
#Define PHPVER 70033
Define PHPVER 70126
#Define PHPVER 70215
#Define PHPVER 70302

ErrorLog "${LOGPATH}\apache_20438.txt"
LogLevel trace8

ServerRoot "${SRVROOT}"
DocumentRoot "${DOCROOT}"
ServerName apache.local
Listen 192.168.0.1:80

LoadModule access_compat_module     modules/mod_access_compat.so
LoadModule authz_core_module        modules/mod_authz_core.so
LoadModule dir_module               modules/mod_dir.so
LoadModule mime_module              modules/mod_mime.so
LoadModule fcgid_module             modules/mod_fcgid.so

<Directory />
    Options Indexes ExecCGI FollowSymLinks
    AllowOverride None
    Require all granted
</Directory>

TypesConfig conf/mime.types
AddType application/x-httpd-php .php
DirectoryIndex index.php index.htm

FcgidInitialEnv SystemRoot "C:\Windows"
FcgidInitialEnv SystemDrive "C:"
FcgidInitialEnv TEMP "D:\www\PHP\${PHPVER}\tmp"
FcgidInitialEnv TMP "D:\www\PHP\${PHPVER}\tmp"
FcgidInitialEnv windir "C:\WINDOWS"
FcgidInitialEnv PHPRC "D:\www\PHP\${PHPVER}"
FcgidInitialEnv PATH "D:\www\PHP\${PHPVER};D:\www\PHP\${PHPVER}\ext;${PATH}"
FcgidInitialEnv PHP_FCGI_MAX_REQUESTS 1000
FcgidMaxRequestsPerProcess 10
FcgidMaxProcesses 15
FcgidIOTimeout 50
FcgidIdleTimeout 50
FcgidFixPathinfo 0
FcgidWrapper "D:/www/PHP/${PHPVER}/php-cgi.exe" .php
AddHandler fcgid-script .php

<VirtualHost *:80>
    # This forces unknown addresses to the default site.
    DocumentRoot "${DOCROOT}"
</VirtualHost>

<VirtualHost *:80>
    DocumentRoot "${DOCROOT}\test2"
    ServerName test2.local
</VirtualHost>

所有PHP配置都是相同的,只是版本7.1以后包含“default_charset”指令,如果不存在,则会导致500内部服务器错误。我发现这个解决方案适用于7.1(由于php.net上的迁移页面,最初也没有工作,但现在也没有)。我找不到任何表明7.2或7.3需要进一步更改的内容。

“php.ini”文件的完整内容如下(XXXXX = Version ID):

[PHP]
; Paths at the top for ease of copying configurations, which
; in this case you would only need to edit these two lines.
extension_dir="D:/www/PHP/XXXXX/ext"
error_log="D:/www/APACHE/logs/php_XXXXX.txt"

allow_url_fopen=On
allow_url_include=Off
asp_tags=Off
auto_globals_jit=On
cgi.fix_pathinfo=0
cgi.force_redirect=0

; default_charset must be set for PHP 7.1 onwards
default_charset="us-ascii"

default_mimetype="text/html"
default_socket_timeout=60
display_errors=On
display_startup_errors=On
engine=On
error_reporting=E_ALL
expose_php=On
html_errors=Off
ignore_repeated_errors=On
ignore_repeated_source=Off
implicit_flush=Off
log_errors=On
log_errors_max_len=1024
magic_quotes_gpc=Off
magic_quotes_runtime=Off
magic_quotes_sybase=Off
max_execution_time=0
max_input_time=60
memory_limit=128M
output_buffering=On
post_max_size=16M
precision=14
register_argc_argv=Off
register_globals=Off
register_long_arrays=Off
report_memleaks=On
request_order="GP"
serialize_precision=100
short_open_tag=On

; Default value for user_ini.filename is ".user.ini". I remove the first
; period here for ease. (In XP, creating files that begin with a period
; usually causes an error unless done from the command prompt.)
user_ini.filename="user.ini"

variables_order="EGPCS"
y2k_compliance=On
zlib.output_compression=Off

(我已经在很多地方读过修复路径信息设置应该是“FcgidFixPathinfo = 1”和“cgi.fix_pathinfo = 1”,但我试过这个没有成功。实际上,打开这些设置只会产生效果在所有正在运行的PHP版本中,“SCRIPT_NAME”和“PHP_SELF”变量都被设置为“D:/index.php”而不是“/index.php”。换句话说,打开它会破坏事物而不是修复任何东西。 )

随着启动和运行,测试就像在“http://test2.local/index.php”请求页面一样简单。 PHP <= 7.1的结果都是一样的,所以我将使用7.1日志。同样,7.2和7.3的结果是相同的,所以我将使用7.2日志。没有PHP版本记录任何错误或崩溃。每个版本在第一个请求上成功加载,并继续愉快地运行,直到Apache重新启动。

Apache启动日志(所有PHP版本):

Setting LogLevel for all modules to trace8
Setting LogLevel for all modules to trace8
AH00455: Apache/2.4.38 (Win32) mod_fcgid/2.3.9 configured -- resuming normal operations
AH00456: Apache Lounge VC15 Server built: Jan 18 2019 12:31:19
AH00094: Command line: 'D:\\www\\APACHE\\20438\\bin\\httpd.exe -d D:/www/APACHE/20438 -E D:/www/APACHE/logs/apache_20438.txt'
AH02639: Using SO_REUSEPORT: no (0)
AH00418: Parent: Created child process 3428
AH00402: Parent: Sent the scoreboard to the child
Setting LogLevel for all modules to trace8
Setting LogLevel for all modules to trace8
AH00453: Child process is running
AH00391: Child: Retrieved our scoreboard from the parent.
AH00403: Child: Waiting for data for listening socket 192.168.0.1:80
AH00408: Parent: Duplicating socket 324 (192.168.0.1:80) and sending it to child process 3428
AH00411: Parent: Sent 1 listeners to child 3428
AH00407: Child: retrieved 1 listeners from parent
AH00352: Child: Acquired the start mutex.
AH00354: Child: Starting 64 worker threads.
mpm child 3428 (gen 0/slot 0) started
AH00334: Child: Accept thread listening on 192.168.0.1:80 using AcceptFilter connect

用于请求“http://test2.local/index.php”的Apache日志(PHP 7.1):

Request received from client: GET /index.php HTTP/1.1
Headers received from client:
  Host: test2.local
  User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:52.0) Gecko/20100101 Firefox/52.0
  Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
  Accept-Language: en-GB,en;q=0.5
  Accept-Encoding: gzip, deflate
  DNT: 1
  Connection: keep-alive
  Upgrade-Insecure-Requests: 1
AH01626: authorization result of Require all granted: granted
AH01626: authorization result of <RequireAny>: granted
request authorized without authentication by access_checker_ex hook: /index.php
mod_fcgid: server test2.local:D:/www/PHP/70126/php-cgi.exe(532) started
Headers from script 'index.php':
  X-Powered-By: PHP/7.1.26
  Content-type: text/html; charset=us-ascii
Response sent with status 200, headers:
  Date: Mon, 18 Feb 2019 01:31:39 GMT
  Server: Apache/2.4.38 (Win32) mod_fcgid/2.3.9
  X-Powered-By: PHP/7.1.26
  Keep-Alive: timeout=5, max=100
  Connection: Keep-Alive
  Transfer-Encoding: chunked
  Content-Type: text/html; charset=us-ascii
brigade contains: bytes: 256, non-file bytes: 256, eor buckets: 0, morphing buckets: 0
brigade contains: bytes: 395, non-file bytes: 395, eor buckets: 0, morphing buckets: 0
brigade contains: bytes: 400, non-file bytes: 400, eor buckets: 0, morphing buckets: 0
brigade contains: bytes: 400, non-file bytes: 400, eor buckets: 1, morphing buckets: 0
will flush because of FLUSH bucket
seen in brigade so far: bytes: 400, non-file bytes: 400, eor buckets: 1, morphing buckets: 0
flushing now
total bytes written: 400
brigade contains: bytes: 0, non-file bytes: 0, eor buckets: 0, morphing buckets: 0
will flush because of FLUSH bucket
seen in brigade so far: bytes: 0, non-file bytes: 0, eor buckets: 0, morphing buckets: 0
flushing now
total bytes written: 400
brigade contains: bytes: 0, non-file bytes: 0, eor buckets: 0, morphing buckets: 0

进程监视器“http://test2.local/index.php”的屏幕截图(PHP 7.1):

Process Monitor Screenshot (PHP 7.1)

用于请求“http://test2.local/index.php”的Apache日志(PHP 7.2):

Request received from client: GET /index.php HTTP/1.1
Headers received from client:
  Host: test2.local
  User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:52.0) Gecko/20100101 Firefox/52.0
  Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
  Accept-Language: en-GB,en;q=0.5
  Accept-Encoding: gzip, deflate
  DNT: 1
  Connection: keep-alive
  Upgrade-Insecure-Requests: 1
AH01626: authorization result of Require all granted: granted
AH01626: authorization result of <RequireAny>: granted
request authorized without authentication by access_checker_ex hook: /index.php
mod_fcgid: server test2.local:D:/www/PHP/70215/php-cgi.exe(808) started
Headers from script 'index.php':
  Status: 404 Not Found
Status line from script 'index.php': 404 Not Found
  X-Powered-By: PHP/7.2.15
  Content-type: text/html; charset=us-ascii
Response sent with status 404, headers:
  Date: Mon, 18 Feb 2019 01:34:54 GMT
  Server: Apache/2.4.38 (Win32) mod_fcgid/2.3.9
  X-Powered-By: PHP/7.2.15
  Keep-Alive: timeout=5, max=100
  Connection: Keep-Alive
  Transfer-Encoding: chunked
  Content-Type: text/html; charset=us-ascii
brigade contains: bytes: 263, non-file bytes: 263, eor buckets: 0, morphing buckets: 0
brigade contains: bytes: 294, non-file bytes: 294, eor buckets: 0, morphing buckets: 0
brigade contains: bytes: 299, non-file bytes: 299, eor buckets: 0, morphing buckets: 0
brigade contains: bytes: 299, non-file bytes: 299, eor buckets: 1, morphing buckets: 0
will flush because of FLUSH bucket
seen in brigade so far: bytes: 299, non-file bytes: 299, eor buckets: 1, morphing buckets: 0
flushing now
total bytes written: 299
brigade contains: bytes: 0, non-file bytes: 0, eor buckets: 0, morphing buckets: 0
will flush because of FLUSH bucket
seen in brigade so far: bytes: 0, non-file bytes: 0, eor buckets: 0, morphing buckets: 0
flushing now
total bytes written: 299
brigade contains: bytes: 0, non-file bytes: 0, eor buckets: 0, morphing buckets: 0

Process Monitor的屏幕截图“http://test2.local/index.php”(PHP 7.2):

Process Monitor Screenshot (PHP 7.2)

任何帮助搞清楚这个谜团的人都会非常感激。再次为冗长的阅读道歉。

apache windows-xp php-7.2 php-7.3
1个回答
0
投票

好吧,对于任何有兴趣的人,我终于找到了问题,如果你愿意自己重新编译PHP,你可以让它工作。

罪魁祸首是调用kernel32中的“FindFirstFileExW”函数失败。这是One Core API重命名并提供包装的文件之一,因此要么包装器搞乱了调用(我怀疑),要么实际函数只是因为任何原因在XP上返回INVALID_HANDLE_VALUE。

在PHP 7.2之前,使用“FindFirstFileW”函数代替“FindFirstFileExW”。所以修复只是替换一行代码的问题。

所以这就是你需要做的,目前适用于所有7.2.x和7.3.x版本的PHP。

抓取PHP源代码并在Zend文件夹中,打开文件“zend_virtual_cwd.c”。搜索文本“FindFirstFileExW”。文件中只有一个出现,PHP 7.3.2在843行。

837
838     if (save) {
839         pathw = php_win32_ioutil_any_to_w(path);
840         if (!pathw) {
841             return (size_t)-1;
842         }
843         hFind = FindFirstFileExW(pathw, FindExInfoBasic, &dataw, FindExSearchNameMatch, NULL, 0);
844         if (INVALID_HANDLE_VALUE == hFind) {
845             if (use_realpath == CWD_REALPATH) {
846                 /* file not found */
847                 FREE_PATHW()
848                 return (size_t)-1;
849             }
850             /* continue resolution anyway but don't save result in the cache */
851             save = 0;
852         } else {
853             FindClose(hFind);
854         }
855     }
856

这里的好消息是两个函数都使用WIN32_FIND_DATA结构(“dataw”参数)。因此,要在XP上运行,我们所要做的就是调用“FindFirstFileW”而不是“FindFirstFileExW”,记住“FindFirstFileW”只需要2个参数,而不是6个。

837
838     if (save) {
839         pathw = php_win32_ioutil_any_to_w(path);
840         if (!pathw) {
841             return (size_t)-1;
842         }
843     //  hFind = FindFirstFileExW(pathw, FindExInfoBasic, &dataw, FindExSearchNameMatch, NULL, 0);
844         hFind = FindFirstFileW(pathw, &dataw);
845         if (INVALID_HANDLE_VALUE == hFind) {
846             if (use_realpath == CWD_REALPATH) {
847                 /* file not found */
848                 FREE_PATHW()
849                 return (size_t)-1;
850             }
851             /* continue resolution anyway but don't save result in the cache */
852             save = 0;
853         } else {
854             FindClose(hFind);
855         }
856     }
856

保存文件并重新构建PHP。如果像我一样你正在使用来自php.net的预编译二进制文件,那么使用原始版本中的相同配置选项进行构建,然后用新的替换原来的“php7.dll”(或“php7ts.dll”)刚刚建成。如果您没有与原始构建器相同的环境,则需要删除一些配置选项。例如,原始7.3.2 nts x86二进制文件的配置选项是:

configure --enable-snapshot-build --enable-debug-pack --disable-zts 
--with-pdo-oci=c:\php-snap-build\deps_aux\oracle\x86\instantclient_12_1\sdk,shared 
--with-oci8-12c=c:\php-snap-build\deps_aux\oracle\x86\instantclient_12_1\sdk,shared 
--enable-object-out-dir=../obj/ --enable-com-dotnet=shared --without-analyzer --with-pgo

由于我没有Oracle或PGO(无论是什么),我只是删除这些选项并使用构建

configure --enable-snapshot-build --enable-debug-pack --disable-zts
--enable-com-dotnet=shared --without-analyzer

就是这样 - 使用One Core API在Windows XP上运行的PHP 7.2.x和7.3.x。

PHP 7.3.2 working on Windows XP

© www.soinside.com 2019 - 2024. All rights reserved.