Comment supprimer tous les instantanés ZFS sauf [n]?

25

Je photographie actuellement mon NAS basé sur ZFS tous les soirs et toutes les semaines, un processus qui m'a sauvé le cul plusieurs fois. Cependant, bien que la création de l'instantané soit automatique (à partir de cron), la suppression des anciens instantanés reste une tâche manuelle. Évidemment, il y a un risque que si je suis frappé par un bus ou que la tâche manuelle ne soit pas effectuée, le NAS manquera d'espace disque.

Quelqu'un a-t-il de bons moyens / scripts pour gérer le nombre d'instantanés stockés sur ses systèmes ZFS? Idéalement, je voudrais un script qui itère à travers tous les instantanés pour un système de fichiers ZFS donné et supprime tous, sauf les n derniers instantanés pour ce système de fichiers.

Par exemple, j'ai deux systèmes de fichiers, l'un appelé tanket l'autre appelé sastank. Les instantanés sont nommés avec la date à laquelle ils ont été créés: sastank@AutoD-2011-12-13une simple sortcommande doit donc les répertorier dans l'ordre. Je cherche à garder la valeur des instantanés quotidiens des 2 dernières semaines tank, mais seulement les deux derniers jours des instantanés sastank.

grandir
la source

Réponses:

35

Vous pouvez trouver quelque chose comme ça un peu plus simple

zfs list -t snapshot -o name | grep ^tank@Auto | tac | tail -n +16 | xargs -n 1 zfs destroy -r
  • afficher la liste des instantanés (noms uniquement) avec zfs list -t snaphot -o name
  • filtre pour ne garder que ceux qui correspondent tank@Autoàgrep ^tank@Auto
  • inverser la liste (précédemment triée du plus ancien au plus récent) avec tac
  • limiter la sortie au 16e résultat le plus ancien et suivre avec tail -n +16
  • puis détruisez avec xargs -n 1 zfs destroy -vr

la suppression d'instantanés dans l'ordre inverse est censée être plus efficace.

ou trier dans l'ordre inverse de la création

zfs list -t snapshot -o name -S creation | grep ^tank@Auto | tail -n +16 | xargs -n 1 zfs destroy -vr

Testez-le avec ...|xargs -n 1 echo

dnozay
la source
1
Je pense que cela nécessite un sort -ravant la sedcommande. sedsemble afficher le bas de la liste au-delà des 15 premières lignes, qui dans le tri par défaut est la plus récente. Inverser la liste signifie que j'obtiens les plus anciens instantanés en bas.
growse
1
Il a déclaré que "la suppression d'instantanés dans l'ordre inverse est censée être plus efficace", d'où l'ordre de tri.
tgunr
19

Cas plus général d'obtention de l'instantané le plus récent en fonction de la date de création, et non par nom.

zfs list -H -t snapshot -o name -S creation | head -1

Portée vers un nom de système de fichiers spécifique TestOne

zfs list -H -t snapshot -o name -S creation -d1 TestOne | head -1

-H: Pas d'en-tête pour que la première ligne soit un nom d'instantané

-t snapshot: Liste des instantanés (la liste peut répertorier d'autres choses comme les pools et les volumes)

-o name: Affiche la propriété du nom de l'instantané.

-S creation: Le capital Sindique un tri décroissant , basé sur le temps de création. Cela place l'instantané le plus récent en première ligne.

-d1 TestOne: Dit inclure les enfants, ce qui semble déroutant mais c'est parce qu'en ce qui concerne cette commande, les instantanés de TestOne sont des enfants. Cela ne répertoriera PAS les instantanés des volumes dans TestOne tels que TestOne/SubVol@someSnapshot.

| head -1: Dirigez-vous vers la tête et ne renvoyez que la première ligne.

AaronLS
la source
1
Merci pour le -d1. C'était la clé de la question "Comment puis-je obtenir tous les instantanés pour un ensemble de données donné?"
Jonathon Reinhart
9

Cela ne répond pas totalement à la question elle-même, mais n'oubliez pas que vous pouvez supprimer des plages d'instantanés.

zfs destroy zpool1 / jeu de données @ 20160918% 20161107

Détruirait tous les instantanés de "20160918" à "20161107" inclus. L'une ou l'autre extrémité peut être laissée en blanc, pour signifier "la plus ancienne" ou "la plus récente". Vous pouvez donc préparer quelque chose qui calcule le "n" puis détruire "...% n" ..

Désolé de ressusciter une vieille question.

lundman
la source
1
Cela fonctionne comme un charme et 100 fois plus vite que la réponse acceptée!
NeilWang
5

growse n'a pas fonctionné sur OpenIndiana pour moi. Il ne comprenait pas -0 pour xargs.

Si vous utilisez le tri, sachez qu'il trie par ordre alphabétique, ce qui peut ne pas être souhaité car vous souhaitez probablement trouver le plus récent.

Voici le code qui supprimera tous les instantanés sauf les derniers.

Supprimez l '«écho» pour aller en direct.

RETENTION=5
FS=tank1/test
SNAPNAME=daily-

zfs list -t snapshot -o name | grep ^$FS@${SNAPNAME} |  sed -n -e :a -e '1,${RETENTION}!{P;N;D;};N;ba' | xargs -n 1 echo zfs destroy -r

Sources: http://sed.sourceforge.net/sed1line.txt

Dan Buhler
la source
2
Upvote parce que quiconque peut utiliser sed comme ça le mérite.
growse
2
Après une récente mise à jour logicielle, cette chaîne sed a cessé de fonctionner pour moi et elle a commencé à supprimer tous les instantanés! mauvais sed! Heureusement, le serveur de production était vieux et restait en sécurité. J'utilise maintenant sed -n -e: a -e '1, $ {RETENTION}! {P; N; D;}; N; ba'
Dan Buhler
Je n'ai jamais vu quelqu'un SED comme ça.
Jason
3

J'ai peut-être résolu cela avec du bash-fu.

 zfs list -t snapshot -o name | grep ^tank@AutoD- | sort -r | wc -l | xargs -n 1 expr -$NUM_TO_KEEP + | tr -d '\n' | xargs -0 -i bash -c "zfs list -t snapshot -o name | grep ^tank@AutoD- | sort -r | tail -n{} | sort |xargs -t -n 1 zfs destroy -r"

Sensationnel. Ça fait tellement mal.

grandir
la source
1

Le chemin pour la tête est nécessaire sur Solaris, mais devrait fonctionner sans le chemin sur les autres distributions.

retention=14
dataset=vmstorage-17/824

zfs list -rt snap -H -o name ${dataset} | \
/usr/gnu/bin/head -n -${retention} | xargs -n 1 zfs destroy -r
Josh Simon
la source