📋 Commit iniziale con: - ✅ Documentazione unificata in docs/ - ✅ Codice Laravel in netgescon-laravel/ - ✅ Script automazione in scripts/ - ✅ Configurazione sync rsync - ✅ Struttura organizzata e pulita 🔄 Versione: 2025.07.19-1644 🎯 Sistema pronto per Git distribuito
399 lines
10 KiB
Bash
399 lines
10 KiB
Bash
#!/bin/bash
|
|
|
|
# NetGescon Auto-Sync Bash Script
|
|
# Sincronizzazione automatica tra WSL/Linux e server remoto
|
|
# Versione: 2.0
|
|
# Data: 2025-01-17
|
|
|
|
set -euo pipefail
|
|
|
|
# Configurazione
|
|
LOCAL_PATH="$HOME/netgescon/netgescon-laravel"
|
|
REMOTE_HOST="192.168.0.43"
|
|
REMOTE_USER="michele"
|
|
REMOTE_PATH="/var/www/netgescon"
|
|
BACKUP_DIR="$HOME/netgescon/backup/sync"
|
|
LOG_FILE="$HOME/netgescon/log/auto-sync.log"
|
|
|
|
# Opzioni default
|
|
MODE="sync"
|
|
TARGET="remote"
|
|
FORCE=false
|
|
VERBOSE=false
|
|
DRY_RUN=false
|
|
AUTO_RESTART=false
|
|
|
|
# Colori per output
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
CYAN='\033[0;36m'
|
|
NC='\033[0m' # No Color
|
|
|
|
# Funzioni utility
|
|
log() {
|
|
local message="$1"
|
|
local level="${2:-INFO}"
|
|
local timestamp=$(date "+%Y-%m-%d %H:%M:%S")
|
|
local log_entry="[$timestamp] [$level] $message"
|
|
|
|
# Crea directory log se non esiste
|
|
mkdir -p "$(dirname "$LOG_FILE")"
|
|
|
|
# Scrivi nel log
|
|
echo "$log_entry" >> "$LOG_FILE"
|
|
|
|
# Output colorato se verbose o errore
|
|
if [[ "$VERBOSE" == "true" || "$level" == "ERROR" ]]; then
|
|
case "$level" in
|
|
"ERROR")
|
|
echo -e "${RED}$log_entry${NC}" >&2
|
|
;;
|
|
"WARN")
|
|
echo -e "${YELLOW}$log_entry${NC}"
|
|
;;
|
|
"SUCCESS")
|
|
echo -e "${GREEN}$log_entry${NC}"
|
|
;;
|
|
*)
|
|
echo -e "${NC}$log_entry${NC}"
|
|
;;
|
|
esac
|
|
fi
|
|
}
|
|
|
|
show_usage() {
|
|
cat << EOF
|
|
NetGescon Auto-Sync Script
|
|
|
|
Uso: $0 [OPZIONI]
|
|
|
|
Modalità:
|
|
-m, --mode MODE Modalità operazione (sync|deploy|backup|status) [default: sync]
|
|
-t, --target TARGET Target operazione (remote|local|both) [default: remote]
|
|
|
|
Opzioni:
|
|
-f, --force Forza operazioni senza backup
|
|
-v, --verbose Output dettagliato
|
|
-d, --dry-run Simulazione senza modifiche
|
|
-r, --auto-restart Riavvia servizi automaticamente
|
|
-h, --help Mostra questo aiuto
|
|
|
|
Esempi:
|
|
$0 # Sync completo
|
|
$0 -m status -v # Mostra stato dettagliato
|
|
$0 -m sync -f -r # Sync forzato con riavvio
|
|
$0 -m backup -t both # Backup locale e remoto
|
|
$0 -d -m sync # Simula sync senza modifiche
|
|
|
|
EOF
|
|
}
|
|
|
|
parse_args() {
|
|
while [[ $# -gt 0 ]]; do
|
|
case $1 in
|
|
-m|--mode)
|
|
MODE="$2"
|
|
shift 2
|
|
;;
|
|
-t|--target)
|
|
TARGET="$2"
|
|
shift 2
|
|
;;
|
|
-f|--force)
|
|
FORCE=true
|
|
shift
|
|
;;
|
|
-v|--verbose)
|
|
VERBOSE=true
|
|
shift
|
|
;;
|
|
-d|--dry-run)
|
|
DRY_RUN=true
|
|
shift
|
|
;;
|
|
-r|--auto-restart)
|
|
AUTO_RESTART=true
|
|
shift
|
|
;;
|
|
-h|--help)
|
|
show_usage
|
|
exit 0
|
|
;;
|
|
*)
|
|
echo "Opzione sconosciuta: $1" >&2
|
|
show_usage
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
}
|
|
|
|
test_remote_connection() {
|
|
log "Testando connessione al server remoto..."
|
|
|
|
if ssh -o ConnectTimeout=10 -o BatchMode=yes "$REMOTE_USER@$REMOTE_HOST" "echo 'Connected'" >/dev/null 2>&1; then
|
|
log "Connessione remota OK" "SUCCESS"
|
|
return 0
|
|
else
|
|
log "Errore connessione remota" "ERROR"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
backup_local() {
|
|
log "Creando backup locale..."
|
|
|
|
local backup_path="$BACKUP_DIR/local-$(date +%Y%m%d-%H%M%S)"
|
|
|
|
mkdir -p "$BACKUP_DIR"
|
|
|
|
if [[ "$DRY_RUN" == "true" ]]; then
|
|
log "DRY RUN: Backup locale verso $backup_path" "WARN"
|
|
return 0
|
|
fi
|
|
|
|
if cp -r "$LOCAL_PATH" "$backup_path" 2>/dev/null; then
|
|
log "Backup locale creato: $backup_path" "SUCCESS"
|
|
return 0
|
|
else
|
|
log "Errore durante backup locale" "ERROR"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
backup_remote() {
|
|
log "Creando backup remoto..."
|
|
|
|
local timestamp=$(date +%Y%m%d-%H%M%S)
|
|
local backup_cmd="sudo cp -r $REMOTE_PATH ${REMOTE_PATH}_backup_$timestamp"
|
|
|
|
if [[ "$DRY_RUN" == "true" ]]; then
|
|
log "DRY RUN: $backup_cmd" "WARN"
|
|
return 0
|
|
fi
|
|
|
|
if ssh "$REMOTE_USER@$REMOTE_HOST" "$backup_cmd" 2>/dev/null; then
|
|
log "Backup remoto creato: ${REMOTE_PATH}_backup_$timestamp" "SUCCESS"
|
|
return 0
|
|
else
|
|
log "Errore durante backup remoto" "ERROR"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
sync_to_remote() {
|
|
log "Sincronizzando verso server remoto..."
|
|
|
|
# Costruisci exclude pattern per rsync
|
|
local exclude_args=(
|
|
"--exclude=node_modules/"
|
|
"--exclude=vendor/"
|
|
"--exclude=storage/logs/"
|
|
"--exclude=storage/framework/cache/"
|
|
"--exclude=storage/framework/sessions/"
|
|
"--exclude=storage/framework/views/"
|
|
"--exclude=.git/"
|
|
"--exclude=*.log"
|
|
"--exclude=.env.local"
|
|
"--exclude=.env.backup"
|
|
)
|
|
|
|
local rsync_cmd=(
|
|
"rsync"
|
|
"-avz"
|
|
"--delete"
|
|
"${exclude_args[@]}"
|
|
"$LOCAL_PATH/"
|
|
"$REMOTE_USER@$REMOTE_HOST:$REMOTE_PATH/"
|
|
)
|
|
|
|
if [[ "$DRY_RUN" == "true" ]]; then
|
|
log "DRY RUN: ${rsync_cmd[*]}" "WARN"
|
|
return 0
|
|
fi
|
|
|
|
log "Eseguendo rsync: ${rsync_cmd[*]}"
|
|
|
|
if "${rsync_cmd[@]}" 2>/dev/null; then
|
|
log "Sincronizzazione completata con successo" "SUCCESS"
|
|
return 0
|
|
else
|
|
log "Errore durante sincronizzazione" "ERROR"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
deploy_remote() {
|
|
log "Eseguendo deploy sul server remoto..."
|
|
|
|
local deploy_commands=(
|
|
"cd $REMOTE_PATH"
|
|
"sudo chown -R www-data:www-data ."
|
|
"sudo chmod -R 755 ."
|
|
"sudo chmod -R 777 storage/"
|
|
"sudo chmod -R 777 bootstrap/cache/"
|
|
"composer install --no-dev --optimize-autoloader"
|
|
"php artisan config:cache"
|
|
"php artisan route:cache"
|
|
"php artisan view:cache"
|
|
)
|
|
|
|
if [[ "$AUTO_RESTART" == "true" ]]; then
|
|
deploy_commands+=(
|
|
"sudo systemctl restart nginx"
|
|
"sudo systemctl restart php8.3-fpm"
|
|
)
|
|
fi
|
|
|
|
local full_command
|
|
IFS=' && ' eval 'full_command="${deploy_commands[*]}"'
|
|
|
|
if [[ "$DRY_RUN" == "true" ]]; then
|
|
log "DRY RUN: $full_command" "WARN"
|
|
return 0
|
|
fi
|
|
|
|
log "Eseguendo deploy remoto..."
|
|
if ssh "$REMOTE_USER@$REMOTE_HOST" "$full_command" 2>/dev/null; then
|
|
log "Deploy completato con successo" "SUCCESS"
|
|
return 0
|
|
else
|
|
log "Errore durante deploy" "ERROR"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
run_migrations() {
|
|
log "Eseguendo migrazioni sul server remoto..."
|
|
|
|
local migration_commands=(
|
|
"cd $REMOTE_PATH"
|
|
"php artisan migrate --force"
|
|
)
|
|
|
|
local full_command
|
|
IFS=' && ' eval 'full_command="${migration_commands[*]}"'
|
|
|
|
if [[ "$DRY_RUN" == "true" ]]; then
|
|
log "DRY RUN: $full_command" "WARN"
|
|
return 0
|
|
fi
|
|
|
|
if ssh "$REMOTE_USER@$REMOTE_HOST" "$full_command" 2>/dev/null; then
|
|
log "Migrazioni completate con successo" "SUCCESS"
|
|
return 0
|
|
else
|
|
log "Errore durante migrazioni" "ERROR"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
show_status() {
|
|
log "Controllando stato del sistema..."
|
|
|
|
# Status locale
|
|
echo -e "\n${CYAN}=== STATUS LOCALE ===${NC}"
|
|
echo "Path: $LOCAL_PATH"
|
|
echo "Esistenza: $(test -d "$LOCAL_PATH" && echo "true" || echo "false")"
|
|
|
|
if [[ -d "$LOCAL_PATH" ]]; then
|
|
local file_count=$(find "$LOCAL_PATH" -type f | wc -l)
|
|
echo "File totali: $file_count"
|
|
|
|
local last_modified=$(find "$LOCAL_PATH" -type f -exec stat -c '%Y %n' {} \; 2>/dev/null | sort -nr | head -1)
|
|
echo "Ultima modifica: $last_modified"
|
|
|
|
local disk_usage=$(du -sh "$LOCAL_PATH" 2>/dev/null | cut -f1)
|
|
echo "Spazio disco: $disk_usage"
|
|
fi
|
|
|
|
# Status remoto
|
|
echo -e "\n${CYAN}=== STATUS REMOTO ===${NC}"
|
|
if test_remote_connection; then
|
|
local remote_status
|
|
remote_status=$(ssh "$REMOTE_USER@$REMOTE_HOST" "
|
|
cd $REMOTE_PATH 2>/dev/null || exit 1
|
|
echo 'Path exists: true'
|
|
echo 'Files count: \$(find . -type f | wc -l)'
|
|
echo 'Last modified: \$(find . -type f -exec stat -c '%Y %n' {} \; | sort -nr | head -1)'
|
|
echo 'Disk usage: \$(du -sh . | cut -f1)'
|
|
echo 'Laravel version: \$(php artisan --version 2>/dev/null || echo \"N/A\")'
|
|
echo 'Database status:'
|
|
php artisan migrate:status 2>/dev/null | tail -5 || echo 'N/A'
|
|
" 2>/dev/null)
|
|
|
|
if [[ $? -eq 0 ]]; then
|
|
echo "$remote_status"
|
|
else
|
|
echo -e "${RED}Errore nel recupero status remoto${NC}"
|
|
fi
|
|
fi
|
|
}
|
|
|
|
main() {
|
|
log "=== NetGescon Auto-Sync Started ===" "SUCCESS"
|
|
log "Modalità: $MODE, Target: $TARGET, Force: $FORCE, DryRun: $DRY_RUN"
|
|
|
|
# Verifica connessione remota se necessario
|
|
if [[ "$TARGET" == "remote" || "$TARGET" == "both" ]]; then
|
|
if ! test_remote_connection; then
|
|
log "Impossibile connettersi al server remoto. Uscita." "ERROR"
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
case "$MODE" in
|
|
"status")
|
|
show_status
|
|
;;
|
|
|
|
"backup")
|
|
if [[ "$TARGET" == "local" || "$TARGET" == "both" ]]; then
|
|
backup_local || exit 1
|
|
fi
|
|
if [[ "$TARGET" == "remote" || "$TARGET" == "both" ]]; then
|
|
backup_remote || exit 1
|
|
fi
|
|
;;
|
|
|
|
"sync")
|
|
# Backup prima della sincronizzazione
|
|
if [[ "$FORCE" != "true" ]]; then
|
|
backup_local || {
|
|
log "Backup locale fallito. Usa -f per continuare." "ERROR"
|
|
exit 1
|
|
}
|
|
backup_remote || {
|
|
log "Backup remoto fallito. Usa -f per continuare." "ERROR"
|
|
exit 1
|
|
}
|
|
fi
|
|
|
|
# Sincronizzazione
|
|
sync_to_remote || exit 1
|
|
|
|
# Deploy automatico
|
|
deploy_remote || exit 1
|
|
;;
|
|
|
|
"deploy")
|
|
deploy_remote || exit 1
|
|
run_migrations || exit 1
|
|
;;
|
|
|
|
*)
|
|
log "Modalità non riconosciuta: $MODE" "ERROR"
|
|
show_usage
|
|
exit 1
|
|
;;
|
|
esac
|
|
|
|
log "=== NetGescon Auto-Sync Completed ===" "SUCCESS"
|
|
}
|
|
|
|
# Parse arguments and run main
|
|
parse_args "$@"
|
|
main
|