Conexão com o MySQL falhar via PHP, enquanto linha de comando funciona bem
Pergunta
Eu tenho um script para instalar o MySQL 5.7 e executar testes em Travis CI (executando Ubuntu 12).
O script contém estas linhas, para instalar o MySQL no modo não-interativo, com nenhuma palavra-passe:
add-apt-repository 'deb http://repo.mysql.com/apt/ubuntu/ precise mysql-5.7-dmr'
apt-get update
echo mysql-community-server mysql-community-server/root-pass password "" | debconf-set-selections
echo mysql-community-server mysql-community-server/re-root-pass password "" | debconf-set-selections
DEBIAN_FRONTEND=noninteractive apt-get -o Dpkg::Options::=--force-confdef -o Dpkg::Options::=--force-confold -q -y install mysql-server libmysqlclient-dev
A instalação é executada sem problemas, e utilizando a mysql
utilitário de linha de comando, eu posso conectar ao servidor usando nenhuma palavra-passe:
mysql --user=root -e "SELECT VERSION();"
+-----------+
| VERSION() |
+-----------+
| 5.7.8-rc |
+-----------+
Agora se eu tentar conectar usando PHP DOP:
new PDO('mysql:host=localhost', 'root', '');
Eu recebo o seguinte erro:
SQLSTATE[HY000] [1045] Acesso negado para o usuário 'root'@'localhost' (using password:NÃO)
Eu tentei para permitir root
para se conectar a partir de qualquer host:
GRANT ALL ON *.* to root@'%' IDENTIFIED BY '';
FLUSH PRIVILEGES;
Sem sucesso.
O que pode ser o problema?
Solução
Encontrei a resposta no manual do MySQL, Autenticação Conectável:
A partir do MySQL 5.5.7, o servidor autentica os clientes usando um plugin.Seleção da adequada conta de carreira, a partir do mysql.tabela de usuário é baseada no nome do usuário e host do cliente, como antes, mas o servidor autentica o cliente através da determinação da linha da conta de autenticação do plugin se aplica para o cliente.
O pacote do MySQL cria um root
usuário usando o auth_socket
autenticação do plugin, então apenas conexões através de um soquete são permitidos, e o nome de usuário do Linux conta é verificada também.
O mysql
o comando usa um socket, por predefinição e é executado como root
no meu script, e assim foi permissão de se conectar.
De acordo com o manual do PHP, um PDO para conexão com o MySQL localhost
também usa um soquete;mas o PHP é executado como um usuário sem privilégios, de modo que a conexão é recusada pelo auth_socket
plugin.
Eu fixo meu script, adicionando esta linha:
mysql --user=root -e \
"UPDATE mysql.user SET plugin='mysql_native_password'; FLUSH PRIVILEGES";
E agora funciona bem.
Outras dicas
Você precisa desactivado o SELinux, executando o comando abaixo:
setsebool httpd_can_network_connect=1