PHP 4 a PHP 5 zároveň na jednom fyzickém serveru s Windows XP
Quick and Dirty HowTo, Not a Definitive Guide

Michal Špaček

(Rev. 32, 20. listopad 2005, 00:56:46)

Obsah dnešní lekce

Teorie strun a membrán aneb úvod do problematiky

Jen tak namátkou Vám mohu vyjmenovat přinejmenším tři metody, jak na jakýkoli fyzický stroj dostat libovolný počet libovolných verzí PHP, z nichž metoda současného běhu více instancí HTTP serveru je ta nejprimitivnější a nejdéle používaná.

Tento návod měl původně vzniknout o prázdninách roku 2004, tenkrát jsem měl pár měsíců svůj první notebook a tou dobou také vyšla první stable verze PHP 5. Pochopitelně jsem chtěl na této nové verzi vyvíjet, protože přinesla mnoho novinek, vylepšení a oprav chyb a také snížila TCO a spousta lidí díky ní začala používat jméno Ten mladej, co nám naprogramuje ten náš GPRMPS systém přes noc. Rychlejší chladnutí kávy a rychlejší teplání piva jsou jedny z mála nevýhod a tak je ani raději nebudeme zmiňovat. Návod jsem tenkrát nabídl magaezínu Interval.cz. Stalo se, co se stalo a tak s menším zpožděním na četné žádosti (1+) vychází úplně někde jinde a v jiné (čti svobodné) podobě se spoustou sprostých slov a ASCII porna.

PHP 4 a PHP 5 zároveň…

Víte, proč žena při menstruaci vaří na všech plotýnkách? Sakra a proč by prostě nemohla?!

Důvod, proč provozovat PHP 4 a zároveň PHP 5 je vskutku jednoduchý, prostě to tak chceme. Ať už kvůli tomu, že budeme ohýbat staré (čti dříve napsané) aplikace (čti skripty) a zároveň psát nové a ty staré prostě nechceme, nebo nemůžeme upravovat na nové verzi PHP a ty nové, ač můžeme, tak na staré verzi PHP psát nechceme.

… na jednom fyzickém serveru…

Co je lepší než lesba v posteli? Dvě lesby v posteli.

Jeden fyzický server je levnější než dva a dva notebooky se nevejdou do jedné brašny. Toto pochopitelně platí pro vývojové stroje, production server snad nikdo na notebooku neprovozuje, na druhou stranu 23 taky není 9. Jeden fyzický stroj je také vhodný např. pro plynulý převod PHP 4 skriptů na server s PHP 5.

Nevýhoda je jasná už z principu, na jednom stroji běží více procesů, zabírají více paměti a ubírají trochu výkonu. Mě na notebooku běží dva servery Apache, dva MySQL servery a přibude PostgreSQL, takže dvou HTTP serverů bych se nebál. Koneckonců stejně všichni máme ty Intel® Káthmandú procesory s 3,14 GB DDR ECC THC pamětmi, takže to je zívačka.

… s Windows XP

This behavior is by design.

Tady nevím, čím bych začal, takže to vezmu od lesa. Na systému unixového typu snad každý administrátor dokáže rozjet Apache na jiném portu nebo jiné IP. Na woknech to není tak úplně jasný, proto je návod primárně pro wokna. Tím samozřejmě nevyjadřuji žádné svoje sympatie. Návod by se asi dal použít i pro nějaký unix, dejte mi vědět, jestli to někdo zkusíte a uspějete. Budu vděčný nejenom za zkrácení nebo prodloužení nadpisu. Koneckonců návod je pro wokna i proto, že níže uváděná záplata je zkrátka pro wokna.

Kudy tudy na Karlštejn aneb možnosti konfigurace

It's not how good you are, it's how bad you want it.

Možností jak to celé postavit je pochopitelně několik, to už ostatně je nenásilnou formou naznačeno v úvodu. Některé jsou vhodné, některé nejsou vhodné a některé nejsou vůbec. Mé osobě jich je známých několik, postupně si je pochopitelně představíme. Pokud v budoucnu spatří světlo světa nějaké další způsoby, tento návod bude patřičně aktualizován. Samozřejmě se budeme chtít co nejvíc přiblížit ostrému produkčnímu prostředí, což s woknama zas nebude tak jednoduché, ale to je zanedbatelný detail. Proto ani nebudu uvádět metody typu "spusť tento soubor, když chceš používat PHP 4 a spusť jiný soubor, když PHP 5", s tím se v praxi v produkčním prostředí moc nesetkáte. Jako dodatek uvádím, že budeme instalovat z oficiálních distribucí, žádné takové ty 42-in-1 balíčky.

PHP je nejčastěji nainstalováno jako modul HTTP serveru. Mohlo by se zdát, že ve chvíli, kdy chceme mít do serveru zavedené dva PHP moduly, není nic jednoduššího, než tyto PHP moduly prostě zavést pomocí LoadModule direktivy. Ostatně, moduly takto zavést i jdou, resp. server při zavádění neohlásí žádnou chybu, jenže vzhledem k tomu, že oba dva moduly se registrují pod stejný MIME typ application/x-httpd-php je potom zcela jasné, že to zkrátka nebude fungovat korektně. Dřívěji zavedený modul je přebit zavedením jiného modulu se stejným MIME typem. Takže když zavedeme nejdříve PHP 4 modul a pak PHP 5 modul, všechny skripty se budou zpracovávat PHP 5 modulem.

Jeden modul, jedno CGI, jeden Apache

Ostatně, v tomto smyslu jsem už já sám jeden článek na Interval.cz kdysi publikoval (i když dnes už bych k publikaci takový text asi vůbec nepřijal ;-)

Jak jsme se dozvěděli, dva PHP moduly nejdou nainstalovat zároveň. Ale dvě CGI verze nainstalovat jdou, mno. Dokonce jde nainstalovat jeden PHP modul a zbytek PHP nainstalovat jako CGI. Takže můžeme mít k dispozici v podstatě neomezený počet PHP verzí. Až na to, že CGI se v ostrém provozu moc nenosí, krom výkonnostního rozdílu je zde také určitý rozdíl v dostupných proměnných a to hlavně v poli $_SERVER.

TODO UPDATE FIXME http://interval.cz/clanek.asp?article=1740

Dva moduly, dva Apache, jedna IP adresa, dva porty

Svoboda jednoho končí tam, kde začíná svoboda druhého.

Pokud se tedy chceme přiblížit ostrému provozu, je třeba provozovat dva HTTP servery a v každém mít zaveden jeden modul PHP. Můj postup předpokládá instalaci Apache 1.3 pro PHP 4 a Apache 2.0 pro PHP 5. Apache standradně po instalaci naslouchá na všech dostupných IP adresách a na portu 80 (direktiva Listen 80). Každý server však potřebuje běžet na unikátní kombinaci IP adresy a portu a tak se nám dva standardně nakonfigurované servery nespustí. Jeden ze serverů tedy přesuneme na jiný port, např. na 81. Přistupovat na něj pak budeme pomocí adresy http://localhost:81/. Pokud bychom port neuvedli, HTTP klient (prohlížeč) v tajnosti port doplní na standardní 80, tak bychom vlastně přistupovali na úplně jiný server, než bychom si přáli. Sami jistě uznáte, že to není zrovna nejpohodlnější, kdo si to má pamatovat, navíc některé skripty nemusí vůbec počítat s tím, že mohou být zpracovávány serverem, který běží na jiném než standardním portu. Tento postup je víceméně pro úplnost, nějak mě nenapadá situace, kdy by jeden počítač měl k dispozici pouze jednu IP adresu – každý počítač, kde je k dispozici TCP/IP má tzv. lokální smyčku (angl. loopback device), která může mít více adres, standardně je dostupná pod IPv4 adresou 127.0.0.1. Nicméně vzhůru níže.

Nainstalujeme první Apache se standardní konfigurací. V nastavení služeb systému se přesvědčíme, že Apache neběží, případně jej vypneme, aby nedošlo k případné kolizi s instalací druhého serveru.

Spustíme instalaci druhého Apache, je vhodné jej nainstalovat do jiného adresáře, než první server. Opět necháme standardní konfiguraci a opět se přesvědčíme, že Apache neběží. V konfiguračním souboru (httpd.conf) druhého serveru vyhledáme direktivu Listen a změníme její hodnotu:

Listen 81

Tím dosáhneme toho, že Apache po startu bude naslouchat na všech IP adresách na portu 81. Pokud provozujeme HTTPS, je třeba adekvátně upravit i direktivy Listen pro server s podporou pro SSL – týká se to portu 443.

Po dokončení konfigurace prověříme její úspěšnost. V nastavení služeb systému spustíme oba Apache servery a počkáme, jestli nenastane konec světa. Poznáme to podle toho, jestli se rozsvítí červený nápis "Všechno je v prdeli", když ne, tak se naše konfigurace povedla. Což si ještě potvrdíme zadáním http://localhost/http://localhost:81/ do prohlížeče. V podpisu serveru bychom měli vidět rozdílné verze.

Teď už stačí jen úspěšně nainstalovat PHP 4 do prvního serveru a PHP 5 (nejlépe z jiného adresáře) do druhého serveru. Soubor php.ini pro PHP 4 umístíme do adresáře prvního serveru tam, kde je soubor Apache.exe, php.ini pro PHP 5 do adresáře s konfigurací druhého serveru tam, kde je httpd.conf a v tomto souboru patřičně upravíme direktivu PHPIniDir:

PHPIniDir "C:/Program Files/Apache Group/Apache2/conf"

PEAR je možné nainstalovat společně do jednoho adresáře. Po restartu HTTP serverů by mělo PHP 4 a PHP 5 fungovat odděleně na dříve uvedených adresách.

Dva moduly, dva Apache, jedna IP adresa, dva porty, reverzní proxy

Německy? Ani slovo, tak akorát "Ich fahre nach Amsterdam."

Tato možnost je v podstatě to stejné jako předchozí možnost, navíc je doplněna reverzním proxy serverem, který nám odstraní problém s dopisováním portu 81 do URL. Reverzní proxy je v podstatě normální proxy, akorát stojí na druhé straně barikády – tedy pokud možno co nejblíže serveru, dá se použít na spoustu úžasných věcí, jak je popsáno třeba na http://www.root.cz/clanky/reverzni-proxy/.

Zmíním to rovnou na úvodu, na konci to pak ještě zopakuji. Špatně nakonfigurovaný proxy server je nebezpečný jak pro naši vlastní síť, tak pro Internet, jako celek, z důvodů jako jsou XSS útoky, spam apod. Špatně nakonfigurovaný proxy server vyrobíme např. tak, že aktivujeme reverzní proxy, ale zapomeneme vypnout standardní (dopřednou) proxy. V tuto chvíli mlže v podstatě kdokoliv využívat našeho serveru k přístupu na jakékoliv jiné servery na Internetu. Na těchto serverech jsme pak vedeni my, jako ten, kdo na ně přistupoval, což není moc dobré, zvlášť pokud na nich byla vykonána nějaká nekalá činnost. Proto je dobré dopřednou proxy zakázat, viz dále.

Servery tedy nakonfigurujeme tak, jako v předchozím návodu (tedy tak, aby fungovaly adresy http://localhost/http://localhost:81/). Nyní "aktivujeme" adresu php5.localhost v souboru hosts, který se nachází v adresáři C:\WINDOWS\system32\drivers\etc a to tak, že k existujícím záznamům doplníme tento řádek:

127.0.0.1       php5.localhost

Tím zajistíme, že první server bude dostupný i pod adresou http://php5.localhost/, což na první pohled nedává moc smysl. Na druhý pohled po pěti pivech už to vypadá lépe, protože si vzpomeneme, že Apache zvládá virtuální servery a že tudy asi vede cesta z hospody domů. Takže po vystřízlivění se pokusíme nastavit první server tak, aby veškeré požadavky na php5.localhost protlačoval na druhý server. Nejdříve je pochopitelně nutné instruovat server, aby nahrál modul zajišťující požadovanou funkcionalitu, to zajistíme odkomentováním následujících řádků v konfiguračním souboru httpd.conf:

LoadModule proxy_module modules/mod_proxy.so

a učiníme jej aktivním pomocí:

AddModule mod_proxy.c

Dále je třeba povolit virtuální servery rozlišované podle jejich jmen direktivou:

NameVirtualHost *:80

Zjednodušeně řečeno, tím povolíme virtuální servery na portu 80 na všech IP adresách, na kterých Apache naslouchá. Na konec konfiguračního souboru, kde obvykle bývají definice virtuálních serverů, přidáme záznam pro naši reverzní proxy:

<VirtualHost *:80>
ServerName php5.localhost
ProxyPass / http://localhost:81/
ProxyPassReverse / http://localhost:81/
</VirtualHost>

ServerName specifikuje jméno virtuálního serveru, ProxyPass pak aktivuje reverzní proxy – veškeré požadavky (protože každý požadavek začíná kořenem) budou "přeposílány" na server bežící na adrese localhost na portu 81, tedy na server, kde běží PHP 5. Požadavek na http://php5.localhost/foo/bar bude prvním serverem vnitřně přesměrován na http://localhost:81/foo/bar. Adresa s portem 81 bude fungovat i při přímém zadání do prohlížeče, pochopitelně. ProxyPassReverse pak zajistí zpětný překlad těch HTTP hlaviček Location, které v sobě nesou adresu druhé serveru na portu 81.

Při provozování reverzního proxy serveru je velice vhodné zakázat normální proxy, to provedeme pomocí direktivy ProxyRequests, kterou umístíme do podmíněného bloku tak, abychom mohli server nastartovat i bez zavedeného modulu pro proxy servery:

<IfModule mod_proxy.c>
ProxyRequests Off
</IfModule>

Tento blok umístíme někam před začátek sekce definující virtuální servery, tedy někam před komentáře uvedené před direktivou NameVirtualHost.

Podobné funkcionality lze dosáhnout pomocí modulu mod_rewrite, resp. speciálního příznaku proxy (nebo P). Nicméně stále tu platí podmínka, že musí být zaveden modul pro proxy server mod_proxy, stejně jako v předchozím případě, takže postup přes mod_rewrite v podstatě jen umožňuje mocnější implementaci reverzního proxy serveru, čehož my nevyužijeme. Je také třeba nezapomenout na zakázání standardní proxy pomocí ProxyRequests Off. Pravidlo pro přepis URL pro virtuální server php5.localhost by pak mohlo vypadat následovně:

RewriteRule ^/(.*) http://localhost:81/$1 [P]

Instalace PHP do obou serverů probíhá tak, jak je popsáno v návodu, kdy se používají dva porty.

Dva moduly, dva Apache, dvě IP adresy

Slunce se skládá se dvou rozsáhlých částí, z nichž ani jedna není za normálních okolností vidět. Ale ta vnější bude vidět 29. března 2006 v Turecku.

Jak jsem již uvedl, každý server musí běžet na unikátní kombinaci IP adresy a portu. Pokud tedy chceme provozovat dva HTTP servery (což musíme kvůli instalaci dvou PHP modulů) a nechceme dopisovat do URL port a nechceme ani provozovat reverzní proxy server, nezbývá nám nic jiného, než spustit každý server na jiné IP adrese. Na jakých, to záleží na situaci, ve které jsme. Adresu 127.0.0.1 máme k dispozici vždy, nevýhoda je ta, že je pouze lokální, nelze na ni přistoupit z jiných počítačů. Pokud máme do počítače zavedenu jednu veřejnou IP adresu, pak máme možnost obsah jednoho serveru zobrazovat i ven (pokud chceme ven obsah obou serverů, pak musíme použít předchozí způsob s reverzní proxy). Pokud je do počítače zavedeno více veřejných IP adres (a to klidně i na jednu síťovou kartu), není problém každý server spustit na jedné veřejné IP adrese a můžeme bez problémů (a bez reverzní proxy) zobrazovat obsah obou serverů celému světu. V následujícím textu budeme předpokládat, že nechceme světu nic ukazovat, nebo že počítač nemá žádnou veřejnou adresu, nebo že veřejná adresa počítače se mění v čase, ať už díky tomu, že je počítač přenášen ze sítě do sítě, nebo adresu mění poskytovatel připojení. Rozhodně tedy situace bude vypadat tak, že jeden server bude spuštěn na adrese 127.0.0.1 a druhý na 127.0.0.2. Windows XP se Service Pack 2 standardně povolí přístup pouze na první zmiňovanou adresu, je tedy potřeba speciální update, který povolí připojení i na ostatní adresy v rozsahu lokální smyčky. Tento update má číslo 884020 a lze jej stáhnout z http://support.microsoft.com/kb/884020/. Je potřeba jej nainstalovat před spuštěním druhého serveru.

Nainstalujeme tedy první server, ve službách systému se přesvědčíme, že není spuštěn, případně službu zastavíme. Nainstalujeme druhý server a opět zajistíme, aby nebyl spuštěn. Nyní se vrhneme na konfiguraci prvního serveru, otevřeme tedy soubor httpd.conf, najdeme ten správný řádek a nastavíme, aby server naslouchal na té správné adrese:

Listen 127.0.0.1:80

To samé provedeme v konfiguračním souboru druhého serveru, jen řádek bude vypadat trochu jinak:

Listen 127.0.0.2:80

Poté ve službách systému oba dva servery spustíme. Do prohlížeče zadáme zkušebně http://127.0.0.1, měl by nám odpovědět první server a http://127.0.0.2, měl by odpovědět druhý server. Ty čísla nejsou zrovna moc přívětivá a tak si je trochu polidštíme. V souboru hosts je již uveden záznam pro první adresu (localhost), takže stačí přidat záznam pro tu druhou:

127.0.0.2       php5.localhost

Nyní by tedy servery měly být dostupné pod adresami http://localhost/http://php5.localhost/.

Instalace PHP do serverů probíhá stejně tak, jak je popsáno v návodu, kdy se používají dva porty.

Dva moduly, jeden Apache, hack

Nejdůležitější nástroj hackera je vypalovačka.

Tato poslední možnost je určena pro experimentátory, spočívá v úpravě zdrojových kódů PHP, případně v úpravě binární distribuce. Oficiálně jsem ji nikde neviděl uváděnou, takže spíš pro zajímavost, je možné, že změna má nějaké vedlejší účinky. Oba dva moduly PHP si registrují stejný MIME typ application/x-httpd-php, takže je celkem problém rozlišit jeden od druhého. úprava tedy spočívá ve změně typu jednoho modulu na něco jiného a modul s takto upravným typem pak bude zpracovávat soubory určené např. pro PHP 4, zatímco modul s původním typem pak soubory určené pro PHP 5. Přiřazení je možné provést pomocí direktivy AddType na úrovni přípon souborů, virtuálních serverů nebo na úrovni adresářů.

TODO UPDATE FIXME http://forum.builder.cz/read.php?20,991619,994783#msg-994783