Apache 2.4 + несколько PHP на Windows XP с одноядерным API - PullRequest
0 голосов
/ 17 февраля 2019

Извиняюсь за долгое чтение, но я думаю, что имеет смысл включать как можно больше подробностей, вместо того, чтобы ждать, пока люди попросят различные конфигурации, логи и т. Д.

У меня естьстарый ПК под управлением XP с установленным One Core API.

Я использую это для тестирования Apache 2.4.38 с несколькими версиями PHP.Все работает отлично, за исключением того, что PHP 7.2 и 7.3 возвращают статус 404 для всех файлов php с сообщением «Входной файл не указан».Журналы Apache, если я правильно их читаю, показывают, что php-cgi.exe вызывается правильно и отвечает за возвращение этого состояния, даже если файлы существуют.

SysInternals Process Monitor показывает, что Apache "httpd.exe "находит файлы php без проблем.После этого все версии PHP до 7.1 проверяют как «user.ini», так и запрашиваемый файл php.Версии 7.2 и 7.3, однако, проверяют только «user.ini» и вообще не пытаются получить доступ к запрошенному файлу php.Несмотря на это, они возвращают ошибку 404 с сообщением «Не указан входной файл».

Теперь я уменьшил масштаб до рабочей конфигурации, которая показана ниже, если кто-то захочет попробовать это самостоятельно.,Apache и все сборки PHP установлены в папке, названной в соответствии с их 5-значным идентификатором версии.Есть один тестовый сайт «test2.local», который содержит один индексный файл.

  • Все 32-битные версии, и все версии PHP не являются поточно-безопасными (nts) версиями.
  • Apache - это текущая сборка из Apache Lounge (по состоянию на 8 февраля 2019 г.).
  • PHP <= 5.5 - последние сборки для каждой версии. </li>
  • PHP> = 5.6 - все текущие сборки (как8 февраля 2019 г.).
  • Все сборки PHP - это предварительно собранные двоичные файлы из php.net.
  • Все среды выполнения VC установлены и работают (2008, 2012, 2017).
  • Для простоты расширения PHP не загружаются.
  • Все версии PHP имеют свой собственный файл "php.ini" в своей папке.
  • Все двоичные файлы проверены и установленыОтсутствуют отсутствующие зависимости, за исключением обычных преступников (расширения PHP, использующие стороннее программное обеспечение, которое не установлено).
  • Все версии "php.exe" и "php-cgi.exe" отлично работают скомандной строки и без каких-либо ошибок записывается в журнал ошибок PHP.
  • Все версии "php-cgi.exe" до 7.1 отлично работают с Apache, также без каких-либо ошибок в журнале.
  • Версии 7.2 и 7.3 "php-cgi.exe" показывают статус 404 для всех phpфайлы в журнале ошибок Apache, но опять же, ничего не записывайте в журнал ошибок 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 = идентификатор версии):

[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», но я попытался это сделать безуспешно. На самом деле, включение этих параметров приводило к тому, что устанавливались только переменные «SCRIPT_NAME» и «PHP_SELF»в "D: /index.php" вместо "/index.php" во всех работающих версиях PHP. Другими словами, включение его сломало, а не исправило.)

Когда все готово, тестирование так же просто, как запрос страницы на "http://test2.local/index.php". Результаты для PHP <= 7.1 одинаковы, поэтому я буду использовать журналы 7.1. Аналогично, результаты для7.2 и 7.3 одинаковы, поэтому я буду использовать журналы 7.2. Ни одна версия PHP не регистрировала ошибок или сбоев. Каждая версия успешно загружалась при первом запросе и продолжала успешно работать до перезапуска Apache. </p>

Журнал запуска 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

Журнал Apache для запроса "http://test2.local/index.php" (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

Снимок экрана Process Monitor для "http://test2.local/index.php" (PHP 7.1) :

Process Monitor Screenshot (PHP 7.1)

Журнал Apache для запроса "http://test2.local/index.php" (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

Снимок экрана монитора процесса для" http://test2.local/index.php" (PHP 7.2) :

Process Monitor Screenshot (PHP 7.2)

Любая помощь в разгадке этой тайны будет принята с благодарностью. Снова извиняюсь за продолжительное чтение.

1 Ответ

0 голосов
/ 25 февраля 2019

Что ж, для тех, кто заинтересован, я наконец-то отследил проблему, и вы можете ее решить, если сами захотите пересобрать PHP.

Виновником является вызов «FindFirstFileExW»функция в kernel32, которая не работает.Это один из файлов, который переименовывает One Core API и предоставляет оболочку, так что либо оболочка портит вызов (в чем я сомневаюсь), либо реальная функция просто возвращает INVALID_HANDLE_VALUE в XP по любой причине.

До версии PHP 7.2 вместо FindFirstFileExW использовалась функция «FindFirstFileW».Таким образом, это просто вопрос замены одной строки кода.

Итак, вот что вам нужно сделать, что в настоящее время применимо ко всем версиям PHP 7.2.x и 7.3.x.

Возьмите исходный код 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

Вот и все - PHP 7.2.x и 7.3.x работают на Windows XP с One Core API.

PHP 7.3.2 working on Windows XP

...