Dès qu'on branche la clé déclarée (reconnue par son UUID), udev demande à systemd de lancer une sauvegarde rsync des dossiers choisis. Ce qui a disparu de l'ordinateur est retiré de la clé, mais conservé 30 jours dans une corbeille datée sur la clé. Notifications de bureau, journal systemd, garde-fous contre une destination erronée. Installateur, tests sans sudo et mode d'emploi fournis. Refs #1
208 lines
8.7 KiB
Bash
Executable file
208 lines
8.7 KiB
Bash
Executable file
#!/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 <<FIN
|
|
Clé de sauvegarde : UUID $UUID_CHOISI
|
|
Utilisateur : $UTILISATEUR_CHOISI
|
|
|
|
1. Pour tester sans rien modifier : sudo sauvegarde-cle-usb --simulation
|
|
2. Débranchez puis rebranchez la clé : la sauvegarde démarre toute seule.
|
|
Attendez la notification « Sauvegarde terminée » avant de la retirer.
|
|
3. Journal : journalctl -u sauvegarde-cle-usb
|
|
|
|
Réglages (dossiers, exclusions, corbeille) : sudo xed $CONF_CIBLE
|
|
FIN
|