sync-folders.sh
Niveau : Dรฉbutant
Synchronisation de dossiers avec rsync.
Description
Ce script synchronise des dossiers : - Wrapper autour de rsync - Modes de synchronisation configurables - Prรฉvisualisation avant exรฉcution - Support SSH pour synchronisation distante
Prรฉrequis
- Systรจme : Linux (RHEL/Debian)
- Permissions : Droits de lecture sur source et รฉcriture sur destination
- Dรฉpendances :
rsync,ssh(pour synchro distante),bc,du
Cas d'Usage
- Synchronisation rรฉguliรจre : Maintien de copies synchronisรฉes de donnรฉes critiques vers backup
- Migration de serveurs : Transfert de donnรฉes entre serveurs avec vรฉrification d'intรฉgritรฉ
- Rรฉplication de contenu : Synchronisation de fichiers web ou applicatifs entre environnements
- Backup incrรฉmental : Sauvegarde efficace avec transfert uniquement des changements
Script
#!/bin/bash
#===============================================================================
# Script Name: sync-folders.sh
# Description: Synchronisation de dossiers avec rsync
# Author: ShellBook
# Version: 1.0
#===============================================================================
set -euo pipefail
# Colors
readonly RED='\033[0;31m'
readonly GREEN='\033[0;32m'
readonly YELLOW='\033[1;33m'
readonly CYAN='\033[0;36m'
readonly NC='\033[0m'
# Configuration
DRY_RUN=false
DELETE=false
VERBOSE=false
COMPRESS=false
EXCLUDE_FILE=""
SSH_PORT=22
usage() {
cat << EOF
Usage: $(basename "$0") [OPTIONS] SOURCE DESTINATION
Synchronisation de dossiers avec rsync.
Arguments:
SOURCE Dossier source (local ou user@host:path)
DESTINATION Dossier destination (local ou user@host:path)
Options:
-d, --dry-run Simulation sans modification
--delete Supprimer les ficyesterdays absents de la source
-v, --verbose Verbose mode
-z, --compress Compresser pendant le transfert
-e, --exclude FILE Ficyesterday d'exclusions
-p, --port NUM Port SSH (default: 22)
-h, --help Show this help
Examples:
$(basename "$0") /home/user/docs /backup/docs
$(basename "$0") -v --delete /var/www /backup/www
$(basename "$0") /data user@server:/backup
$(basename "$0") -d user@server:/data /local/backup
EOF
}
log_info() {
echo -e "${GREEN}[INFO]${NC} $1"
}
log_warn() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $1" >&2
}
format_size() {
local bytes=$1
if (( bytes >= 1073741824 )); then
printf "%.2fG" $(echo "scale=2; $bytes/1073741824" | bc)
elif (( bytes >= 1048576 )); then
printf "%.2fM" $(echo "scale=2; $bytes/1048576" | bc)
elif (( bytes >= 1024 )); then
printf "%.2fK" $(echo "scale=2; $bytes/1024" | bc)
else
printf "%dB" "$bytes"
fi
}
is_remote() {
[[ "$1" == *":"* ]]
}
build_rsync_options() {
local opts="-a --progress --stats"
[[ "$DRY_RUN" == "true" ]] && opts="$opts --dry-run"
[[ "$DELETE" == "true" ]] && opts="$opts --delete"
[[ "$VERBOSE" == "true" ]] && opts="$opts -v"
[[ "$COMPRESS" == "true" ]] && opts="$opts -z"
if [[ -n "$EXCLUDE_FILE" ]] && [[ -f "$EXCLUDE_FILE" ]]; then
opts="$opts --exclude-from=$EXCLUDE_FILE"
fi
# SSH options si transfert distant
if is_remote "$SOURCE" || is_remote "$DESTINATION"; then
opts="$opts -e 'ssh -p $SSH_PORT'"
fi
echo "$opts"
}
get_dir_info() {
local path=$1
if is_remote "$path"; then
# Pour chemins distants
local host=${path%%:*}
local remote_path=${path#*:}
ssh -p "$SSH_PORT" "$host" "du -sb '$remote_path' 2>/dev/null" | awk '{print $1}' || echo "0"
else
if [[ -d "$path" ]]; then
du -sb "$path" 2>/dev/null | awk '{print $1}' || echo "0"
else
echo "0"
fi
fi
}
main() {
local SOURCE=""
local DESTINATION=""
# Parse arguments
while [[ $# -gt 0 ]]; do
case $1 in
-d|--dry-run)
DRY_RUN=true
shift
;;
--delete)
DELETE=true
shift
;;
-v|--verbose)
VERBOSE=true
shift
;;
-z|--compress)
COMPRESS=true
shift
;;
-e|--exclude)
EXCLUDE_FILE="$2"
shift 2
;;
-p|--port)
SSH_PORT="$2"
shift 2
;;
-h|--help)
usage
exit 0
;;
-*)
log_error "Unknown option: $1"
usage
exit 1
;;
*)
if [[ -z "$SOURCE" ]]; then
SOURCE="$1"
elif [[ -z "$DESTINATION" ]]; then
DESTINATION="$1"
fi
shift
;;
esac
done
# Validation
if [[ -z "$SOURCE" ]] || [[ -z "$DESTINATION" ]]; then
log_error "Source et destination requises"
usage
exit 1
fi
# Vรฉrification source
if ! is_remote "$SOURCE" && [[ ! -d "$SOURCE" ]]; then
log_error "Source does not exist: $SOURCE"
exit 1
fi
# Header
echo -e "${CYAN}โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ${NC}"
echo -e "${GREEN} SYNCHRONISATION DE DOSSIERS${NC}"
echo -e "${CYAN}โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ${NC}"
echo -e " Source: $SOURCE"
echo -e " Destination: $DESTINATION"
echo -e " Mode: ${DRY_RUN:+SIMULATION}${DRY_RUN:-EXรCUTION}"
[[ "$DELETE" == "true" ]] && echo -e " ${YELLOW}โ Delete mode activรฉ${NC}"
echo -e "${CYAN}โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ${NC}"
# Info sur la source
if ! is_remote "$SOURCE"; then
local source_size=$(get_dir_info "$SOURCE")
log_info "Taille source: $(format_size $source_size)"
fi
# Construction options rsync
local rsync_opts=$(build_rsync_options)
if [[ "$DRY_RUN" == "true" ]]; then
log_warn "Mode simulation - aucune modification ne sera effectuรฉe"
fi
echo ""
log_info "Dรฉmarrage de la synchronisation..."
echo ""
# Exรฉcution rsync
local start_time=$(date +%s)
# S'assurer que la source a un / final pour synchroniser le contenu
[[ "$SOURCE" != */ ]] && SOURCE="$SOURCE/"
eval rsync $rsync_opts "$SOURCE" "$DESTINATION"
local end_time=$(date +%s)
local duration=$((end_time - start_time))
# Rรฉsumรฉ
echo ""
echo -e "${CYAN}โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ${NC}"
if [[ "$DRY_RUN" == "true" ]]; then
log_info "Simulation completede (aucune modification)"
else
log_info "Synchronizing completede!"
fi
log_info "Durรฉe: ${duration}s"
echo -e "${CYAN}โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ${NC}"
}
main "$@"
Usage
# Rendre exรฉcutable
chmod +x sync-folders.sh
# Synchronisation locale
./sync-folders.sh /home/user/documents /backup/documents
# Avec suppression des ficyesterdays absents
./sync-folders.sh --delete /var/www /backup/www
# Simulation d'abord
./sync-folders.sh -d --delete /data /backup
# Vers un serveur distant
./sync-folders.sh -z /home/user user@server:/backup
# Depuis un serveur distant
./sync-folders.sh user@server:/data /local/backup
# Avec exclusions
./sync-folders.sh -e exclude.txt /source /dest
Sortie Exemple
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
SYNCHRONISATION DE DOSSIERS
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Source: /home/user/documents/
Destination: /backup/documents
Mode: EXรCUTION
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
[INFO] Taille source: 2.34G
[INFO] Dรฉmarrage de la synchronisation...
sending incremental file list
./
document1.pdf
12,456,789 100% 45.23MB/s 0:00:00 (xfr#1, to-chk=142/145)
document2.docx
3,456,123 100% 12.45MB/s 0:00:00 (xfr#2, to-chk=141/145)
...
Number of files: 145 (reg: 138, dir: 7)
Number of created files: 5
Number of deleted files: 0
Number of regular files transferred: 8
Total file size: 2,456,789,123 bytes
Total transferred file size: 45,678,901 bytes
Literal data: 45,678,901 bytes
Matched data: 0 bytes
Total bytes sent: 45,789,012
Total bytes received: 1,234
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
[INFO] Synchronisation completede!
[INFO] Durรฉe: 23s
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Ficyesterday d'Exclusion
Exemple de ficyesterday exclude.txt:
# Ficyesterdays temporaires
*.tmp
*.temp
*~
.*.swp
# Caches
.cache/
__pycache__/
node_modules/
# Ficyesterdays systรจme
.DS_Store
Thumbs.db
# Logs
*.log
logs/