Ajouter termsynctools.sh

This commit is contained in:
2025-08-14 20:19:59 +00:00
parent 8a17d19601
commit 24b59bc9dd

685
termsynctools.sh Normal file
View File

@@ -0,0 +1,685 @@
#!/data/data/com.termux/files/usr/bin/bash
#********************************************#
# #
# TermSyncTools v0.2.8 #
# A CLI tool to backup and restore termux #
# https://github.com/tuxgyver/termuxsynctools #
# By Johnny et Noe Fontaine #
# #
#********************************************#
# Variables
readonly SOURCE="$HOME"
readonly DEST="$HOME/storage/shared/Termux/Backup"
readonly PKGS_SRC="$PREFIX/var/log/apt/history.log"
readonly GDRIVE_REMOTE="Gdrive:/Termux/Backup"
readonly VERSION="0.2.8"
readonly TEMP_DIR="/data/data/com.termux/files/usr/tmp"
readonly program_name=$(basename "$0")
readonly PROOT_SRC="$PREFIX/var/lib/proot-distro/installed-rootfs"
# Colors
B='\e[1;34m' # blue
R='\e[1;31m' # red
G='\e[1;32m' # green
W='\e[1;37m' # white bold
Y='\e[1;33m' # yellow
off='\e[0m' # reset color
t=' ' # tab
OK=" $W[$G$W]$off"
EXC=" $W[$Y$W]$off"
ERR=" $W[$R$W]$off"
# Initialize environment
function init_environment() {
# Vérifier/créer le répertoire temporaire
if [[ ! -d "${TEMP_DIR}" ]]; then
mkdir -p "${TEMP_DIR}"
chmod 700 "${TEMP_DIR}"
fi
# Vérifier/créer le répertoire de destination
if [[ ! -d "${DEST}" ]]; then
mkdir -p "${DEST}"
fi
# Vérifier les permissions de stockage
while ! [ -w /storage/emulated/0/ ]; do
printf "${ERR} Autorisez l'accès au stockage${off}\n"
termux-setup-storage
sleep 2
done
}
# Banner
function display_banner() {
figlet "TermSyncTools" | lolcat -i
printf "\n\n"
}
# Help
function show_help() {
printf "${W}Usage: ${G}${program_name}${off} [-hvq] [-b|-r [home|pkgs|proot]] [-d] [-s] [-a]\n"
printf "${W}-h${off} ${G}affiche cette aide${off}\n"
printf "${W}-v${off} ${G}affiche la version${off}\n"
printf "${W}-b [home|pkgs|proot]${off} ${G}sauvegarde home, packages ou proot-distrib${off}\n"
printf "${W}-r [home|pkgs|proot]${off} ${G}restaure home, packages ou proot-distrib${off}\n"
printf "${W}-d${off} ${G}supprime les backups${off}\n"
printf "${W}-s${off} ${G}sauvegarde automatique${off}\n"
printf "${W}-a${off} ${G}supprime la programmation de la sauvegarde automatique${off}\n"
printf "${W}-q${off} ${G}quitte pendant la restauration${off}\n"
printf "By Fontaine ${B}Johnny${off} & ${G}Noe${off} \n"
}
# Version
function show_version() {
printf "TermSyncTools version ${VERSION}\n"
printf "Outil de sauvegarde et restauration pour Termux\n"
printf "https://github.com/Noewolf5449/termux-sync\n"
printf "By Fontaine ${B}Johnny${off} & ${G}Noe${off} \n"
}
# Error handling
function error() {
printf "${ERR} ${R}Erreur:${off} $*\n" >&2
}
# Success message
function success() {
printf "${OK} $*\n"
}
# Info message
function info() {
printf "${EXC} $*\n"
}
# Check Internet
function check_internet() {
if ping -q -w 1 -c 1 8.8.8.8 &> /dev/null; then
return 0
fi
return 1
}
# Google Drive sync
function sync_with_gdrive() {
local direction=$1
local file=$2
info "Synchronisation avec Google Drive..."
if ! rclone listremotes | grep -q "Gdrive:"; then
error "Google Drive non configuré. Exécutez 'rclone config'"
return 1
fi
case "$direction" in
"up")
if [[ -n "$file" && -f "${DEST}/${file}" ]]; then
if rclone copy "${DEST}/${file}" "${GDRIVE_REMOTE}" --progress; then
success "Synchronisation terminée"
return 0
fi
fi
;;
"down")
if rclone sync "${GDRIVE_REMOTE}" "${DEST}" --progress; then
success "Synchronisation terminée"
return 0
fi
;;
*)
error "Direction de synchronisation invalide"
return 1
;;
esac
error "Échec de la synchronisation"
return 1
}
# Backup home
function backup_home() {
info "Sauvegarde du home"
printf "${t}Veuillez patienter...\n"
local temp_file="${TEMP_DIR}/${backup_name}_home.tmp"
local backup_file="${DEST}/${backup_name}_home.bak"
# Liste des exclusions
local exclude_dirs=(
".cache"
"storage"
"*/node_modules"
"*/venv"
"${TEMP_DIR}"
"${DEST}"
)
local exclude_args=""
for dir in "${exclude_dirs[@]}"; do
exclude_args+="--exclude='${dir}' "
done
# Sauvegarde
if eval tar -I pigz -cf "${temp_file}" -C "${SOURCE}" ${exclude_args} . ; then
mv "${temp_file}" "${backup_file}"
success "Home sauvegardé dans: ${backup_file}"
sync_with_gdrive "up" "${backup_name}_home.bak"
return 0
else
rm -f "${temp_file}"
error "Échec de la sauvegarde du home"
return 1
fi
}
# Backup packages
function backup_pkgs() {
info "Sauvegarde des packages"
printf "${t}Veuillez patienter...\n"
local pkg_file="${DEST}/${backup_name}_pkgs.bak"
# Liste des packages installés
if dpkg --get-selections | grep -v deinstall | cut -f1 > "${pkg_file}"; then
success "Packages sauvegardés dans: ${pkg_file}"
sync_with_gdrive "up" "${backup_name}_pkgs.bak"
return 0
else
error "Échec de la sauvegarde des packages"
return 1
fi
}
# Backup proot-distrib
function backup_proot() {
info "Sauvegarde de proot-distrib"
printf "${t}Veuillez patienter...\n"
local proot_file="${DEST}/${backup_name}_proot.bak"
# Sauvegarde de proot-distrib
if tar -I pigz -cf "${proot_file}" -C "${PROOT_SRC}" . ; then
success "proot-distrib sauvegardé dans: ${proot_file}"
sync_with_gdrive "up" "${backup_name}_proot.bak"
return 0
else
error "Échec de la sauvegarde de proot-distrib"
return 1
fi
}
# Restore home
function restore_home() {
info "Restauration du home"
printf "${t}Veuillez patienter...\n"
# Synchronisation avec Google Drive
sync_with_gdrive "down"
# Vérifie les sauvegardes disponibles
local backups=($(ls -1 ${DEST}/*_home.bak 2>/dev/null))
if [ ${#backups[@]} -eq 0 ]; then
error "Aucune sauvegarde disponible"
return 1
fi
# Liste les sauvegardes
printf "\n${t}Sauvegardes disponibles:\n"
for i in "${!backups[@]}"; do
printf "${t}$((i+1)). ${backups[$i]##*/}\n"
done
printf "\n"
# Sélection de la sauvegarde
local backup_number
read -p "Numéro de la sauvegarde à restaurer (ou 'q' pour quitter): " backup_number
if [[ "$backup_number" == "q" ]]; then
info "Quitter la restauration"
return 0
fi
if ! [[ "$backup_number" =~ ^[0-9]+$ ]] || \
[ "$backup_number" -lt 1 ] || \
[ "$backup_number" -gt ${#backups[@]} ]; then
error "Sélection invalide"
return 1
fi
local selected_backup="${backups[$((backup_number-1))]}"
local safety_backup="${TEMP_DIR}/home_backup_before_restore_$(date +%Y%m%d_%H%M%S).bak"
# Crée une sauvegarde de sécurité
info "Création d'une sauvegarde de sécurité..."
if ! tar -I pigz -cf "${safety_backup}" -C "${SOURCE}" . ; then
error "Impossible de créer la sauvegarde de sécurité"
return 1
fi
# Restaure la sauvegarde
info "Restauration en cours..."
if tar -I pigz -xf "${selected_backup}" -C "${SOURCE}"; then
success "Home restauré avec succès"
printf "${t}Redémarrez votre session pour appliquer les changements\n"
rm -f "${safety_backup}"
return 0
else
error "Échec de la restauration"
info "Restauration de la sauvegarde de sécurité..."
tar -I pigz -xf "${safety_backup}" -C "${SOURCE}"
rm -f "${safety_backup}"
return 1
fi
}
# Restore packages
function restore_pkgs() {
if ! check_internet; then
error "Pas de connexion internet"
return 1
fi
info "Restauration des packages"
printf "${t}Veuillez patienter...\n"
# Synchronisation avec Google Drive
sync_with_gdrive "down"
# Vérifie les sauvegardes disponibles
local backups=($(ls -1 ${DEST}/*_pkgs.bak 2>/dev/null))
if [ ${#backups[@]} -eq 0 ]; then
error "Aucune sauvegarde disponible"
return 1
fi
# Liste les sauvegardes
printf "\n${t}Sauvegardes disponibles:\n"
for i in "${!backups[@]}"; do
printf "${t}$((i+1)). ${backups[$i]##*/}\n"
done
printf "\n"
# Sélection de la sauvegarde
local backup_number
read -p "Numéro de la sauvegarde à restaurer (ou 'q' pour quitter): " backup_number
if [[ "$backup_number" == "q" ]]; then
info "Quitter la restauration"
return 0
fi
if ! [[ "$backup_number" =~ ^[0-9]+$ ]] || \
[ "$backup_number" -lt 1 ] || \
[ "$backup_number" -gt ${#backups[@]} ]; then
error "Sélection invalide"
return 1
fi
local selected_backup="${backups[$((backup_number-1))]}"
# Mise à jour et installation des packages
if apt-get update && apt-get install -y $(cat "${selected_backup}"); then
success "Packages restaurés"
printf "${t}Redémarrez votre session pour appliquer les changements\n"
return 0
else
error "Échec de la restauration des packages"
return 1
fi
}
# Restore proot-distrib
function restore_proot() {
info "Restauration de proot-distrib"
printf "${t}Veuillez patienter...\n"
# Synchronisation avec Google Drive
sync_with_gdrive "down"
# Vérifie les sauvegardes disponibles
local backups=($(ls -1 ${DEST}/*_proot.bak 2>/dev/null))
if [ ${#backups[@]} -eq 0 ]; then
error "Aucune sauvegarde disponible"
return 1
fi
# Liste les sauvegardes
printf "\n${t}Sauvegardes disponibles:\n"
for i in "${!backups[@]}"; do
printf "${t}$((i+1)). ${backups[$i]##*/}\n"
done
printf "\n"
# Sélection de la sauvegarde
local backup_number
read -p "Numéro de la sauvegarde à restaurer (ou 'q' pour quitter): " backup_number
if [[ "$backup_number" == "q" ]]; then
info "Quitter la restauration"
return 0
fi
if ! [[ "$backup_number" =~ ^[0-9]+$ ]] || \
[ "$backup_number" -lt 1 ] || \
[ "$backup_number" -gt ${#backups[@]} ]; then
error "Sélection invalide"
return 1
fi
local selected_backup="${backups[$((backup_number-1))]}"
local safety_backup="${TEMP_DIR}/proot_backup_before_restore_$(date +%Y%m%d_%H%M%S).bak"
# Crée une sauvegarde de sécurité
info "Création d'une sauvegarde de sécurité..."
if ! tar -I pigz -cf "${safety_backup}" -C "${PROOT_SRC}" . ; then
error "Impossible de créer la sauvegarde de sécurité"
return 1
fi
# Restaure la sauvegarde
info "Restauration en cours..."
if tar -I pigz -xf "${selected_backup}" -C "${PROOT_SRC}"; then
success "proot-distrib restauré avec succès"
printf "${t}Redémarrez votre session pour appliquer les changements\n"
rm -f "${safety_backup}"
return 0
else
error "Échec de la restauration"
info "Restauration de la sauvegarde de sécurité..."
tar -I pigz -xf "${safety_backup}" -C "${PROOT_SRC}"
rm -f "${safety_backup}"
return 1
fi
}
# Backup function
function backup() {
local type=$1
# Demande le nom de la sauvegarde
read -p "Nom de la sauvegarde (vide pour nom par défaut): " backup_name
if [[ -z "$backup_name" ]]; then
backup_name="backup_$(date +%Y%m%d_%H%M%S)"
fi
case "$type" in
"home")
backup_home
;;
"pkgs")
backup_pkgs
;;
"proot")
backup_proot
;;
"")
backup_home && backup_pkgs && backup_proot
;;
*)
error "Type de sauvegarde invalide"
show_help
return 1
;;
esac
}
# Restore function
function restore() {
local type=$1
case "$type" in
"home")
restore_home
;;
"pkgs")
restore_pkgs
;;
"proot")
restore_proot
;;
"")
restore_home && restore_pkgs && restore_proot
;;
*)
error "Type de restauration invalide"
show_help
return 1
;;
esac
}
# Delete backups
function delete_backups() {
info "Suppression des backups"
printf "${t}Veuillez patienter...\n"
# Synchronisation avec Google Drive
sync_with_gdrive "down"
# Vérifie les sauvegardes disponibles
local backups=($(ls -1 ${DEST}/*.bak 2>/dev/null))
if [ ${#backups[@]} -eq 0 ]; then
error "Aucune sauvegarde disponible"
return 1
fi
# Liste les sauvegardes
printf "\n${t}Sauvegardes disponibles:\n"
for i in "${!backups[@]}"; do
printf "${t}$((i+1)). ${backups[$i]##*/}\n"
done
printf "\n"
# Sélection de la sauvegarde à supprimer
local backup_number
read -p "Numéro de la sauvegarde à supprimer: " backup_number
if ! [[ "$backup_number" =~ ^[0-9]+$ ]] || \
[ "$backup_number" -lt 1 ] || \
[ "$backup_number" -gt ${#backups[@]} ]; then
error "Sélection invalide"
return 1
fi
local selected_backup="${backups[$((backup_number-1))]}"
local backup_name="${selected_backup##*/}"
# Suppression locale
if rm -f "${selected_backup}"; then
success "Backup local supprimé: ${backup_name}"
else
error "Échec de la suppression du backup local: ${backup_name}"
return 1
fi
# Suppression distante
if rclone delete "${GDRIVE_REMOTE}/${backup_name}"; then
success "Backup distant supprimé: ${backup_name}"
else
error "Échec de la suppression du backup distant: ${backup_name}"
return 1
fi
# Affiche la liste des backups restants
local remaining_backups=($(ls -1 ${DEST}/*.bak 2>/dev/null))
if [ ${#remaining_backups[@]} -eq 0 ]; then
info "Aucune sauvegarde restante"
else
printf "\n${t}Sauvegardes restantes:\n"
for i in "${!remaining_backups[@]}"; do
printf "${t}$((i+1)). ${remaining_backups[$i]##*/}\n"
done
printf "\n"
fi
return 0
}
# Auto backup
function auto_backup() {
info "Configuration de la sauvegarde automatique"
printf "${t}Veuillez patienter...\n"
local cron_job="0 7 * * * /data/data/com.termux/files/usr/bin/bash termsynctools -b"
if (crontab -l 2>/dev/null; echo "$cron_job" ) | crontab -; then
success "Sauvegarde automatique configurée"
return 0
else
error "Échec de la configuration de la sauvegarde automatique"
return 1
fi
}
# Delete auto backup
function delete_auto_backup() {
info "Suppression de la sauvegarde automatique"
printf "${t}Veuillez patienter...\n"
local cron_job="0 7 * * * /data/data/com.termux/files/usr/bin/bash termsynctools -b"
local temp_crontab=$(mktemp)
# Lire le fichier crontab actuel
crontab -l > "$temp_crontab"
# Supprimer la ligne spécifique de la tâche cron
grep -vF "$cron_job" "$temp_crontab" > "$temp_crontab.tmp" && mv "$temp_crontab.tmp" "$temp_crontab"
# Écrire le fichier crontab mis à jour
crontab "$temp_crontab"
# Supprimer le fichier temporaire
rm -f "$temp_crontab"
success "Sauvegarde automatique supprimée"
return 0
}
# Install dependencies
function install_dependencies() {
if check_internet; then
info "Installation des dépendances..."
if apt-get update && \
apt-get install -y tar pigz rclone figlet lolcat cronie; then
success "Dépendances installées"
return 0
fi
else
error "Pas de connexion internet"
fi
return 1
}
# Configure rclone
function configure_rclone() {
if ! rclone listremotes | grep -q "Gdrive:"; then
info "Configuration de rclone avec Google Drive..."
rclone config
else
success "rclone déjà configuré avec Google Drive"
fi
}
# Get optional arguments
function getopts_get_optional_argument() {
eval next_token=\${$OPTIND}
if [[ -n $next_token && $next_token != -* ]]; then
OPTIND=$((OPTIND + 1))
OPTARG=$next_token
else
OPTARG=""
fi
}
# Cleanup function
function cleanup() {
rm -f "${TEMP_DIR}/${backup_name}_home.tmp" "${TEMP_DIR}/${backup_name}_pkgs.tmp"
error "Programme terminé de manière inattendue"
exit 1
}
# Main
function main() {
# Trap signals
trap cleanup 1 2 3 15 20
# Initialize environment
init_environment
# Check and install dependencies
if ! [[ $(type -P tar) && $(type -P pigz) && \
$(type -P rclone) && $(type -P figlet) && \
$(type -P lolcat) && $(type -P crontab) ]]; then
install_dependencies
fi
# Configure rclone
configure_rclone
# Display banner
display_banner
# Parse arguments
local OPTIND
while getopts ":hvbrdqsa" opt; do
case $opt in
h)
show_help
return 0
;;
v)
show_version
return 0
;;
b)
getopts_get_optional_argument "$@"
backup "${OPTARG}"
return $?
;;
r)
getopts_get_optional_argument "$@"
restore "${OPTARG}"
return $?
;;
d)
delete_backups
return $?
;;
s)
auto_backup
return $?
;;
a)
delete_auto_backup
return $?
;;
q)
info "Quitter la restauration"
return 0
;;
\?)
error "Option invalide"
return 1
;;
:)
error "Option nécessitant un argument"
show_help
return 1
;;
esac
done
if [[ $OPTIND -eq 1 ]]; then
error "Aucune option fournie"
printf "Utilisez '${program_name} -h' pour l'aide\n"
return 1
fi
}
main "$@"
exit $?