Réparer l'authentification MySQL quand elle a pétée
Le jeudi 24 septembre 2015 par Benjamin BoudoirAucune idée du comment, mais hier je tente de créer un utilisateur et mysql me répond :
ERROR 1146 (42S02): Table 'mysql.user' doesn't exist
Awww man.
Je vérifie le filesystem : yeap, existe pas.
Awww man².
Bon. Comment qu'on fait ?
Récupérer les mots de passe
On a au moins un mot de passe stocké en clair et ça tombe bien, on en a besoin, c'est celui de debian-sys-maint, stocké dans /etc/mysql/debian.cnf.
C'est l'utilisateur utilisé par Debian pour démarrer, stopper, monitorer et gérer les MAJ de MySQL.
Sinon, récupérer les autres utilisateurs depuis vos applicatifs. Si vous avez un backup de la base mysql, c'est mieux. Mais vous ne seriez pas en train de galérer si c'était le cas.
Dans mon cas, j'avais encore une authent fonctionnelle, mais pas accès aux hash des mots de passe. Si vous avez de la prod dessus, c'est l'occasion de voir d'où viennent les connexions, avec quels users et sur quelles bases avec un SHOW PROCESSLIST.
Personnellement, c'était du test donc j'avais un script qui me recréait tous mes utilisateurs, la question s'est pas posée.
Stopper MySQL
C'est con, mais on va devoir down un peu.
root@server:~# /etc/init.d/mysql stop
[ ok ] Stopping MariaDB database server: mysqld
Réinstaller les bases système
mysql_install_db
Et on attend.
Il est possible que suite à ça, les bases soient créées en tant que root:root. Il faudra réattribuer les bases à leur utilisateur :
root@server:~# chown -R mysql: /var/lib/mysql
Dans le cas contraire, MySQL ne démarre pas et vous averti que :
InnoDB: Operating system error number 13 in a file operation. InnoDB: The error means mysqld does not have the access rights to InnoDB: the directory.
Lancer MySQL en mode recovery
root@server:~# mysqld --skip-grant-tables --skip-networking &
[1] 20178
Rajouter les mots de passe
Ou au moins celui de debian-sys-maint. Parce que c'est chiant a faire. Vu que l'authent est désactivée, vous pouvez vous asseoir sur CREATE USER et autres GRANT. On va devoir faire ça à la roots :
mysql> INSERT INTO user(Host,User,Password,
Select_priv,Insert_priv,
Update_priv,Delete_priv,
Create_priv,Drop_priv,
Reload_priv,Shutdown_priv,
Process_priv,File_priv,
Grant_priv,References_priv,
Index_priv,Alter_priv,
Show_db_priv,Super_priv,
Create_tmp_table_priv,
Lock_tables_priv,
Execute_priv,
Repl_slave_priv,
Repl_client_priv,
Create_view_priv,
Show_view_priv,
Create_routine_priv,
Alter_routine_priv,
Create_user_priv,Event_priv,
Trigger_priv,Create_tablespace_priv)
VALUES("localhost", "debian-sys-maint", PASSWORD('monsuperpassword'),
"Y","Y","Y","Y","Y","Y","Y","Y","Y","Y",
"Y","Y","Y","Y","Y","Y","Y","Y","Y","Y",
"Y","Y","Y","Y","Y","Y","Y","Y","Y");
Query OK, 1 row affected, 4 warnings (0.00 sec)
Relancer MySQL
On va commencer par tuer le mysqld en background avec un coup de :
kill -15 $!
Si vous avez eu d'autres commandes en background, hésitez pas a plutôt récupérer le pid qui vous a été renvoyé ou le récupérer avec un ps et faites un :
kill -15 20178
ou si vous êtes un flemmard et que vous n'en avez pas un autre qui tourne :
pkill -15 mysqld
Et on redémarre normalement MySQL :
root@server:~# /etc/init.d/mysql start
[ ok ] Starting MariaDB database server: mysqld.
Voilà. Normalement vous avez fait une liste de vos utilisateurs et de leurs droits d'accès et vous les réimportez avec le script que vous en avez tiré et le tour est joué, la prod est repartie.