7.3 KiB
Export système pour revue
scripts/backup.sh produit un candidat privé hors du dépôt. La commande
sans argument ne met plus à jour pkglist/, inventory/, rootfs/ ni
templates/ suivis par Git. Elle ne sauvegarde ni données personnelles,
dotfiles, clés Secure Boot, connexions réseau, secrets, ni fichiers Trainlog.
La zone locale d’export n’est pas une preuve de sauvegarde hors disque ou de
restauration possible. Ce code n’a été testé ici que sur des fixtures.
Interface et destination
backup.sh [--output-dir REPERTOIRE_PARENT]
backup.sh --dry-run [--output-dir REPERTOIRE_PARENT]
backup.sh --help
--output-dir désigne un parent : chaque invocation crée un sous-répertoire
unique. Par défaut, le parent est
${XDG_STATE_HOME:-$HOME/.local/state}/arch-system/exports. Un
XDG_STATE_HOME relatif est ignoré avec diagnostic, selon la
spécification XDG ;
le chemin par défaut sous HOME est alors employé. Un parent explicite
relatif est résolu depuis le répertoire courant. Les chemins sont normalisés ;
la destination égale au dépôt ou située dedans, les alias vers celui-ci et les
parents traversant un lien symbolique sont refusés. Un parent final existant
doit appartenir à l’utilisateur et ne pas être ouvert au groupe ou aux autres.
Les nouveaux répertoires sont créés privés, sans chmod/chown des ancêtres.
Un parent contenant des espaces ou un antislash littéral reste accepté ; le
calcul des empreintes ne dépend pas de la représentation de son nom.
--dry-run affiche les sources, les catégories obligatoire/facultatif, le
parent et les transformations ; il ne crée rien et ne lance ni sudo, ni
collecteur, ni demande de mot de passe. Il ne prouve pas la réussite des
lectures futures. La collecte refuse une invocation en root ; les fichiers de
sortie sont écrits par l’utilisateur sous umask 077. Les lectures privilégiées
utilisent sudo -n, un contrôle d’état strict et seulement les sources
explicitement autorisées. Aucun résultat n’est installé avec sudo.
Collecteurs et états
| Classe | Collecteurs | Raison |
|---|---|---|
| Obligatoire | pacman -Qqen, -Qqem ; unités système activées, en cours et timers ; lsblk, findmnt, /etc/fstab, Btrfs subvolumes/usage, mémoire et swap ; pacman.conf, makepkg.conf, mkinitcpio.conf |
Sans ces éléments, le candidat annoncé manquerait son noyau d’inventaire et de configuration. |
| Facultatif | pacman -Qdtq ; unités en échec et unités utilisateur ; scrub Btrfs ; SMART de /dev/nvme0 ; nftables.conf, limine-snapper-sync, TLP, zram-generator, Snapper, deux helpers root ; modèle Limine |
Leur absence ou indisponibilité peut être légitime selon la machine, l’utilisateur ou le matériel. Elle reste visible dans le manifeste. |
SUCCESS indique un fichier collecté non vide ; EMPTY, une commande
réussie avec résultat vide permis ; ABSENT, une absence effectivement
établie pour une source facultative ; UNAVAILABLE, un outil ou nvme0
indisponible ; CHECK_ERROR, un contrôle impossible ou une réponse
invalide ; COLLECT_ERROR, une commande ou lecture échouée.
PORTABILITY_REVIEW marque le modèle Limine à relire, même après une
transformation reconnue. Une erreur obligatoire interdit la finalisation ;
une erreur facultative produit COMPLETE_WITH_WARNINGS si le noyau
obligatoire a réussi. COMPLETE est réservé à un ensemble sans avertissement.
En pratique, un modèle Limine présent entraîne une alerte de portabilité.
Les listes sont des observations : « natif » ne prouve pas dans tous les
cas « dépôt officiel », et « étranger » ne prouve pas « AUR ».
pacman -Qdtq désigne les dépendances orphelines selon
pacman(8). La documentation
primaire ne justifie pas une règle générale « code 1 = aucun orphelin » :
une sortie vide avec code non nul reste COLLECT_ERROR, avec une cause à
examiner. Les résultats vides de commandes revenues avec succès sont
distingués. Le relevé SMART éventuel concerne seulement /dev/nvme0,
pas tous les disques.
Finalisation, manifeste et limites
La collecte commence dans un répertoire .incomplete.* privé, doté d’un
manifest.tsv au statut INCOMPLETE. Les sorties sont d’abord reçues dans
une zone de travail privée ; une commande qui écrit partiellement puis échoue
ne publie pas ce fichier comme relevé valide. Après les éléments obligatoires,
le manifeste est terminé et le répertoire est renommé localement en
export-* sans remplacer un nom existant. Chaque invocation a son espace ;
avant un renommage réussi, une erreur ou un INT/TERM conserve son reliquat
marqué INCOMPLETE et annoncé. Après le renommage réussi, un INT/TERM
conserve le candidat complet et annonce son chemin avec le diagnostic
« finalisation acquise, terminaison interrompue ». L'exporteur reconnaît ce
renommage par la disparition du staging et l'identité de l'objet au chemin
final ; la simple présence d'une destination préexistante ne suffit pas.
Une collision conserve le staging incomplet sans revendiquer cet autre export.
Les exports antérieurs ne sont ni supprimés ni remplacés. Les codes sont 0 pour
simulation ou candidat finalisé, 1 pour erreur, 2 pour usage invalide,
130/143 pour INT/TERM. SIGKILL et une coupure d’alimentation
ne sont pas interceptés ; aucune garantie de durabilité après coupure n’est
revendiquée.
Le manifeste contient version, début/fin UTC, révision source, statut global, état de chaque collecteur et SHA-256 des fichiers de sortie finalisés. Chaque empreinte est calculée via l'entrée standard, après vérification de l'ouverture du fichier et du succès de la commande ; seule une réponse de 64 chiffres hexadécimaux est acceptée. Un échec ou une réponse malformée interdit la finalisation. Le manifeste ne contient pas son propre hash. Vérifier les empreintes et lire le contenu avant toute utilisation. Les lectures ne forment pas un instantané atomique : services et fichiers peuvent changer pendant la collecte. Les vérifications de chemins réduisent les risques d’alias et de liens ; elles ne remplacent pas une exclusion des modifications concurrentes de la machine.
Le modèle Limine candidat est produit uniquement dans l’export. La section
commençant par ### Auto-generated by limine-snapper-sync est retirée.
Les formes root=UUID=<hexadécimal/tirets> et
root=PARTUUID=<hexadécimal/tirets> deviennent des placeholders distincts.
Une forme root= non reconnue est signalée ; tous les autres champs
demeurent soumis à revue. Ni ESP_PATH, ni signatures, ni snapshots ne sont
changés. Le modèle n’est pas déclaré universellement portable.
Revue avant toute promotion manuelle
Examiner les fichiers et le manifeste hors du dépôt, particulièrement
identifiants de stockage, noms de services, nftables.conf, fstab et
Limine. Aucun filtrage simple ne certifie l’absence de secrets ; ne pas
publier automatiquement. Les listes de déploiement et la politique réseau
restent des décisions de reconstruction distinctes de l’état observé.
Une éventuelle reprise manuelle dans Git demande une revue spécifique des
contenus et de leur portée. L’existence du candidat n’apporte ni copie
externe, ni restauration testée.