2011-11-15 13 views
7

Mam bardzo prosty skrypt testowy:Połączenie PDO działa z linii poleceń, ale nie przez Apache?

<?php 

$DSN = "mysql:host=db.example.edu;port=3306;dbname=search_data"; 

try { 

    $DB = new PDO($DSN, "username", "super-secret-password!"); 

} catch (PDOException $e) { 

    header('Content-Type: text/plain'); 
    print "Could not connect to database, rawr. :-("; 
    exit; 

} 


$SQL = "SELECT phrase FROM search ORDER BY RAND() LIMIT 10"; 

foreach($DB->query($SQL) as $row){ 

    print $row['phrase']."\n"; 

} 

?> 

Kiedy wykonać ten skrypt z wiersza poleceń, to działa doskonale:

$ php test.php 
corporal punishment 
Stretches 
voluntary agencies and the resettlement of refugees 
music and learning 
Nike Tiger Woods Scandal 
Hermeneia 
PSYCHINFO 
anthony bourdain 
Black-White Couples and their Social Worlds 
colonization, hodge 

Ale kiedy dostęp do dokładnie tego samego scenariusza poprzez przeglądarce internetowej , to mówi:

Could not connect to database, rawr. :-(

próbowałem var_dump od błędu, a wiadomość jest: „SQLSTATE [HY000] [2003] nie można połączyć się z serwerem MySQL na ' db.example.edu "(13)".

To jest zagadkowe. Jest to dokładnie ten sam skrypt na tym samym serwerze - dlaczego działa po uruchomieniu go z wiersza poleceń, ale kończy się niepowodzeniem, gdy Apache go uruchomi?

+0

Czy to serwer Linux? Czy to Redinux, czy CentOS z SELinux? Jeśli tak, być może będziesz musiał włączyć booleany SELinux 'httpd_can_network_connect' oraz' httpd_can_network_connect_db', aby umożliwić serwerowi Apache nawiązanie połączenia ze zdalnym hostem bazy danych. –

+1

więcej informacji na temat tego błędu (13 = uprawnienie odmówione) znajduje się tutaj: http://www.filonov.com/blog/2009/08/07/sqlstatehy000-2003-cant-connect-to-mysql-server-on-xxx -xxx-xxx-xxx-13/ – thetaiko

+0

@Michael Tak, jest to serwer RHEL 6.1 i nowy, błyszczący. Ponadto, @thetai - to działało! To SELinux blokował połączenie, a uruchomienie 'setsebool -P httpd_can_network_connect = 1' jako root naprawiło to. Jeśli chcesz opublikować to jako odpowiedź, z przyjemnością przyjmuję i przegłosuję. –

Odpowiedz

24

Jeśli jest to dystrybucja pochodna Red Hata (RHEL, CentOS, Fedora, ScientificLinux), która używa SELinux (lub jakiejkolwiek pochodnej innej niż Red Hat przy użyciu SELinux), domyślnym ustawieniem polityki w chwili pisania tego tekstu jest zakazanie Apacheowi wykonywania zewnętrzne połączenia z innymi serwerami lub bazami danych. Jako root, musisz włączyć następujące dwa booleany SELinux. Użyj opcji -P, aby utrzymać zmianę w trakcie ponownego uruchamiania.

setsebool -P httpd_can_network_connect=1 
setsebool -P httpd_can_network_connect_db=1 

Pamiętaj, że httpd_can_network_connect może nie być konieczne. Spróbuj najpierw włączyć tylko httpd_can_network_connect_db.

+2

Dzięki! Linia 'httpd_can_network_connect' nie była w moim przypadku konieczna, wystarczy linia' httpd_can_network_connect_db'. –

+0

Uratowałeś mój dzień. Wielkie dzięki ◕‿◕ – PHPst

+0

jeśli nie wznowiłeś tego, proszę zrób to ... – bart2puck

0

miałem ten sam problem dla PHP ftp ftp_connect i musiał ustawić

setsebool -P httpd_can_network_connect=1 

To jest mylące, ponieważ takie rzeczy jak fil_get_contents i zwijają pracy poprzez PHP i Apache dobrze przed ustawieniem tego.

-1

sam problem ale inna przyczyna tutaj
Moje rozwiązanie był tylko prosty apt-get install php-mysql z dala

Koniecznie czekiem na pdo_mysql w phpinfo()
okazało się, że na tym stanowisku: PDOException “could not find driver”

Zastanawiam się, dlaczego CLI działało w takich warunkach. O_o Może coś zainstalowano niepoprawnie lub zostało przesłonięte? Cóż, teraz działa dobrze!

+0

Chcesz wyjaśnić, a nie tylko przechytrzyć? Wciąż nie mam pojęcia, dlaczego działa w CLI, a nie poprzez Apache. Jeśli przegapiłem coś oczywistego, proszę, po prostu powiedz nam, CO. Wysłałem swoje rozwiązanie, ponieważ * faktycznie rozwiązało mój problem * i może pomóc innym. Jeśli zrobiłem coś całkowicie złego, proszę nas oświecić. – Balmipour

0

Ponadto stosując powyżej przyjętej odpowiedź

setsebool -P httpd_can_network_connect=1 
setsebool -P httpd_can_network_connect_db=1 

Musiałem też zmienić kontekst zabezpieczeń pliku, który httpd starał się dostępem.

Skrypt php uruchomiony przez Apache próbował uzyskać dostęp do pliku certyfikatu, który znajdował się poza normalnym katalogiem głównym httpd. Zmiana uprawnień do plików w celu umożliwienia dostępu za pośrednictwem protokołu httpd nie była wystarczająca, aby zezwolić na dostęp httpd do tego pliku.Musiałem zmienić kontekst zabezpieczeń, tak więc przed zmianą:

[admin]$ ls -Z ../../certs/rds-ca-2015-root-us-east-1-BUNDLE.pem 
-rw-r--r--. admin apache unconfined_u:object_r:unlabeled_t:s0 ../../certs/rds-ca-2015-root-us-east-1-BUNDLE.pem 

Zmiana kontekstu za pomocą:

sudo chcon -v --type=httpd_sys_content_t ../../certs/rds-ca-2015-root-us-east-1-BUNDLE.pem``` 

dostać:

[admin]$ ls -Z ../../certs/rds-ca-2015-root-us-east-1-BUNDLE.pem 
-rw-r--r--. admin apache unconfined_u:object_r:httpd_sys_content_t:s0 ../../certs/rds-ca-2015-root-us-east-1-BUNDLE.pem 

Teraz wszystko jest dobre. Dobrym źródłem do obejrzenia jest /var/log/audit/audit.log i zwróć szczególną uwagę na błędy. W moim przypadku błąd wskazujący kierunek rozwiązania:

type=AVC msg=audit(1509047616.042:4049): avc: denied { read } for pid=17096 comm="httpd" name="rds-ca-2015-root-us-east-1-BUNDLE.pem" dev="xvdb" ino=262146 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:unlabeled_t:s0 tclass=file 
Powiązane problemy