I já se nějakou dobu snažím najít řešení "PHP Warning: oci_new_connect(): OCIEnvNlsCreate() failed. There is something wrong with your system - please check that DYLD_LIBRARY_PATH includes the directory with Oracle Instant Client libraries"
chyba v systému Mac OS X. Nakonec jsem po dlouhém výzkumu našel řešení, které tuto chybu trvale opravuje, a chtěl jsem ho zde sdílet, abych pomohl ostatním.
Jako malé pozadí používám instalaci PHP od společnosti Apple na OS X 10.8.4 (PHP 5.3.15 se Suhosin-Patch) a použil jsem úložiště PECL k instalaci rozšíření OCI8 poté, co jsem si stáhl Oracle Instant Client ke stažení z Oracle.com.
Také jsem testoval všechna řešení této chyby, která jsem našel online, včetně nastavení DYLD_LIBRARY_PATH
, ORACLE_HOME
a LD_LIBRARY_PATH
systémové proměnné prostředí v mém ~/.bash_profile
a ~/.bashrc
soubory; při pokusu o konfiguraci proměnných prostředí pomocí mod_env
Apache modul a SetEnv
v httpd.conf
; nastavení proměnných prostředí pomocí putenv("DYLD_LIBRARY_PATH=/...")
v kódu PHP; stejně jako další návrhy, ale všechny se nepodařilo vyřešit chybu.
Jediné funkční řešení, které jsem v minulosti našel a které jsem použil při své předchozí instalaci OS X 10.7.8, zahrnovalo zkopírování obsahu knihoven Oracle Instant Client do vždy prohledávaných, ale skrytých systémových složek:/usr/include
, /usr/bin
a /usr/lib
. Cítil jsem však, že toto řešení není ideální a potenciálně by z dlouhodobého hlediska znesnadnilo údržbu a modernizaci knihoven, a cítil jsem, že někde musí existovat udržitelné řešení tohoto problému.
Nakonec po mnoha dalších výzkumech jsem narazil na příspěvek na fórech OpenSUSE, který podrobně popsal, jak tam skupina uživatelů vyřešila stejnou chybu OCI pod Apache/PHP na OpenSUSE. Příspěvek na fóru se také rozšířil o komentáře, které jsem viděl v jiných příspěvcích na fóru, které hovořily o tom, že v typickém nastavení Apache/PHP existuje několik typů „proměnných prostředí“:
- Existují proměnné prostředí Apache, které se obvykle konfigurují pomocí
mod_env
- zobrazí se vApache Environment
částiphp_info()
stránku. - Existují proměnné prostředí PHP, obvykle nastavené pomocí
php.ini
neboputenv()
a zpřístupní se ve vašich skriptech pomocígetenv()
a podobné metody. - Nakonec je zde to, co zde nazývám „proměnné prostředí specifické pro proces“ – to jsou proměnné prostředí, které je třeba nakonfigurovat před spuštěním procesu Apache a jako součást samotného procesu spouštění Apache. Nestačí zadat tyto proměnné prostředí ve svém
~/.bash_profile
například. Tyto speciální proměnné prostředí zdědí proces Apache při jeho spuštění a to je zásadní , všemi jeho podřízenými procesy včetně dalších spawnů procesu Apache a samotným PHP – a právě tyto „proměnné prostředí specifické pro proces“ musíme nakonfigurovat, abychom trvale a udržitelně vyřešili náš problém s knihovnou OCI8. Při správné konfiguraci se tyto proměnné prostředí objeví vEnvironment Variables
částiphp_info()
stránku.
Vodítko, které mě přivedlo k řešení na Mac OS X, bylo z příspěvku na fóru OpenSUSE, který obsahoval komentář člena fóra key_nap , který si všiml, že když byl na OpenSUSE spuštěn proces Apache, načítal se také speciální konfigurační soubor. Tento soubor, /usr/share/apache2/load_configuration
se ukázal jako bash skript a napadlo je, že by mohli zahrnout příslušný export DYLD_LIBRARY_PATH=...
příkazy v tomto bash skriptu a konfigurací tamních proměnných prostředí je po spuštění zdědí proces Apache a jeho potomci.
To mě přivedlo k přemýšlení, kde bychom na Mac OS X byli schopni správně nakonfigurovat tytéž „proměnné prostředí specifické pro proces“. Jako launchd
se používá téměř výhradně na OS X k řešení načítání systémových procesů, zajímalo by mě, jestli bychom byli schopni nakonfigurovat potřebné proměnné prostředí v launchd
Apache konfigurační soubor? Na OS X 10.8 byste měli najít launchd
Apache konfigurace .plist
soubor na /System/Library/LaunchDaemons/org.apache.httpd.plist
. Když jsem soubor otevřel ve svém systému, okamžitě jsem si všiml sekce pro specifikaci proměnných prostředí!
Naším řešením (testováno pro Mac OS X 10.8.4) proto bylo upravit soubor org.apache.httpd.plist
soubor, jak je uvedeno níže (všimněte si zahrnutí ORACLE_HOME
, DYLD_LIBRARY_PATH
a LD_LIBRARY_PATH
do sekce EnvironmentVariables souboru) a poté restartujte Apache spuštěním sudo apachectl restart
z terminálu.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Disabled</key>
<true/>
<key>Label</key>
<string>org.apache.httpd</string>
<key>EnvironmentVariables</key>
<dict>
<key>XPC_SERVICES_UNAVAILABLE</key>
<string>1</string>
<key>ORACLE_HOME</key>
<string>/Users/workstation/Oracle</string>
<key>DYLD_LIBRARY_PATH</key>
<string>/Users/workstation/Oracle/lib</string>
<key>LD_LIBRARY_PATH</key>
<string>/Users/workstation/Oracle/lib</string>
</dict>
<key>ProgramArguments</key>
<array>
<string>/usr/sbin/httpd-wrapper</string>
<string>-D</string>
<string>FOREGROUND</string>
</array>
<key>OnDemand</key>
<false/>
<key>SHAuthorizationRight</key>
<string>system.preferences</string>
</dict>
</plist>
Přidáním těchto definic „proměnných prostředí specifického pro proces“ do launchd
Apache konfiguračního souboru, zajistíme, že tyto proměnné prostředí správně zdědí Apache a všechny jeho podřízené procesy, které zahrnují PHP a všechny moduly načtené PHP, jako je OCI8! Samozřejmě byste měli nahradit cestu /Users/workstation/Oracle/...
ukázaný ve výše uvedeném příkladu se správnými cestami k vaší vlastní instalaci klientských knihoven Oracle – použijte stejné hodnoty jako při zadávání těchto proměnných prostředí ve vašem ~/.bash_profile
.
Také se ujistěte, že máte pro váš systém nainstalovanou správnou verzi Oracle Instant Client Libraries – tedy buď 32bitovou nebo 64bitovou variantu v závislosti na tom, jakou verzi OS X používáte a zda v nich běží Apache a PHP. 32bitový nebo 64bitový režim. Na OS X 10.8 a vyšším by měl Apache/PHP běžet jako 64bitové procesy. Pokud si nejste jisti, můžete udělat to, co jsem dělal já na svém předchozím Macu a zkombinovat 32bitové a 64bitové verze binárních souborů knihovny Oracle Instant Client do jediné multiarchitekturní fat-binary pomocí lipo
nástroj z XCode, který vytvoří binární soubory, které se načtou na obě platformy.
Konečně, výše popsané řešení pro konfiguraci proměnných prostředí v launchd
Apache konfigurační soubor by měl také fungovat při řešení podobných chyb v jiných modulech PHP spuštěných přes Apache, které při hledání propojených knihoven spoléhají na proměnné prostředí. Pokud spouštíte PHP z příkazového řádku, měli byste být schopni specifikovat všechny proměnné prostředí, které potřebujete ve svém ~/.bash_profile
a/nebo ~/.bashrc
soubory.