Serveur dédié : installation de MariaDB 10.3 photo

MariaDB : résoudre l’erreur “Column count of mysql.proc is wrong”

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 errorCode language: JavaScript (javascript)

Si cela arrive, pas de panique: MariaDB 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.

WordPress : résoudre le problème de la table wp_options à qui manquent une colonne Unique et une Primary Key photo

WordPress : résoudre le problème de la table wp_options à qui manquent une colonne Unique et une Primary Key

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-rootCode language: JavaScript (javascript)

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     |       |
+--------------+---------------------+------+-----+---------+-------+Code language: PHP (php)

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     |                |
+--------------+---------------------+------+-----+---------+----------------+Code language: PHP (php)

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-rootCode language: JavaScript (javascript)

Et on vérifie le résultat:

wp db query "DESCRIBE $(wp db prefix --allow-root)options" --allow-rootCode language: JavaScript (javascript)

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-rootCode language: JavaScript (javascript)

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'Code language: JavaScript (javascript)

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-rootCode language: JavaScript (javascript)

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)Code language: CSS (css)

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)Code language: CSS (css)

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-rootCode language: JavaScript (javascript)

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)Code language: CSS (css)

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)Code language: CSS (css)

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-rootCode language: JavaScript (javascript)

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-rootCode language: JavaScript (javascript)

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-rootCode language: JavaScript (javascript)

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     |                |
+--------------+---------------------+------+-----+---------+----------------+Code language: PHP (php)

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

MariaDB ne veut plus redémarrer : quelques solutions

MariaDB ne veut plus se lancer

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.serviceCode language: CSS (css)

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'.Code language: PHP (php)

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.

Solution: vérifier l’espace disponible sur le disque du serveur

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

tail -f /var/log/mysql/error.logCode language: JavaScript (javascript)

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] AbortingCode language: PHP (php)

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.logCode language: JavaScript (javascript)

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.Code language: PHP (php)

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).

WordPress : nettoyer les tables wp_options et wp_postmeta photo

WordPress : nettoyer les tables wp_options et wp_postmeta

Nous allons aujourd’hui examiner deux tables importantes de votre base de données WordPress, wp_options et wp_postmeta.

C’est un domaine qui est souvent négligé en ce qui concerne les performances globales de WordPress et de la base de données.

Cela est très visible sur les sites les plus anciens et les plus gros et peut être la cause des temps de requête lents sur votre site en raison des données à chargement automatique laissées par les plugins et les thèmes tiers.

Voici quelques conseils pour vérifier, dépanner et nettoyer vos tables wp_options et wp_postmeta.

Que contient la table wp_options ?

La table wp_options contient toutes les données relatives aux options et paramètres de votre site WordPress telles que:

  • URL du site, URL de la page d’accueil, adresse électronique de l’administrateur, catégorie par défaut, publications par page, format d’heure, etc.
  • Paramètres pour les plugins, les thèmes, les widgets,
  • Données temporairement mises en cache.

La table wp_options contient plusieurs champs :

  • option_id
  • option_name
  • option_value
  • autoload

Le champ qui nous intéresse particulièrement est le champ autoload, qui contient un drapeau qui peut être soit “yes”, soit “no”. Cela contrôle essentiellement si la valeur est chargée ou non par la fonction wp_load_alloptions().

Les données à chargement automatique sont des données qui sont chargées sur chaque page de votre site WordPress. L’attribut autoload est défini sur «yes» par défaut pour les développeurs, mais tous les plugins ne doivent théoriquement pas charger leurs données sur chaque page.

Le problème que les sites WordPress peuvent rencontrer est celui où la table wp_options contient une grande quantité de données auto-chargées. Cependant, la table wp_options n’a pas non plus été conçue pour contenir des milliers de lignes.

Combien coûte trop de données autoloadées? Cela peut varier, bien sûr, mais idéalement, vous voulez que la taille de votre ordinateur soit comprise entre 300 Ko et 1 Mo.

Une fois que vous commencez à approcher la plage de 3 à 5 Mo ou plus, il existe très probablement des éléments pouvant être optimisés ou supprimés du chargement automatique.

Et tout ce qui dépasse 10 Mo doit être traité immédiatement. Cela ne signifie pas toujours que cela posera un problème, mais c’est un bon point de départ.

Vérifier la taille totale des données auto-chargées

On peut calculer la taille totale des données auto-chargées d’un site WordPress en effectuant la requête suivante sous MySQL:

SELECT SUM(LENGTH(option_value)) as autoload_size FROM wp_options WHERE autoload='yes';Code language: JavaScript (javascript)

La valeur d’autoload_size est exprimée en octets. Il y a 1024 octets dans un KB et 1024 KB dans un MB. Dans notre cas, 622 138 octets sont donc égaux à 0,62 MB. Donc pour ce site, c’est une bonne taille! Si vous restituez moins de 1 Mo, ne vous inquiétez pas. Cependant, si le résultat était beaucoup plus grand, passez à l’étape suivante.

Lire la suite

The SEO Framework : résoudre l'erreur 404 du fichier sitemap.xml sous NginX photo

The SEO Framework : résoudre l’erreur 404 du fichier sitemap.xml sous NginX

Cela fait belle lurette que j’ai troqué Yoast SEO pour The SEO Framework, qui est bien mieux codé et plus performant.

Récemment, lors d’un changement de serveur, je me suis aperçu que l’un des sites avait son fichier sitemap.xml qui renvoyait une erreur 404 sous NginX.

Si cela vous arrive, deux solutions s’offrent à vous.

Vérification du server block

Commencez d’abord par vérifier que votre serveur block contient les bonnes directives pour gérer les règles de WordPress:

location / {
        # This is cool because no php is touched for static content.
        # include the "?$args" part so non-default permalinks doesn't break when using query string
        try_files $uri $uri/ /index.php?$args;
}Code language: PHP (php)

Sauvez votre server block puis relancez NginX. Il est possible que cela ne soit pas suffisant, si c’est le cas, nous allons ajouter une directive supplémentaire.

Une directive dédiée pour sitemap.xml

Ajoutons une directive supplémentaire à notre server block, qui permettra de rediriger vers la sitemap générée par The SEO Framework :

# sitemap.xml directive
# Matt Biscay
# https://www.skyminds.net/?p=30771
location = /sitemap.xml {
	rewrite ^/sitemap.xml$ "/?the_seo_framework_sitemap=xml" permanent;
}Code language: PHP (php)

Sauvez les changements et rechargez NginX – boom, la sitemap est de retour!

Linux : supprimer les vieux kernels et libérer de la place sur la partition /boot photo

Ubuntu : supprimer les vieux kernels et libérer de la place sur la partition /boot

Voici un tutoriel qui vous permet de supprimer les kernels linux installés sur votre serveur qui ne sont pas actuellement utilisés.

Cela est utile pour faire un peu de ménage sur la partition /boot, idéalement avant qu’elle ne soit complètement saturée. Sinon, je vous donne aussi l’astuce pour faire le ménage manuellement et retrouver APT complètement opérationnel.

Ce tutoriel a été testé sous Ubuntu Server 18.04 LTS, il est complètement transférable sous Ubuntu et Debian.

Cas de figure 1: /boot n’est pas plein à 100% et apt est opérationnel

1. On vérifie la version actuelle du kernel

uname -r

Cela nous donne la version du noyau sous laquelle tourne notre machine:

4.15.0-46-genericCode language: CSS (css)

2. On supprime les vieux kernels

2.a. On liste les vieux kernels

sudo dpkg --list 'linux-image*'|awk '{ if ($1=="ii") print $2}'|grep -v `uname -r`Code language: JavaScript (javascript)

You will get the list of images something like below:

linux-image-4.15.0-45-genericCode language: CSS (css)

2.b. On supprime les vieux kernels (un par un)

sudo apt purge linux-image-4.15.0-45-genericCode language: CSS (css)

Une fois que les vieux kernels sont supprimés, on supprime également les paquets qui seront maintenant obsolètes:

sudo apt autoremove

Et on finit par la mise à jour de la liste des noyaux de GRUB:

sudo update-grub

Voilà, il ne vous reste plus qu’à rebooter votre machine ou votre serveur. Il ne reste que le dernier kernel.

Cas de figure 2 : apt est indisponible car /boot est plein à 100%

NOTE: cette partie du tutoriel n’est valable que si et seulement si vous ne pouvez utiliser APT parce que la partition /boot est pleine à 100%.

1. Listez les images de kernel

Obtenez la liste des images de kernels et faites la liste des kernels que vous pouvez supprimer car ils ne sont plus utilisés. Cette commande vous montre les kernels installés à l’exception de celui qui est en cours d’utilisation:

sudo dpkg --list 'linux-image*'|awk '{ if ($1=="ii") print $2}'|grep -v `uname -r`Code language: JavaScript (javascript)

Voici le résultat de la commande, la liste des kernels installés mais inutilisés:

linux-image-3.19.0-59-generic
linux-image-3.19.0-61-generic
linux-image-3.19.0-65-generic
linux-image-extra-3.19.0-59-generic
linux-image-extra-3.19.0-61-generic
linux-image-extra-3.19.0-65-genericCode language: CSS (css)

2. Préparez la suppression

Vous devez préparer la commande qui va supprimer tous les kernels inutilisés en utilisant la brace expansion pour vous simplifier la vie. Je vous conseille d’écrire la commande dans un éditeur de texte et de bien la vérifier avant de la lancer dans le terminal.

N’oubliez pas d’exclure le kernel actuel ainsi que les deux kernels les plus récents pour pallier tout problème:

sudo rm -rf /boot/*-3.19.0-{59,61,65}-*

3. Nettoyez APT et ses messages d’avertissement à propos d’une installation partielle

sudo apt-get -f installCode language: JavaScript (javascript)

4. Autoremove

Enfin, on lance la commande autoremove pour supprimer les paquets relatifs aux vieilles images de kernel qui ont été rendues orphelines par le nettoyage manuel de /boot :

sudo apt autoremove

5. Mise à jour de GRUB

sudo update-grub

6. APT est opérationnel

Vous pouvez de nouveau utiliser APT et mettre à jour, installer et supprimer les paquets de votre distribution:

sudo apt update
NginX : résoudre

NginX : résoudre “upstream sent too big header while reading response header from upstream”

Nginx: des entêtes trop larges

Lors de la mise en ligne d’un nouveau site, je suis tombé sur une page qui ne fonctionnait pas et donnait une erreur 502 avec ce message dans les logs:

upstream sent too big header while reading response header from upstreamCode language: JavaScript (javascript)

Solution: augmenter la taille des entêtes

Si votre serveur utilise NginX, il suffit d’ajouter ces deux lignes à votre server block pour que tout rentre dans l’ordre:

fastcgi_buffers 16 16k; 
fastcgi_buffer_size 32k;

L’augmentation de la taille des buffers permet d’envoyer toutes les données d’un coup d’un seul, ce qui résout l’erreur.

Il ne reste plus ensuite qu’à relancer le serveur NginX:

service nginx restart

Hop, problème réglé.

MySQL : résoudre le message

MySQL : résoudre “Warning: Using a password on the command line interface can be insecure.”

J’ai récemment écrit un petit script bash qui me permet de sauvegarder rapidement toutes les bases de données d’un serveur. Le script est lancé par une tâche cron automatiquement, tous les jours.

Si l’on passe l’utilisateur et le mot de passe SQL dans la requête, avec mysql ou mysqldump, vous obtiendrez très certainement le message d’avertissement suivant:

Warning: Using a password on the command line interface can be insecure.Code language: PHP (php)

Et pour cause : cela veut dire que n’importe qui ayant accès au serveur pourra voir, dans les logs ou avec un simple ps, vos informations de connexion à vos bases de données. Ce n’est pas ce qui se fait de mieux en matière de sécurité !

Une solution est de passer en argument un fichier qui contiendra vos données de connexion à la base de données.

Donc, au lieu d’écrire :

mysqldump -u $USER -p$PASSWORD --databases $db > $BACKUP_PATH/$date-$db.sqlCode language: PHP (php)

Il vaut mieux écrire:

mysqldump --defaults-extra-file=/etc/mysql/mysql-backup-script.cnf --databases $db > $BACKUP_PATH/$date-$db.sqlCode language: PHP (php)

Note: L’argument --defaults-extra-file doit venir en premier, sinon il ne sera pas interprété.

Le fichier /etc/mysql/mysql-backup-script.cnf contient les identifiants de votre utilisateur SQL qui aura les droits sur chacune des bases de données à sauvegarder. Voici à quoi il ressemble:

[client]
user = 'backup'
password = 'GIGANTIC_SECURE_PASSWORD'Code language: JavaScript (javascript)

Par sécurité, on restreint les droits d’accès au fichier pour qu’il ne soit pas lisible par tout le monde:

chmod 400 /etc/mysql/mysql-backup-script.cnf

Il ne vous reste qu’à créer votre cron avec votre nouvelle commande, sans montrer les identifiants SQL en clair.

PHP : ajouter les directives

PHP : ajouter les directives “HttpOnly” et “Secure” aux cookies de session

Les directives “HttpOnly” et “Secure”

A l’heure où la grande majorité des sites internet sont passés à HTTPS, il n’est pas rare de constater que PHP ne sert toujours pas les cookies de session avec les directives “HttpOnly” et “Secure”.

Pourtant, les directives sont bien disponibles dans le fichier php.ini, il suffit donc de les activer.

Edition de php.ini

On édite donc notre fichier php.ini:

nano /etc/php/7.2/fpm/php.ini

Et on modifie ces valeurs :

session.cookie_httponly 1
session.cookie_secure 1
session.use_only_cookies 1Code language: CSS (css)

Enregistrez le fichier et relancez PHP:

service php7.2-fpm restartCode language: CSS (css)

Testez votre site de nouveau : les cookies de session contiennent maintenant les deux nouvelles directives :

set-cookie: PHPSESSID=7d5h81tfiuna3p2p00o1v7b13q; path=/; secure; HttpOnlyCode language: JavaScript (javascript)

Cela ne s’applique pas à tous les cookies créés par les plugins ou applications du site.

Il faudrait pour cela que le serveur, nginx, possède nativement le module nginx_cookie_flag_module.

Résoudre l'erreur

Résoudre l’erreur “/var/cache/debconf/config.dat is locked by another process: Resource temporarily unavailable”

Lors d’une mise à jour APT, il arrive qu’un installeur vous demande s’il faut écraser ou non un des fichiers de configuration existant. C’est le cas notamment de certaines versions de PHP qui requièrent une mise à jour du fichier php.ini.

Si vous êtes derrière votre terminal, pas de problème. Si par contre, vous ne prêtez pas attention à votre terminal, pensant que tout s’est mis à jour, ou si votre connexion SSH est rompue lors de l’installation, vous risquez d’avoir dpkg en vrac, avec une installation de paquet qui restera ‘en cours”.

Concrètement, vous obtiendrez un de ces messages:

debconf: DbDriver "config": /var/cache/debconf/config.dat is locked by another process: Resource temporarily unavailable
dpkg: error processing package XXXXX:amd64 (--configure):
 subprocess installed post-installation script returned error exit status 1
Errors were encountered while processing:
 XXXXX:amd64
needrestart is being skipped since dpkg has failed
E: Sub-process /usr/bin/dpkg returned an error code (1)Code language: PHP (php)

Mais pas de panique, il est très simple de résoudre le problème en quelques commandes.

Commencez par vérifiez quel est le processus responsable du fichier en question:

fuser -v /var/cache/debconf/config.datCode language: JavaScript (javascript)

Résultat :

USER        PID ACCESS COMMAND
/var/cache/debconf/config.dat:
root       8756 F.... frontendCode language: JavaScript (javascript)

Il ne nous reste plus qu’à tuer proprement le processus:

kill 8756

Il ne vous reste plus qu’à relancer vos commandes apt habituelles, tout est redevenu opérationnel.


Serveur dédié : résoudre l'erreur  'Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2)' — Missing /var/run/mysqld/mysqld.sock photo

Serveur dédié : résoudre l’erreur ‘Can’t connect to local MySQL server through socket ‘/var/run/mysqld/mysqld.sock’ (2)’ — Missing /var/run/mysqld/mysqld.sock

Après mise à jour du serveur SQL, il est possible d’obtenir cette erreur au redémarrage physique (boot) du serveur :

error: 'Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2)' — Missing /var/run/mysqld/mysqld.sockCode language: JavaScript (javascript)

Il se trouve que systemd lance bien le service mysql qui est donc démarré mais ne semble pas pouvoir être en mesure de créer son fichier sock. Il va donc falloir l’aider:

On crée un nouveau fichier pour systemd:

nano /etc/tmpfiles.d/mysql.conf

et on y ajoute ce code qui va permettre de chmoder et chowner le répertoire /var/run/mysqld pour l’utilisateur mysql:

# systemd tmpfile settings for mysql
# See tmpfiles.d(5) for details

d /var/run/mysqld 0755 mysql mysql -Code language: PHP (php)

Cela règle le problème définivement.

Cron : résoudre l'erreur logrotate_script: 3: [: /var/run/mysqld/mysqld.pid: unexpected operator photo

Cron : résoudre l’erreur logrotate_script: 3: [: /var/run/mysqld/mysqld.pid: unexpected operator

Depuis que j’ai déplacé les bases de données SQL sur une autre partition, logrotate semble avoir quelques soucis avec l’archivage des logs de MariaDB. Voici le message d’erreur complet :

/etc/cron.daily/logrotate: logrotate_script: 3: [: /var/run/mysqld/mysqld.pid: unexpected operatorCode language: JavaScript (javascript)

C’est en fait un problème de regex connu et la solution est très simple.

1. On édite le fichier /etc/logrotate.d/mysql-server:

nano /etc/logrotate.d/mysql-server

2. on recherche la ligne avec la regex de grep:

if [ -f `my_print_defaults --mysqld | grep -oP "pid-file=\K[^$]+"` ]; thenCode language: CSS (css)

3. on ajoute m1 aux arguments de grep, ce qui nous donne:

if [ -f `my_print_defaults --mysqld | grep -oPm1 "pid-file=\K[^$]+"` ]; thenCode language: CSS (css)

Sauvegardez le fichier. Vous ne recevrez plus de message d’erreur lors du lancement de la tâche cron et les fichiers logs de MySQL/MariaDB seront bien archivés.