#!/usr/bin/env bash # ============================================================================= # installer.sh — installe (ou désinstalle) la sauvegarde automatique sur clé # ----------------------------------------------------------------------------- # Utilisation, depuis ce dossier : # sudo ./installer.sh installation (questions posées) # sudo ./installer.sh --uuid E234-70AF --utilisateur marie # installation sans questions # sudo ./installer.sh --desinstaller tout retirer (la clé n'est pas touchée) # # On peut le relancer autant de fois que l'on veut (changer de clé, mettre # à jour le script) : les réglages personnels de la configuration existante # sont conservés, seuls l'UUID et l'utilisateur sont mis à jour. # ============================================================================= set -euo pipefail export LC_ALL=C.UTF-8 ICI="$(cd "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)" SCRIPT_CIBLE="/usr/local/sbin/sauvegarde-cle-usb" SERVICE_CIBLE="/etc/systemd/system/sauvegarde-cle-usb.service" REGLE_CIBLE="/etc/udev/rules.d/99-sauvegarde-cle-usb.rules" CONF_CIBLE="/etc/sauvegarde-cle-usb.conf" UUID_CHOISI="" UTILISATEUR_CHOISI="" ACTION="installer" erreur() { printf 'ERREUR : %s\n' "$*" >&2; exit 1; } titre() { printf '\n== %s ==\n' "$*"; } aide() { sed -n '4,13p' "${BASH_SOURCE[0]}" | sed 's/^# \{0,1\}//' } while [[ $# -gt 0 ]]; do case "$1" in --desinstaller|--désinstaller) ACTION="desinstaller" ;; --uuid) UUID_CHOISI="${2:-}"; shift ;; --utilisateur) UTILISATEUR_CHOISI="${2:-}"; shift ;; --aide|--help|-h) aide; exit 0 ;; *) aide >&2; erreur "option inconnue : $1" ;; esac shift done [[ "$(id -u)" -eq 0 ]] || erreur "lancez ce programme avec sudo : sudo $0" recharger() { systemctl daemon-reload udevadm control --reload-rules } # ----------------------------------------------------------------------------- # Désinstallation # ----------------------------------------------------------------------------- if [[ "$ACTION" == "desinstaller" ]]; then titre "Désinstallation" systemctl stop sauvegarde-cle-usb.service 2>/dev/null || true for f in "$REGLE_CIBLE" "$SERVICE_CIBLE" "$SCRIPT_CIBLE" "$CONF_CIBLE"; do if [[ -e "$f" ]]; then rm -f -- "$f" echo "Supprimé : $f" fi done recharger echo echo "La sauvegarde automatique est désinstallée." echo "Les copies déjà présentes sur la clé n'ont pas été touchées." exit 0 fi # ----------------------------------------------------------------------------- # Vérifications préalables # ----------------------------------------------------------------------------- for f in sauvegarde-cle-usb sauvegarde-cle-usb.conf sauvegarde-cle-usb.service 99-sauvegarde-cle-usb.rules.modele; do [[ -f "$ICI/$f" ]] || erreur "fichier manquant à côté de installer.sh : $f" done command -v rsync >/dev/null || erreur "rsync n'est pas installé : sudo apt install rsync" command -v notify-send >/dev/null || echo "Remarque : notify-send absent (sudo apt install libnotify-bin) : pas de notifications." # ----------------------------------------------------------------------------- # Choix de la clé # ----------------------------------------------------------------------------- # Une partition est candidate si elle a un UUID et si elle est (directement ou # non, ex. clé chiffrée déverrouillée) sur un périphérique USB. lister_candidats() { local nom type uuid fstype while read -r nom type uuid fstype; do [[ -n "$uuid" && -n "$fstype" ]] || continue case "$type" in part|disk|crypt) ;; *) continue ;; esac lsblk -nso TRAN "$nom" 2>/dev/null | grep -qx usb || continue printf '%s %s %s\n' "$nom" "$uuid" "$fstype" done < <(lsblk -rnpo NAME,TYPE,UUID,FSTYPE) } if [[ -z "$UUID_CHOISI" ]]; then titre "Choix de la clé de sauvegarde" echo "Branchez la clé à utiliser (et, si elle est chiffrée, déverrouillez-la" echo "dans le gestionnaire de fichiers), puis appuyez sur Entrée." read -r _ mapfile -t CANDIDATS < <(lister_candidats) [[ "${#CANDIDATS[@]}" -gt 0 ]] || erreur "aucune clé USB trouvée. Est-elle bien branchée ?" echo "Clés USB trouvées :" echo i=0 for c in "${CANDIDATS[@]}"; do i=$((i + 1)) read -r nom _ _ <<<"$c" printf ' [%d] ' "$i" lsblk -dno NAME,LABEL,UUID,FSTYPE,SIZE "$nom" | head -n1 done echo echo "(Colonnes : nom, étiquette, UUID, système de fichiers, taille)" echo "Pour comparer : lsblk -o NAME,LABEL,UUID,FSTYPE,SIZE,TRAN" read -r -p "Numéro de la clé de sauvegarde : " num [[ "$num" =~ ^[0-9]+$ && "$num" -ge 1 && "$num" -le "${#CANDIDATS[@]}" ]] || erreur "choix invalide." read -r _ UUID_CHOISI fstype <<<"${CANDIDATS[$((num - 1))]}" else periph="$(blkid -U "$UUID_CHOISI" 2>/dev/null || true)" if [[ -n "$periph" ]]; then fstype="$(blkid -o value -s TYPE "$periph" 2>/dev/null || true)" else fstype="" echo "Attention : aucune partition d'UUID $UUID_CHOISI n'est branchée actuellement." fi fi [[ "$UUID_CHOISI" =~ ^[A-Za-z0-9-]+$ ]] || erreur "UUID invalide : $UUID_CHOISI" periph="$(blkid -U "$UUID_CHOISI" 2>/dev/null || true)" if [[ -n "$periph" && "$(lsblk -dno TYPE "$periph" 2>/dev/null)" == "crypt" ]]; then echo "Clé chiffrée : le démarrage automatique n'est pas garanti après le" echo "déverrouillage. Lancez alors la sauvegarde avec :" echo " sudo systemctl start sauvegarde-cle-usb" fi case "${fstype:-}" in crypto_LUKS) erreur "c'est l'enveloppe chiffrée de la clé. Déverrouillez-la dans le gestionnaire de fichiers, relancez l'installateur et choisissez la ligne « crypt » qui apparaît." ;; ext4|ext3|ext2|btrfs|xfs) echo "Clé au format Linux ($fstype) : droits et propriétaires seront conservés." ;; vfat) echo "Clé au format FAT32 : ni droits ni liens symboliques, fichiers de 4 Go maximum." ;; exfat|ntfs) echo "Clé au format $fstype : ni droits ni propriétaires (suffisant pour des documents)." ;; "") ;; *) echo "Format $fstype : non testé, copie prudente sans droits." ;; esac # ----------------------------------------------------------------------------- # Choix de l'utilisateur # ----------------------------------------------------------------------------- if [[ -z "$UTILISATEUR_CHOISI" ]]; then defaut="${SUDO_USER:-}" [[ "$defaut" == "root" ]] && defaut="" read -r -p "Utilisateur dont on sauvegarde le dossier personnel [${defaut}] : " UTILISATEUR_CHOISI UTILISATEUR_CHOISI="${UTILISATEUR_CHOISI:-$defaut}" fi [[ -n "$UTILISATEUR_CHOISI" ]] || erreur "aucun utilisateur indiqué." [[ "$UTILISATEUR_CHOISI" =~ ^[a-z_][a-z0-9_.-]*$ ]] || erreur "nom d'utilisateur invalide : $UTILISATEUR_CHOISI" id -u "$UTILISATEUR_CHOISI" >/dev/null 2>&1 || erreur "utilisateur inconnu : $UTILISATEUR_CHOISI" DOSSIER_PERSO="$(getent passwd "$UTILISATEUR_CHOISI" | cut -d: -f6)" # ----------------------------------------------------------------------------- # Installation des fichiers # ----------------------------------------------------------------------------- titre "Installation" install -o root -g root -m 755 "$ICI/sauvegarde-cle-usb" "$SCRIPT_CIBLE" echo "Script : $SCRIPT_CIBLE" install -o root -g root -m 644 "$ICI/sauvegarde-cle-usb.service" "$SERVICE_CIBLE" echo "Service : $SERVICE_CIBLE" if [[ -f "$CONF_CIBLE" ]]; then # Configuration existante : on garde les réglages, on met à jour la clé. sed -i -e "s|^UUID=.*|UUID=\"$UUID_CHOISI\"|" \ -e "s|^UTILISATEUR=.*|UTILISATEUR=\"$UTILISATEUR_CHOISI\"|" "$CONF_CIBLE" echo "Réglages : $CONF_CIBLE (conservés, clé et utilisateur mis à jour)" echo " vérifiez la liste SOURCES si l'utilisateur a changé." else sed -e "s|^UUID=.*|UUID=\"$UUID_CHOISI\"|" \ -e "s|^UTILISATEUR=.*|UTILISATEUR=\"$UTILISATEUR_CHOISI\"|" \ -e "s|/home/marie|$DOSSIER_PERSO|g" \ "$ICI/sauvegarde-cle-usb.conf" > "$CONF_CIBLE" echo "Réglages : $CONF_CIBLE" fi chown root:root "$CONF_CIBLE" chmod 644 "$CONF_CIBLE" sed "s|@UUID@|$UUID_CHOISI|" "$ICI/99-sauvegarde-cle-usb.rules.modele" > "$REGLE_CIBLE" chmod 644 "$REGLE_CIBLE" echo "Règle udev : $REGLE_CIBLE" recharger titre "C'est prêt" cat <