PDO connection works from command line, but not th

2019-01-25 11:59发布

问题:

I have a very simple test script:

<?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";

}

?>

When I execute this script from the command line, it works perfectly:

$ 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

But when I access the exact same script through my web browser, it says:

Could not connect to database, rawr. :-(

I've tried var_dump on the error, and the message is: "SQLSTATE[HY000] [2003] Can't connect to MySQL server on 'db.example.edu' (13)".

This is puzzling. It's the exact same script on the exact same server -- why does it work when I execute it from the command line, but fail when Apache executes it?

回答1:

If this is a Red Hat-derived distribution (RHEL, CentOS, Fedora, ScientificLinux) running SELinux (or any non Red Hat derivative using SELinux), the default policy setting at time of this writing is to prohibit Apache from making external connections to other servers or databases. As root, you must enable the following two SELinux booleans. Use the -P option to persist the change across a reboot.

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

Note that httpd_can_network_connect may not be necessary. Try it first turning on only httpd_can_network_connect_db.



回答2:

I had the same problem for PHP ftp ftp_connect and had to set the

setsebool -P httpd_can_network_connect=1

It's confusing because other things like fil_get_contents and curl work through PHP and apache just fine before setting that.



回答3:

In addition the using the above accepted answer

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

I had to also change the security context of a file that httpd was trying to access.

A php script run through apache was trying to access a certificate file that was outside the normal document root of httpd. Changing the file permissions to allow httpd access was not enough to allow httpd access to that file. I had to change to security context as well, so before the change:

[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

Change context using:

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

to get:

[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

Now all is good. A good resource to look at is /var/log/audit/audit.log and pay close attention to errors. In my case the error that pointed to the direction of a resolution was:

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


回答4:

Same issue but different cause here
My solution was just a simple apt-get install php-mysql away

Be sure to check for pdo_mysql in your phpinfo()
Found it on this post : PDOException “could not find driver”

I wonder why CLI worked in such conditions O_o Maybe something installed incorrectly, or got overriden ? Well, now, it works fine !