Tag

terminal

Browsing

Aujourd’hui, on importe la base de données d’un site existant dans la nouvelle version de Local Lightning, estampillée 5.4.1.

D’habitude, je lance Adminer > Import, je sélectionne mon fichier de base de données et boom, la base est importée. Mais aujourd’hui, rien ne se passe comme prévu: Adminer mouline, mouline, perd la moitié du design de sa page et n’importe pas la base.

SSH à la rescousse

Je me dis qu’on aura peut-être plus de chance depuis la console SSH. Dans Local, faites un clic droit sur le site > Open Site Shell. Une fenêtre de terminal apparaît alors.

Utilisation de WP-CLI

On commence d’abord par la méthode wp-cli. On copie notre fichier adminer.sql sous /app/public et on lance la commande suivante:

wp db import ./adminer.sql

Résultat:

ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)

Cela commence bien. La version 5 de Local utilise MySQL 8 donc certaines choses ne sont peut-être pas tout à fait au point. Comme il n’y a pas de socket mysql dans /tmp/mysql.sock, nous allons manuellement spécifier notre socket MySQL dans notre commande. Local nous donne l’adresse du socket dans l’onglet Database:

wp db import ./adminer.sql --socket="/Users/matt/Library/Application Support/Local/run/rvrb6Ce-Z/mysql/mysqld.sock"

Résultat:
ERROR 1067 (42000) at line 23841 in file: './adminer.sql': Invalid default value for 'comment_date'

La bonne nouvelle, c’est que l’on peut se connecter à la base de données MySQL. Mais tiens donc, nous sommes déjà tombés sur cette erreur Invalid default value for comment_date !

Configuration de MySQL

Pour régler le problème sous Local, la marche à suivre diffère un peu de ce que nous avions lancé sur notre serveur puisqu’il n’y a pas une mais deux variables de configuration de mysqld à modifier.

On se connecte au serveur mysql:

mysql -u root -proot

Commençons par voir ce que les variables sql_mode contiennent:

SELECT @@GLOBAL.sql_mode; SELECT @@SESSION.sql_mode; 

Résultat:

+------------------------------------------------------------------------------------------+
| @@GLOBAL.sql_mode                                                                        |
+------------------------------------------------------------------------------------------+
| ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION |
+------------------------------------------------------------------------------------------+
1 row in set (0,00 sec)

+------------------------------------------------------------------------------------------+
| @@SESSION.sql_mode                                                                       |
+------------------------------------------------------------------------------------------+
| ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION |
+------------------------------------------------------------------------------------------+

Le problème est, comme la dernière fois, la présence de ces deux instructions: NO_ZERO_IN_DATE,NO_ZERO_DATE.

On enlève donc ces deux instructions de nos deux directives:

SET @@GLOBAL.sql_mode="ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION";
SET @@SESSION.sql_mode="ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION";

Voilà ce que nous obtenons au final:

+------------------------------------------------------------------------------------------+
| @@GLOBAL.sql_mode                                                                        |
+------------------------------------------------------------------------------------------+
| ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION |
+------------------------------------------------------------------------------------------+
1 row in set (0,00 sec)

+------------------------------------------------------------------------------------------+
| @@SESSION.sql_mode                                                                       |
+------------------------------------------------------------------------------------------+
| ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION |
+------------------------------------------------------------------------------------------+
1 row in set (0,00 sec)

On peut désormais importer notre fichier SQL:

mysql -u root -proot local < ./adminer.sql 

Hop l’import de la base de données se passe maintenant sans aucun problème.

De temps en temps, il faut un peu faire le ménage sur nos disques durs et il est assez utile de chercher à savoir quels sont les dossiers qui prennent le plus d’espace disque.

Sous Linux et MacOS, voici la commande que je lance pour trouver tous les répertoires de plus de 500 Mà, classés par ordre d’importance:

du -m ~/Downloads/* | awk '$1 > 500' | sort -nr

Voici le détail de la commande:

  • du signifie disk usage
  • -m signifie que l’on souhaite la taille en Mo
  • ~/Downloads/* est le chemin dans lequel se trouvent nos gros dossiers, là où se trouvent nos données
  • awk '$1 > 500' capture le chemin du dossier lorsqu’il dépasse 500 Mo
  • sort -nr permet de classer la liste du plus gros dossier au plus petit

Une petite commande à garder sous le coude, cela permet d’éviter de perdre trop de temps à trouver le dossier le plus gourmand du disque!

Chez l’un de mes clients, nous avons eu besoin de réinitialiser le mot de passe MySQL de l’utilisateur root, qui a été oublié.

Je vous avais déjà décrit comment réinitialiser le mot de passe root d’un serveur MySQL ou MariaDB sous Ubuntu.

Comme le serveur tourne sous Debian, nous avons un moyen très simple d’avoir accès à la base mysql pour modifier le mot de passe root. Cela ne prend que quelques secondes.

L’utilisateur debian-maintenance à la rescousse

Sous les systèmes à base Debian, il existe par défaut un utilisateur nommé debian-sys-maint, qui se charge de routines de maintenance sur la base SQL et qui possède tous les droits d’administration sur toutes les bases de données.

Il se trouve que le mot de passe de l’utilisateur debian-sys-maint est visible, en clair dans ce fichier:

nano /etc/mysql/debian.cnf

Copiez le mot de passe. Ensuite, connectez-vous avec debian-sys-maint au serveur de base de données:

mysql -u debian-sys-maint -p

Vous êtes maintenant connecté au serveur de base de données, en tant qu’administrateur, sous l’utilisateur debian-sys-maint.

Tous les utilisateurs de la base de données sont stockés dans la base mysqldonc on commence par la sélectionner:

use mysql;

Et on peut maintenant changer le mot de passe de l’utilisateur root avec une simple mise à jour du mot de passe:

SET PASSWORD FOR 'root'@'localhost' = PASSWORD('^*p4!_BHLn6Q&xuft*^5tjyby7^_$)d7_fgf&zec8#ExV@xY');
flush privileges;

Il ne reste plus qu’à quitter MySQL monitor:

quit;

Voilà, le mot de passe de l’utilisateur rootest désormais changé. Vous pouvez vous identifier normalement avec le nouveau mot de passe que vous venez de définir plus haut:

mysql -u root -p
Enter password:

Une astuce toujours utile à garder sous le coude!

Depuis que je suis passé à MacOS X Catalina, j’ai ajouté l’outil capture d’écran dans la Touchbar, histoire de toujours l’avoir à portée de main.

Pour les puristes, vous pouvez capturer l’écran avec Shift-Command-5 (à partir de Mojave et supérieur) ou Shift-Command-3.

Par contre, toutes les captures d’écran sont préfixées par défaut avec “Capture d’écran” suivie de la date et de l’heure. Cela peut être gênant lorsque l’on publie cette image sur internet, étant donné que les noms de fichiers accentués ne sont pas toujours bien gérés.

Voici donc une petite astuce pour changer le préfixe pour celui de votre choix. Dans mon exemple, je l’ai tout simplement changé pour “Screenshot”.

Changer le nom de fichier par défaut de l’outil capture d’écran

Ouvrez le terminal puis lancez la commande suivante, en remplaçant “Screenshot” par le préfixe de votre choix:

defaults write com.apple.screencapture name "Screenshot"

Relancez ensuite le service SystemUI:

killall SystemUIServer

Lancez ensuite l’outil de capture d’écran et enregistrez votre capture. Elle est maintenant préfixée par ce que vous avez choisi.

Activer SSH sous CPanel photo 4

Lors d’une connexion SSH sur le serveur d’un client chez WPEngine, je suis tombé sur le message d’erreur suivant:

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@         WARNING: UNPROTECTED PRIVATE KEY FILE!          @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions 0644 for '/Users/matt/.ssh/id_ed25519.pub' are too open.
It is required that your private key files are NOT accessible by others.
This private key will be ignored.
Load key "/Users/matt/.ssh/id_ed25519.pub": bad permissions

Voici la commande que j’avais entré:

ssh -i ~/.ssh/id_ed25519.pub -o IdentitiesOnly=yes EXAMPLE@wEXAMPLE.ssh.wpengine.net

Au lieu d’utiliser ma clé privée, j’ai utilisé ma clé publique (id_ed25519.pub) qui – comme elle est publique – bénéficie de droits plus large que la clé privée.

Il faut donc relancer la commande en retirant l’extension .pub du chemin de la clé, pour que la clé privée soit prise en compte:

ssh -i ~/.ssh/id_ed25519 -o IdentitiesOnly=yes EXAMPLE@wEXAMPLE.ssh.wpengine.net

Dès lors, plus de problème de connexion et la connexion sur le serveur WPEngine se fait sans souci:

  ____  _____  _____
 ╱   ▕ ▕    ▕ ▕    ▕
▕    ▕ ▕    ▕ ▕    ▕
▕____▕  ╲___╱  ╲___▕                                      ▫
 ____           ____     ▃  ▃  ▃  ▃▃▃    ___   __    __      __   ___
▕    ▕    _    ╱   ▕     █  █  █ ▕█▀▀▙  ▕___) |  ▕  ╱  ▕ ▕  |  ▕ ▕___)
▕    ▕   ( )  ▕    ▕      ██ ██  ▕███▛  ▕     |  ▕ ▕   ▕ ▕  |  ▕ ▕
▕____╱    ‾    ╲___▕       █ █   ▕█      ╲__╱ |  ▕  ╲__▕ ▕  |  ▕  ╲__╱
 ____    ___   ___                                  ___╱
▕    ╲  ╱   ╲ ▕    ╲
▕    ▕ ▕    ▕ ▕    ▕
▕____╱ ▕____▕ ▕____▕

WP Engine Shell - PHP 7.3

Git – et son homologue Github – permet de versionner votre code afin de pouvoir commenter les changements de code, revenir en arrière et annuler une modification en cas de problème, tenir une feuille de route, accepter des demandes de modifications venant d’autres développeurs (pull requests) et permettre la collaboration de plusieurs personnes sur un même projet.

Voici un petit tuto pour vous donner les commandes essentielles qui permettent de créer le dépôt, ajouter du code et l’envoyer sur Github.

Installation de Git

Commençons par l’étape obligatoire qui est l’installation de Git sur votre système d’exploitation:

MacOSX : résoudre l’erreur xcrun: error: invalid active developer path

Sous MacOSX, lorsque vous lancez une commande git, vous pouvez obtenir le message d’erreur suivant:

xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools), missing xcrun at: /Library/Developer/CommandLineTools/usr/bin/xcrun

Cela signifie qu’il vous manque les outils de développement XCode. Cela peut arriver après chaque mise à jour d’OSX donc vous pouvez les installer avec:

xcode-select --install

Créer un nouveau dépôt Git et l’associer à votre dépôt GitHub

Placez-vous dans le répertoire qui contient votre code. On crée un nouveau dépôt Git avec:

git init

Cela initialise votre répertoire avec les dossiers cachés de git. On ajoute maintenant l’adresse de notre dépôt sur GitHub:

git remote add origin https://github.com/example/example-project

Nous allons maintenant pouvoir ajouter notre code.

Ajouter et valider votre code

Pour ajouter des fichiers, on utilise la directive add:

git add *
git add <filename>

Ensuite, on valide avec un message qui explique la validation des changements:

git commit -m "Ajout des fichiers du projet"

A ce stade, le fichier est dans le HEAD de git, mais pas encore dans votre dépôt distant. On l’envoie donc sur GitHub avec:

git push origin master

Pour mettre à jour votre dépôt local vers les dernières validations qui se trouvent sur GitHub (attention, cela écrase les fichiers locaux!), exécutez la commande:

git pull

Voilà, c’est un petit mémo simple mais il permet déjà de se servir des principales fonctions de git.

Activer SSH sous CPanel photo 4

Sur un nouveau serveur à base d’Ubuntu Server 18.04, j’obtiens cette erreur à la suite d’un test du service ssh:

sshd -t

Could not load host key: /etc/ssh/ssh_host_ed25519_key
Missing privilege separation directory: /run/sshd

Les solutions à ces deux problèmes sont triviales, cela se règle en deux petites commandes.

L’erreur Could not load host key

L’erreur Could not load host key survient lorsque certaines clés SSH n’ont pas été générées lors de l’installation du système d’exploitation du serveur.

Dans le cas du serveur qui nous occupe, il nous manque la clé de chiffrement ED25519 qui doit se trouver à l’adresse /etc/ssh/ssh_host_ed25519_key.

Pour générer toutes les clés de chiffrement SSH manquantes, une seule commande suffit:

ssh-keygen -A

L’argument -A signifie que l’on génère toutes les clés (All keys). Voici le résultat sur le serveur:

ssh-keygen: generating new host keys: ED25519

L’erreur Missing privilege separation directory: /run/sshd

Cette erreur apparaît lorsque le répertoire mentionné – ici /run/sshd – n’a pas été correctement créé. Il suffit de le créer:

mkdir -p /run/sshd

Vérifiez la configuration SSH:

sshd -t

S’il n’y a plus d’erreur, vous pouvez alors redémarrer le service ssh:

service ssh restart

Et voilà, problèmes réglés.

Auto Draft photo

Le hotlinking (ou liaison automatique ; aussi connu en anglais sous les noms de inline linking, leeching, piggy-backing, direct linking ou offsite image grabs) consiste à utiliser l’adresse d’un fichier publié sur un site web, le plus souvent une image, pour l’afficher sur un autre site, sur un blog, dans un forum, etc.

En d’autres termes, au lieu d’enregistrer l’image et de l’installer sur son propre serveur Web, le hotlinkeur crée un lien direct vers le serveur d’origine.

Sous NginX, il peut être très utile d’éviter que des gens publient vos photos ou images sur votre site, en gardant les liens de votre serveur et en consommant toute votre bande passante.

Il suffit d’éditer votre server block et d’y ajouter cette directive:

location ~ .(gif|png|jpeg|jpg|svg)$ {
     valid_referers none blocked ~.google. ~.bing. ~.yahoo. ~.facebook. ~.pinterest. ~.twitter. yourdomain.com *.yourdomain.com server_names;
     if ($invalid_referer) {
        return   403;
    }
}

N’hésitez pas à rajouter les domaines que vous souhaitez whitelister et qui sont autorisés à utiliser vos fichiers média.

Relancez ensuite NginX avec:

service nginx restart

Cela devrait quelque peu soulager votre serveur et garantir votre bande passante à vos visiteurs.

Je vous ai déjà parlé du chmod et du chown de manière extensive mais aujourd’hui on va un tout petit peu plus loin.

La valeur du chmod telle qu’elle apparaît dans le terminal est un peu esotérique. Prenons par exemple le chmod d’un fichier standard de WordPress : -rw-r-----, cela demande une petite gymnastique intellectuelle pour réaliser quels sont les droits véritables.

Je vous propose donc une petite commande qui va vous simplifier la vie, de manière à vous donner la valeur numérique du chmod des fichiers et répertoires.

Il vous suffit d’utiliser la commande stat comme ceci, dans votre fenêtre de terminal:

stat -c '%a %U:%G %n' *

Notes:

  • -c permet de formater la sortie avec la template entre apostrophes
  • %a donne la valeur octale du chmod
  • %U donne le nom de l’utilisateur du chown
  • %G donne le groupe de l’utilisateur du chown
  • %n donne le nom du fichier

Et voilà simple et efficace!

Serveur dédié : installation de MariaDB 10.3 photo

Sur l’un des serveurs de mes clients Codeable, j’ai mis à jour MariaDB de la version 10.1 à la version 10.3 et voici ce que retournait MariaDB lors du lancement de procédures:

ERROR 1558 (HY000): Column count of mysql.proc is wrong. Expected 21, found 20. 
Created with MariaDB 100212, now running 100303. 
Please use mysql_upgrade to fix this error

Si cela arrive, pas de panique: MaraDB fonctionne et le site s’affiche mais la base de données mysql n’a pas été mise à jour par apt, il faut lancer la procédure d’installation manuellement, depuis le terminal.

On met donc la base mysql à jour avec mysql-upgrade:

mysql_upgrade -u root -p

et on relance MariaDB:

service mysql restart

La routine de mise à jour mysql_upgrade permet de mettre à jour la base interne de MariaDB, qui évolue au fil des mises à jour.

Au redémarrage du service, plus de problème avec les procédures SQL.

Chez Codeable, j’ai travaillé sur l’optimisation d’un site e-commerce propulsé par WooCommerce récemment, qui connaissait quelques problèmes de lenteur.

Sous phpMyAdmin, on trouvait également cette erreur:

Current selection does not contain a unique column

Si vous obtenez cette erreur, c’est que la structure de la table wp_options n’est pas à jour donc nous la vérifions avec wp-cli:

wp db query "DESCRIBE $(wp db prefix --allow-root)options" --allow-root

Le résultat obtenu nous montre qu’il n’y a pas de clé primaire (primary key) qui est normalement option_id et qu’il n’y a pas de restriction unique imposée sur la colonne option_name:

+--------------+---------------------+------+-----+---------+-------+
| Field        | Type                | Null | Key | Default | Extra |
+--------------+---------------------+------+-----+---------+-------+
| option_id    | bigint(20) unsigned | NO   |     | NULL    |       |
| option_name  | varchar(191)        | YES  |     | NULL    |       |
| option_value | longtext            | NO   |     | NULL    |       |
| autoload     | varchar(20)         | NO   |     | yes     |       |
+--------------+---------------------+------+-----+---------+-------+

Et c’est là que le bât blesse – voici à quoi ressemble la structure standard de la table wp-options:

+--------------+---------------------+------+-----+---------+----------------+
| Field        | Type                | Null | Key | Default | Extra          |
+--------------+---------------------+------+-----+---------+----------------+
| option_id    | bigint(20) unsigned | NO   | PRI | NULL    | auto_increment |
| option_name  | varchar(191)        | NO   | UNI | NULL    |                |
| option_value | longtext            | NO   |     | NULL    |                |
| autoload     | varchar(20)         | NO   | MUL | yes     |                |
+--------------+---------------------+------+-----+---------+----------------+

Ajouter la Primary Key manquante à wp_options

On ajoute à la colonne option_id la clé primaire qui lui manque:

wp db query "ALTER TABLE $(wp db prefix --allow-root)options MODIFY option_id INT AUTO_INCREMENT PRIMARY KEY;" --allow-root

Et on vérifie le résultat:

wp db query "DESCRIBE $(wp db prefix --allow-root)options" --allow-root

Ajouter la contrainte Unique qui manque à wp_options

Pour ajouter la contrainte UNIQUE à la colonne option_name, on lance:

wp db query "ALTER TABLE $(wp db prefix --allow-root)options ADD UNIQUE (option_name);" --allow-root

Là, il est possible que cela bloque, suivant ce qui se trouve dans votre table wp_options.

Résoudre le problème des doublons

Si vous obtenez une erreur comme :

ERROR 1062 (23000) at line 1: Duplicate entry 'jetpack_available_modules' for key 'option_name'

alors cela signifie qu’il existe des enregistrements option_name dupliqués, des doublons qui portent le même nom alors que chaque nom option_name devrait être unique.

On peut obtenir la liste des enregistrements option_name doublons avec cette requête:

wp db query "SELECT option_name, COUNT(*) optioncount FROM $(wp db prefix --allow-root)options GROUP BY option_name HAVING optioncount > 1 ORDER BY optioncount DESC;" --allow-root

Par ordre ascendant, voici la liste des doublons:

+---------------------------------------------+-------------+
| option_name                                 | optioncount |
+---------------------------------------------+-------------+
| jetpack_callables_sync_checksum             |       47123 |
| jetpack_sync_full_config                    |          50 |
| jetpack_sync_full_enqueue_status            |          43 |
| jpsq_sync_checkout                          |          10 |
| jetpack_sync_full__params                   |           5 |
| jetpack_sync_settings_sync_via_cron         |           4 |
| jetpack_sync_full__started                  |           4 |
+---------------------------------------------+-------------+

On peut supprimer automatiquement tous les doublons option_name de deux manières différentes, soit en utilisant la plus vieille valeuroption_id(donc la plus petite valeur d’ID), soit en utilisant la valeuroption_id la plus récente (plus grande valeur d’ID).

Garder le doublon option_name le plus ancien

Voici la requête SQL qui montre uniquement le plus ancien enregistrement (MIN) option_id pour chaque doublon de valeur option_name:

SELECT *
FROM wp options
WHERE option_id NOT IN
    (SELECT *
     FROM
       (SELECT MIN(n.option_id)
        FROM wp_options
        GROUP BY n.option_name) x)

Une fois que vous avez vérifié le résultat, on peut passer à la suppression.

Cette requête SQL garde l’enregistrement (MIN) option_id le plus ancien de tous les doublonsoption_name et supprime tous les enregistrements plus récents que la valeur trouvée:

DELETE
FROM wp options
WHERE option_id NOT IN
    (SELECT *
     FROM
       (SELECT MIN(n.option_id)
        FROM wp_options n
        GROUP BY n.option_name) x)

Voici l’équivalent wp-cli:

wp db query "DELETE FROM $(wp db prefix --allow-root)options WHERE option_id NOT IN (SELECT * FROM (SELECT MIN(n.option_id) FROM $(wp db prefix --allow-root)options n GROUP BY n.option_name) x)" --allow-root

Garder le doublon option_name le plus récent

Cette requête SQL ne montre que les enregistrements option_id les plus récents (MAX) pour tous les doublons option_name :

SELECT *
FROM wp_options
WHERE option_id NOT IN
    (SELECT *
     FROM
       (SELECT MAX(n.option_id)
        FROM wp_options n
        GROUP BY n.option_name) x)

Et voici la requête qui permet de garder les enregistrements option_id les plus récents (MAX) pour tous les doublons option_name en supprimant tous les doublons les plus anciens:

DELETE
FROM wp_options
WHERE option_id NOT IN
    (SELECT *
     FROM
       (SELECT MAX(n.option_id)
        FROM wp_options n
        GROUP BY n.option_name) x)

Voici l’équivalent wp-cli pour garder l’enregistrement option_name le plus récent:

wp db query "DELETE FROM $(wp db prefix --allow-root)options WHERE option_id NOT IN (SELECT * FROM (SELECT MAX(n.option_id) FROM $(wp db prefix --allow-root)options n GROUP BY n.option_name) x)" --allow-root

Vérifier les clés et contraintes de la table wp_options

Ajoutons de nouveau la contrainte UNIQUE sur la colonne option_name :

wp db query "ALTER TABLE $(wp db prefix --allow-root)options ADD UNIQUE (option_name);" --allow-root

Si vous n’obtenez pas d’erreur, vérifiez la table une nouvelle fois pour constater les changements:

wp db query "DESCRIBE $(wp db prefix --allow-root)options;" --allow-root

Kaboom! Votre table wp_options possède maintenant une PRIMARY KEY sur la colonne option_id et la contrainte UNIQUE sur la colonne option_name:

+--------------+---------------------+------+-----+---------+----------------+
| Field        | Type                | Null | Key | Default | Extra          |
+--------------+---------------------+------+-----+---------+----------------+
| option_id    | bigint(20) unsigned | NO   | PRI | NULL    | auto_increment |
| option_name  | varchar(191)        | NO   | UNI |         |                |
| option_value | longtext            | NO   |     | NULL    |                |
| autoload     | varchar(20)         | NO   |     | yes     |                |
+--------------+---------------------+------+-----+---------+----------------+

Je vous conseille de vérifier la structure de la table de temps à autre, notamment si vous constatez une prise de poids anormale en très peu de temps

Serveur dédié : installation de MariaDB 10.3 photo

Sur le serveur chinois que j’ai monté pour un de mes clients sur Codeable, le site a commencé à afficher des erreurs étranges : erreur 502 pour nginx sur certaines pages et des nombres étranges en lieu et place des données de la base de données.

Après un redémarrage des services PHP, nginx et mysql, je constate que MariaDB veut bien s’arrêter mais ne veut plus de lancer.

Voici ce que donne:

systemctl status mariadb.service

Résultat:

● mariadb.service - MariaDB database server
   Loaded: loaded (/lib/systemd/system/mariadb.service; enabled; vendor preset: enabled)
   Active: failed (Result: exit-code) since Mon 2019-04-22 18:14:22 CST; 59s ago
  Process: 721 ExecStartPost=/bin/sh -c systemctl unset-environment _WSREP_START_POSITION (code=exited, status=0/SUCCESS)
  Process: 718 ExecStartPost=/etc/mysql/debian-start (code=exited, status=0/SUCCESS)
  Process: 12274 ExecStart=/usr/sbin/mysqld $MYSQLD_OPTS $_WSREP_NEW_CLUSTER $_WSREP_START_POSITION (code=exited, status=1/FAILURE)
  Process: 12179 ExecStartPre=/bin/sh -c [ ! -e /usr/bin/galera_recovery ] && VAR= ||   VAR=`/usr/bin/galera_recovery`; [ $? -eq 0 ]   && systemctl set-environment _WSREP_START_POSITION=$VAR || exit 1 (code=exited,
  Process: 12176 ExecStartPre=/bin/sh -c systemctl unset-environment _WSREP_START_POSITION (code=exited, status=0/SUCCESS)
  Process: 12173 ExecStartPre=/usr/bin/install -m 755 -o mysql -g root -d /var/run/mysqld (code=exited, status=0/SUCCESS)
 Main PID: 12274 (code=exited, status=1/FAILURE)
   Status: "MariaDB server is down"
systemd[1]: Starting MariaDB database server…
mysqld[12274]: 2019-04-22 18:14:19 140194687476288 [Note] /usr/sbin/mysqld (mysqld 10.1.26-MariaDB-0+deb9u1) starting as process 12274 …
systemd[1]: mariadb.service: Main process exited, code=exited, status=1/FAILURE
systemd[1]: Failed to start MariaDB database server.
systemd[1]: mariadb.service: Unit entered failed state.
systemd[1]: mariadb.service: Failed with result 'exit-code'.

Bon, chou blanc. Cela ne nous donne aucune information exploitable quand à l’erreur qui empêche le démarrage du service de base de données.

On regarde ensuite ce que nous donnent les logs de MariaDB:

tail -f /var/log/mysql/error.log

Résultat:

2019-04-22 18:14:19 140194687476288 [Note] InnoDB: Completed initialization of buffer pool
2019-04-22 18:14:19 140194687476288 [Note] InnoDB: Highest supported file format is Barracuda.
2019-04-22 18:14:19 140194687476288 [Note] InnoDB: 128 rollback segment(s) are active.
2019-04-22 18:14:19 140194687476288 [Note] InnoDB: Waiting for purge to start
2019-04-22 18:14:19 140194687476288 [Note] InnoDB:  Percona XtraDB (http://www.percona.com) 5.6.36-82.1 started; log sequence number 11397472969
2019-04-22 18:14:19 140194687476288 [Note] Plugin 'FEEDBACK' is disabled.
2019-04-22 18:14:19 140194687476288 [ERROR] mysqld: Can't change size of file (Errcode: 28 "No space left on device")
2019-04-22 18:14:19 140194687476288 [ERROR] Can't init tc log
2019-04-22 18:14:19 140194687476288 [ERROR] Aborting

Là, c’est beaucoup plus intéressant. Visiblement, deux erreurs majeures sont à l’origine du non-démarrage du service:

  • il n’y a plus d’espace disponible sur le disque dur du serveur,
  • le fichier /var/lib/mysql/tc.log ne peut pas être initialisé.

Après un petit df, il s’avère que le client a installé un plugin de sauvegarde qui a littéralement saturé tout l’espace disponible.

Après un petit ménage, il ne reste plus qu’à gérer la seconde erreur, Can’t init tc log.

Le fichier /var/lib/mysql/tc.log peut parfois souffrir d’un problème de permission. Dans le cas du client, on l’archive par précaution:

mv /var/lib/mysql/tc.log /var/lib/mysql/tc_bakup.log

Puis on relance le serveur MariaDB:

service mysql start

On vérifie le statut du service:

service mysql status

qui nous retourne:

service mysql status
● mariadb.service - MariaDB database server
   Loaded: loaded (/lib/systemd/system/mariadb.service; enabled; vendor preset: enabled)
   Active: active (running) since Mon 2019-04-22 18:17:22 CST; 1h 37min ago
  Process: 12467 ExecStartPost=/bin/sh -c systemctl unset-environment _WSREP_START_POSITION (code=exited, status=0/SUCCESS)
  Process: 12464 ExecStartPost=/etc/mysql/debian-start (code=exited, status=0/SUCCESS)
  Process: 12340 ExecStartPre=/bin/sh -c [ ! -e /usr/bin/galera_recovery ] && VAR= ||   VAR=`/usr/bin/galera_recovery`; [ $? -eq 0 ]   && systemctl set-environment _WSREP_START_POSITION=$VAR || exit 1 (code=exited,
  Process: 12337 ExecStartPre=/bin/sh -c systemctl unset-environment _WSREP_START_POSITION (code=exited, status=0/SUCCESS)
  Process: 12334 ExecStartPre=/usr/bin/install -m 755 -o mysql -g root -d /var/run/mysqld (code=exited, status=0/SUCCESS)
 Main PID: 12437 (mysqld)
   Status: "Taking your SQL requests now..."
    Tasks: 29 (limit: 4915)
   CGroup: /system.slice/mariadb.service
           └─12437 /usr/sbin/mysqld

Apr 22 18:17:20 iZuf6aj6jz83uxa0jgbgcrZ systemd[1]: Starting MariaDB database server...
Apr 22 18:17:21 iZuf6aj6jz83uxa0jgbgcrZ mysqld[12437]: 2019-04-22 18:17:21 139940495544896 [Note] /usr/sbin/mysqld (mysqld 10.1.26-MariaDB-0+deb9u1) starting as process 12437 ...
Apr 22 18:17:22 iZuf6aj6jz83uxa0jgbgcrZ systemd[1]: Started MariaDB database server.

A noter que l’erreur 502 de nginx n’était pas due à une mauvaise configuration du server block mais bien d’un manque d’espace disque. C’est important à vérifier, avant de se lancer dans la dissection du fichier de configuration d’nginx (qui n’aurait pas réglé le problème dans ce cas précis).

Spelling error report

The following text will be sent to our editors: