Table des matières
Bonjour à tous,
Dans cet article, je vais vous expliquer ma mésaventure avec les dates de mes fichiers sous Nextcloud suite à une migration. Les manipulations dont je vais parler sont celles que j’ai utilisé, mais vous devrez les adapter à votre situation. Quoi qu’il en soit, je vous recommande d’être prudent et de toujours faire des sauvegardes.
Les dates et les fichiers
Chaque fichier possède des métadonnées pour le décrire et notamment plusieurs dates:
- mtime (modification time): indique la dernière date de modification du fichier.
- atime (access time): indique la dernière date d’accès du fichier (par vous, un autre utilisateur ou un programme).
- ctime (creation time): indique la date de création du fichier.
Toutes ces dates sont relatives à Epoch qui représente la date initiale à partir de laquelle est mesuré le temps par les systèmes d’exploitation. La plus utilisée est celle notamment utilisée par les systèmes Unix et datant du 1er janvier 1970. À l’heure où j’écris ces lignes, il s’est passé 1592667597 secondes depuis cette date, si je crée un fichier maintenant, il aura cette date dans la variable ctime (plus les quelques secondes le temps d’écrire ceci et de le créer).
Nextcloud ?
Pour ceux ne connaissant pas Nextcloud, c’est un logiciel libre servant à la base pour héberger des fichiers “à la Dropbox”. Vous pouvez l’installer sur votre serveur, et vos fichiers seront alors disponibles et synchronisés sur vos différents périphériques.
On retrouve maintenant beaucoup plus de fonctionnalités notamment grâce au fait qu’il est possible de réaliser des applications (comprendre ici des extensions) qu’il est possible d’installer sur Nextcloud. On retrouve notamment: calendrier, gestionnaires de contacts, outil de visioconférence, éditeur de texte en ligne, gestionnaire de mots de passe … Vous pouvez retrouver ici toutes les applications répertoriées sur le store officiel.
Un souci de date ?
Comme j’en parlais dans mon précédent article, je suis en train de migrer petit à petit tous mes services sur Docker. Il se trouve que le 10 mai dernier, j’ai entre autres migré mon serveur Nextcloud. La migration s’est très bien passée (bien que la copie des 230Go de données prenne un peu de temps ^^).
Le problème ne vient pas forcément du nombre important de Gigaoctets de données mais plutôt du nombre de fichiers … Il y avait en effet 142 932 dossiers pour 256 750 fichiers. Le plus simple pour copier autant de fichiers et pouvoir reprendre en cas de coupure (réseau ou autre) est selon moi d’utiliser rsync (un outil pour copier des fichiers d’une source vers une destination). Le souci vient du fait que j’ai oublié de mettre les options -az
avec l’option -a
qui inclut notamment l’option -t
qui permets de préserver les dates de modifications.
Donc pour éviter tous problèmes, je vous recommande d’utiliser cette option, et tout ira bien !
Bref, j’ai donc migré toutes mes données en écrasant les dates de modifications. Je ne m’en suis rendu compte que récemment pour une autre raison. En réalité, Nextcloud stocke en base de données les dates de modifications donc les dates s’affichaient correctement après la migration. Récemment, j’ai essayé l’application Temporary files lock mais qui générait plein de soucis dans les logs à cause du chiffrement des données. J’ai fini par la supprimer et j’ai dû faire la commande occ files:scan --all
qui permets notamment de scanner les fichiers et de mettre à jour le cache des fichiers. En l’occurrence, les dates de modifications des fichiers sont stockées dans ce fameux cache de Nextcloud. En lançant cette commande, j’ai donc mis dans le cache de Nextcloud les dates de modifications des fichiers telles qu’elles le sont sur les fichiers sur le serveur, à savoir le 10 mai 2020, date de la copie et de la migration.
J’ai mis 2 jours (après la commande de scan complet) à m’en rendre compte, je me suis d’abord assuré de ne pas avoir perdu de fichiers. En réalité, ce qui m’a interpellé était que le client lourd de Nextcloud était en train de télécharger de nouveau toutes les données. En fait, c’était parce que les dates des fichiers avaient changés, donc il considérait (à raison) que les fichiers étaient différents. Je me suis tout d’abord résigné à avoir perdu les dates correctes de mes fichiers …
Comment s’en sortir ?
Les chemins des fichiers que nous allons voir ont été falsifiés, mais j’ai essayé de garder une cohérence ! Tout ce qui va être réalisé ci-dessous devra être adapté à votre cas !
Récupérer la bonne sauvegarde
Et puis le lendemain, j’étais quand même titillé … J’ai des sauvegardes, j’ai donc les dates correctes de mes fichiers.
J’utilise borg (un outil de sauvegarde incrémentielle) et j’ai donc lancé la commande borg list <repo-name>
pour lister les dates des dernières sauvegardes:
2020-01-31T03:49:56 Fri, 2020-01-31 03:50:06 [...]
2020-02-27T01:00:22 Thu, 2020-02-27 01:00:27 [...]
2020-03-31T04:49:00 Tue, 2020-03-31 04:49:07 [...]
2020-04-30T14:41:46 Thu, 2020-04-30 14:42:01 [...]
2020-05-09T04:45:26 Sat, 2020-05-09 04:45:35 [...]
2020-05-17T04:11:30 Sun, 2020-05-17 04:11:37 [...]
2020-05-24T03:46:16 Sun, 2020-05-24 03:46:23 [...]
2020-05-31T04:09:33 Sun, 2020-05-31 04:09:48 [...]
2020-06-06T04:12:54 Sat, 2020-06-06 04:13:01 [...]
2020-06-07T04:11:12 Sun, 2020-06-07 04:11:27 [...]
2020-06-08T04:11:20 Mon, 2020-06-08 04:11:28 [...]
2020-06-09T04:05:21 Tue, 2020-06-09 04:05:30 [...]
2020-06-10T04:01:21 Wed, 2020-06-10 04:01:29 [...]
2020-06-11T03:54:33 Thu, 2020-06-11 03:54:44 [...]
On peut voir ici un bel exemple de la politique de nettoyage (lancée une seule fois par semaine) que j’utilise avec borg:
borg prune --list --keep-daily=7 --keep-weekly=4 --keep-monthly=-1 --keep-within=2d <repo-name>
À savoir qu’on garde 1 sauvegarde par mois (on voit les mois de janvier, février …), 1 sauvegarde par semaine sur les 4 dernières semaines (toutes celles du mois de mai), 1 sauvegarde par semaine sur les 7 derniers jours (toutes les dernières) et toutes les sauvegardes réalisées sur les 2 derniers jours.
Si vous avez finement observé, on ne devrait pas voir une sauvegarde le samedi 9 mai mais plutôt le dimanche 10 mai. Et bien oui, mais la sauvegarde du 10 mai à pris plus de 24 heures (c’est un petit Raspberry Pi qui gère les sauvegardes sur un disque dur dédié), et le 10 mai, on avait plus de 200Go à sauvegarder (beaucoup pour un Raspberry Pi !). Coup de bol pour moi puisque plus d’un mois après, ça me donne une sauvegarde datant de la veille de la migration (autrement, ça aurait été le 30 avril, soit un delta de 10 jours perdus).
La commande (plutôt longue sur un Raspberry Pi) borg mount <repo-name>::2020-05-09T04:45:26 /tmp/borg/
(après avoir créé ce dossier /tmp/borg/
) nous mets à disposition les fichiers tels qu’ils étaient le jour du 9 mai au petit matin.
Un script pour récupérer les dates des fichiers
Bien sûr, on ne va pas recopier les fichiers, mais simplement récupérer leurs dates ! J’ai pour cela trouvé un script qui faisait ce que je voulais (je laisse une copie ici si jamais).
J’ai donc modifié la ligne 72 pour changer le chemin d’utilisation du script (j’ai remplacé le .
par le chemin de mes données (exemple: /tmp/borg/nextcloud/data/pofilo/files/
)).
Ensuite, j’ai donné les droits d’exécution au script (chmod +x save-file-attrs.py
) puis je l’ai lancé en mode sauvegarde: ./save-file-attrs.py save
.
Le script m’a donc généré un fichier .saved-file-attrs
avec un contenu du genre:
"/tmp/borg/nextcloud/data/pofilo/files/Images/Mobile/Camera/20190811_201341.jpg": {
"uid": 33,
"gid": 33,
"mode": 33188,
"mtime": 1566850199.0,
"atime": 1566895773.184171,
"ctime": 1566895773.184171
}
Si on va voir sur le site EpochConverter, on voit bien que la date de modification (mtime) date du 26 août 2019.
Une commande pour récupérer les fichiers modifiés depuis la sauvegarde
Toutes les commandes réalisées ci-dessous sont à faire sur le serveur en production. Je vous impose de faire une sauvegarde avant (fichiers + base de données !). J’ai la chance d’avoir une réplication de mon serveur sur une machine virtuelle, j’ai donc pu tester dessus avant de le faire en production.
Maintenant que votre sauvegarde est réalisée et fonctionnelle, nous pouvons continuer.
On passe Nextcloud en mode maintenance en éditant le fichier /data/nextcloud/config/config.php
où l’on met la variable maintenance à true: 'maintenance' => true,
.
La sauvegarde datait du 9 mai, nous sommes (le soir où j’ai fait les manipulations) le 19 juin. On a donc 39 jours entre les 2. Notre fichier .saved-file-attrs
possède les dates de tous les fichiers au 9 mai, mais depuis, certains fichiers ont pu être modifiés, on les liste donc via la commande: find /data/nextcloud/data/pofilo/files -type f -mtime -39 -print > /tmp/find.txt
.
Le fichier /tmp/find.txt
généré contient donc une liste de tous les fichiers modifiés dans les 39 derniers jours. À priori, les espaces dans les noms de fichiers sont gérés de la même façon entre la commande find et le script utilisé plus haut mais pas les accents dans les noms de fichiers (faîtes donc attention si vous en avez !).
Notre fichier .saved-file-attrs
possède les chemins absolus des fichiers mais avec le chemin du dossier monté par borg, il faut donc les corriger (dans notre cas, il faut remplacer /tmp/borg/
par /data/
, on utilise donc une commande comme: sed -i 's|/tmp/borg/|/data/|g' .saved-file-attrs
).
Un autre script pour restaurer les dates des fichiers
J’ai donc fait un petit script python pour retirer les fichiers récemment modifiés (ceux de find.txt
) à la liste de ceux de la sauvegarde (le fichier .saved-file-attrs
). Vous pouvez retrouver le script ici.
Ce dernier va lire (oui les noms de fichiers sont codés en dur, on va au plus simple !), les fichiers .saved-file-attrs.bak
et find.txt
et créer un fichier .saved-file-attrs
qui contiendra donc le même contenu que l’ancien, mais sans les fichiers modifiés dans les 39 derniers jours.
On fait donc mv .saved-file-attrs .saved-file-attrs.bak
pour renommer le fichier qui va être utilisé par le script puis on lance le script (possédant les droits d’exécution) ./remove-modified.py
.
Pour chaque fichier présent dans find.txt
, le script va vous dire:
- Soit
not found <file>
si le fichier n’existait pas du temps de la sauvegarde, on peut donc l’ignorer. - Soit
removed (existed but changed since) <file>
si le fichier existait du temps de la sauvegarde mais a depuis été modifié (on veut également l’ignorer et ne pas restaurer sa date au temps de la sauvegarde).
Le premier script pour restaurer les dates
Maintenant que les fichiers modifiés ont été supprimés de la liste, on peut réutiliser le script de tout à l’heure en mode restauration: ./save-file-attrs.py restore
(il va restaurer les dates présentes dans le fichier .saved-file-attrs
).
Une dernière passe sur Nextcloud et la base de données
La commande que nous allons utiliser nécessite une instance de Nextcloud fonctionnelle, on retire donc le mode maintenance ajouté précédemment.
Comme je l’ai dit précédemment, Nextcloud stocke les dates de modifications des fichiers en base de données. On va lui faire mettre à jour sa base via la commande occ files:scan --path pofilo/files/
(je vous conseille de regarder la documentation pour adapter la commande à votre cas).
Le problème avec la commande scan de Nextcloud est qu’elle modifie les dates des dossiers comme étant modifiés à l’instant. Mais comme le montre cet utilisateur sur Github, les dates des dossiers sont encore présentes en base de données.
On les modifie donc via les commandes:
$ mysql -u nextcloud -p
> use nextcloud;
> UPDATE oc_filecache SET mtime=storage_mtime;
Et voilà! On retrouve enfin nos fichiers (et dossiers) avec des dates plus authentiques (dans mon cas, certains dataient de plus de 10 ans). Ayant 3 utilisateurs sur mon instance Nextcloud, j’ai répété ces opérations 3 fois.
Conclusion
Quand on a des sauvegardes, rien n’est perdu, on peut toujours bidouiller pour arriver à nos fins ! Cela montre néanmoins l’intérêt et l’importance des sauvegardes.
Mais on peut quand même se dire que la procédure à suivre pour restaurer quelques dates est quand même compliquée pour une si petite option oubliée (le -t
de rsync). L’effet papillon dans un bel exemple !