From 255260c97959f30471d4cebdd662a9eba1b8b713 Mon Sep 17 00:00:00 2001 From: francesco Date: Tue, 21 Apr 2026 13:06:46 +0200 Subject: [PATCH] ++ Fix Semplificazione progetto, centralizzazione Gotify + Upload --- .gitignore | 12 +++ .secret.example | 7 -- README.md | 42 +++++--- backup.sh | 248 +++++++++++++----------------------------------- core.sh | 202 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 309 insertions(+), 202 deletions(-) create mode 100644 .gitignore create mode 100644 core.sh diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a94f168 --- /dev/null +++ b/.gitignore @@ -0,0 +1,12 @@ +### Windows +# Windows thumbnail cache files +Thumbs.db + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows shortcuts +*.lnk \ No newline at end of file diff --git a/.secret.example b/.secret.example index 88d4682..196bbd3 100644 --- a/.secret.example +++ b/.secret.example @@ -5,10 +5,3 @@ DB_HOST=localhost DB_NAME=nome_database DB_USER=utente_mysql DB_PASS=password_mysql - -# Gotify -GOTIFY_URL="https://alert.qwince.com/message" -GOTIFY_TOKEN="ABnq7pJSSPrFRjx" - -# Upload HTTP endpoint -UPLOAD_URL="http://192.168.0.10:8080/upload" diff --git a/README.md b/README.md index e4c9373..980bedf 100644 --- a/README.md +++ b/README.md @@ -24,26 +24,21 @@ Script bash per eseguire il backup automatico di un database MySQL e della carte 3. Il file `.secret.UTENTE` verrà creato automaticamente con le credenziali fornite. -4. (Opzionale) Modifica il file per configurare Gotify e upload remoto: +4. Rendi eseguibile lo script di backup: ```bash - nano .secret.UTENTE - ``` - -5. Rendi eseguibile lo script di backup: - ```bash - chmod +x backup.sh + chmod +x core.sh ``` ## Utilizzo Esegui lo script specificando utente e dominio: ```bash -./backup.sh utente dominio +./core.sh utente dominio ``` Esempio: ```bash -./backup.sh myuser esempio.com +./core.sh myuser esempio.com ``` ## Configurazione su Webmin/Cron @@ -59,12 +54,12 @@ Esempio: ```bash chmod +x init.sh ./init.sh - chmod +x backup.sh + chmod +x core.sh ``` 3. Su cron manager inserisci: ```bash - /home/UTENTE/cloudpanel-backup/backup.sh UTENTE dominio.com + /home/UTENTE/cloudpanel-backup/core.sh UTENTE dominio.com ``` ## Funzionalità @@ -72,11 +67,34 @@ Esempio: 1. Esegue il dump del database MySQL specificato 2. Copia la cartella `/home/UTENTE/htdocs/DOMINIO` 3. Crea un archivio ZIP contenente database e file del sito -4. (Opzionale) Trasferisce il backup su server remoto +4. (Opzionale) Trasferisce il backup su server remoto via HTTP 5. (Opzionale) Invia notifiche via Gotify 6. Pulisce i file temporanei 7. Il file ZIP ha il formato: `backup_DOMINIO_YYYYMMDD_HHMMSS.zip` +## Configurazione Gotify e Upload remoto + +Le impostazioni di Gotify e dell'endpoint di upload sono centralizzate nel file `core.sh` e non nei file `.secret.*`. +Per modificarle, edita direttamente `core.sh`: +```bash +# Gotify +GOTIFY_URL="https://alert.qwince.com/message" +GOTIFY_TOKEN="il_tuo_token" + +# Upload HTTP endpoint +UPLOAD_URL="http://192.168.0.10:8080/upload" +``` + +## Backup multiplo + +Per eseguire il backup di tutti i siti configurati: +```bash +chmod +x backup-siti.sh +./backup-siti.sh +``` + +L'elenco dei siti è configurabile nell'array `SITES` dentro `backup-siti.sh`. + ## Note di sicurezza - Il file `.secret.UTENTE` contiene credenziali sensibili diff --git a/backup.sh b/backup.sh index 40e43e4..0bb5ab3 100644 --- a/backup.sh +++ b/backup.sh @@ -1,195 +1,77 @@ #!/bin/bash -# Script di backup per database MySQL e cartella htdocs -# Le credenziali del database devono essere nel file .secret -# Uso: ./backup.sh user dominio - -# Verifica parametri user e dominio -if [ -z "$1" ] || [ -z "$2" ]; then - echo "Errore: Specificare user e dominio come parametri" - echo "Uso: $0 user dominio" - echo "Esempio: $0 utente esempio.com" - exit 1 -fi - -USER="$1" -DOMAIN="$2" - # Ottieni la directory dello script SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -SECRET_FILE="$SCRIPT_DIR/.secret.$USER" -# Verifica che il file .secret esista -if [ ! -f "$SECRET_FILE" ]; then - echo "Errore: File .secret non trovato in $SCRIPT_DIR" - echo "Creare il file .secret con le seguenti variabili:" - echo "DB_HOST=localhost" - echo "DB_NAME=nome_database" - echo "DB_USER=utente" - echo "DB_PASS=password" - exit 1 -fi +LOG_DIR="/tmp/cloudpanel-backup-log" +LOG_FILE="$LOG_DIR/backup_siti.log" +BACKUP_SCRIPT="$SCRIPT_DIR/core.sh" -# Carica le credenziali dal file .secret -source "$SECRET_FILE" +# Crea la directory dei log se non esiste +mkdir -p "$LOG_DIR" -# Verifica che le variabili necessarie siano definite -if [ -z "$DB_HOST" ] || [ -z "$DB_NAME" ] || [ -z "$DB_USER" ] || [ -z "$DB_PASS" ]; then - echo "Errore: Una o più variabili mancanti nel file .secret" - echo "Variabili richieste: DB_HOST, DB_NAME, DB_USER, DB_PASS" - exit 1 -fi +# Cancella il log precedente +: > "$LOG_FILE" -# Funzione per inviare notifica a Gotify -send_gotify_notification() { - local title="$1" - local message="$2" - local priority="${3:-5}" - - if [ -n "$GOTIFY_URL" ] && [ -n "$GOTIFY_TOKEN" ]; then - curl -X POST "$GOTIFY_URL" \ - -H "Content-Type: application/json" \ - -d "{\"title\":\"$title\",\"message\":\"$message\",\"priority\":$priority}" \ - -H "X-Gotify-Key: $GOTIFY_TOKEN" \ - -s > /dev/null 2>&1 - fi -} - -# Funzione per trasferire il backup su server remoto via HTTP -transfer_to_remote() { - local file="$1" - - if [ -z "$UPLOAD_URL" ]; then - echo "Attenzione: URL di upload non configurato, trasferimento saltato" - return 0 - fi - - # Verifica disponibilità del server - echo "Verifica disponibilità server remoto..." - SERVER_CHECK=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 5 --max-time 10 "$UPLOAD_URL" 2>/dev/null) - - if [ $? -ne 0 ] || [ -z "$SERVER_CHECK" ]; then - echo "⚠️ Server remoto non raggiungibile" - send_gotify_notification "⚠️ [ $DOMAIN ] Backup Locale" "Data: $DATE_FORMAT\nBackup di $DOMAIN completato\nServer remoto non disponibile\nFile mantenuto in locale: backup_${DOMAIN}_$TIMESTAMP.zip" 6 - return 2 - fi - - echo "Server disponibile (HTTP $SERVER_CHECK)" - echo "Trasferimento backup su server remoto via HTTP..." - echo "" - - # Upload del file via curl con barra di progresso - RESPONSE=$(curl -X POST "$UPLOAD_URL" -F "file=@$file" -#) - - echo "" - if [ $? -ne 0 ]; then - echo "Errore durante il trasferimento del backup" - send_gotify_notification "⚠️ [ $DOMAIN ] Backup Parziale" "Data: $DATE_FORMAT\nBackup di $DOMAIN completato ma trasferimento remoto fallito" 6 - return 1 - fi - - # Verifica la risposta - if echo "$RESPONSE" | grep -q '"status":"ok"'; then - echo "Backup trasferito con successo" - echo "Risposta server: $RESPONSE" - return 0 - else - echo "Errore: Risposta server non valida" - echo "Risposta: $RESPONSE" - send_gotify_notification "⚠️ [ $DOMAIN ] Backup Parziale" "Data: $DATE_FORMAT\nBackup di $DOMAIN completato ma upload fallito" 6 - return 1 - fi -} - -# Configurazione -TIMESTAMP=$(date +"%Y%m%d_%H%M%S") -DATE_FORMAT=$(date +"%d/%m/%Y") -BACKUP_DIR="$SCRIPT_DIR/backup_${DOMAIN}_$TIMESTAMP" -SITE_DIR="/home/${USER}/htdocs/${DOMAIN}" -DB_DUMP_FILE="$BACKUP_DIR/database_$TIMESTAMP.sql" -ZIP_FILE="$SCRIPT_DIR/backup_${DOMAIN}_$TIMESTAMP.zip" - -# Crea directory di backup temporanea -echo "Creazione directory di backup..." -mkdir -p "$BACKUP_DIR" - -# Esegui dump del database -echo "Esecuzione dump del database $DB_NAME per il dominio $DOMAIN..." -mysqldump --no-tablespaces -h "$DB_HOST" -u "$DB_USER" -p"$DB_PASS" "$DB_NAME" > "$DB_DUMP_FILE" - -if [ $? -ne 0 ]; then - echo "Errore durante il dump del database" - send_gotify_notification "❌ [ $DOMAIN ] Backup Fallito" "Data: $DATE_FORMAT\nErrore durante il dump del database $DB_NAME per $DOMAIN" 8 - rm -rf "$BACKUP_DIR" - exit 1 -fi - -echo "Dump del database completato: $DB_DUMP_FILE" - -# Verifica che la cartella del sito esista -if [ ! -d "$SITE_DIR" ]; then - echo "Attenzione: La cartella $SITE_DIR non esiste" - echo "Continuando solo con il backup del database..." -else - # Copia la cartella del sito - echo "Copia della cartella del sito..." - cp -r "$SITE_DIR" "$BACKUP_DIR/htdocs" - - if [ $? -ne 0 ]; then - echo "Errore durante la copia della cartella del sito" - send_gotify_notification "❌ [ $DOMAIN ] Backup Fallito" "Data: $DATE_FORMAT\nErrore durante la copia della cartella $SITE_DIR" 8 - rm -rf "$BACKUP_DIR" - exit 1 - fi - - echo "Cartella del sito copiata con successo" -fi - -# Crea archivio zip -echo "Creazione archivio zip..." -cd "$SCRIPT_DIR" -zip -r "$ZIP_FILE" "backup_${DOMAIN}_$TIMESTAMP" - -if [ $? -ne 0 ]; then - echo "Errore durante la creazione dell'archivio zip" - send_gotify_notification "❌ [ $DOMAIN ] Backup Fallito" "Data: $DATE_FORMAT\nErrore durante la creazione dell'archivio zip per $DOMAIN" 8 - rm -rf "$BACKUP_DIR" - exit 1 -fi - -echo "Archivio zip creato: $ZIP_FILE" - -# Rimuovi la directory temporanea -echo "Pulizia file temporanei..." -rm -rf "$BACKUP_DIR" - -BACKUP_SIZE=$(du -h "$ZIP_FILE" | cut -f1) +exec > >(tee -a "$LOG_FILE") 2>&1 +echo "==========================================" +echo "Backup Siti" +echo "Data: $(date '+%d-%m-%Y %H:%M:%S')" +echo "==========================================" echo "" -echo "==========================================" -echo "Backup completato con successo!" -echo "File: $ZIP_FILE" -echo "Dimensione: $BACKUP_SIZE" -echo "==========================================" -# Trasferisci il backup su server remoto -transfer_to_remote "$ZIP_FILE" -TRANSFER_STATUS=$? +# Array: "utente dominio" +SITES=( + "associazionecoach associazionecoach.com" + "qwince-adam adam.qwince.com" + "ainormanni ainormanni.com" + "cathedralroomandloft cathedralroomandloft.com" + "gdmantincendio gdmantincendio.it" + "greeningtech greeningtech.com" + "qwince-mercurio mercurio.qwince.com" + "farmasfera-sso-test portale-test-farmasfera.qwince.com" + "professionalvalue professionalvalue.it" + "puntofarma puntofarma.online" + "teleconsulto-sanita sanita.teleconsulto.online" + "studiolegaletodaro studiolegaletodaro.it" + "termanager termanager.pyconetwork.it" + "qwince-webcalcio webcalcio.qwince.com" + "akashido www.akashido.it" + "skillforequity www.skillforequity.com" + "concura concura.online" + "qwince qwince.com" + # TODO: aggiungere utente mancante + # "UTENTE neuralya.marketing" + # "UTENTE longevity.concura.online" +) -# Se il trasferimento è riuscito, rimuovi il file locale -if [ $TRANSFER_STATUS -eq 0 ]; then - echo "Rimozione file locale..." - rm -f "$ZIP_FILE" - echo "File zip rimosso dal locale, disponibile solo sul server remoto" - send_gotify_notification "✅ [ $DOMAIN ] Backup Completato" "Data: $DATE_FORMAT\nBackup di $DOMAIN completato con successo\nFile: backup_${DOMAIN}_$TIMESTAMP.zip\nDimensione: $BACKUP_SIZE\nCaricato sul server remoto" 5 -elif [ $TRANSFER_STATUS -eq 2 ]; then - # Server non disponibile - mantieni solo l'ultima copia locale - echo "Pulizia backup precedenti..." - find "$SCRIPT_DIR" -name "backup_${DOMAIN}_*.zip" -type f ! -name "backup_${DOMAIN}_$TIMESTAMP.zip" -delete - echo "Mantenuta solo l'ultima copia locale" -else - # Errore durante il trasferimento - mantieni solo l'ultima copia locale - echo "Pulizia backup precedenti..." - find "$SCRIPT_DIR" -name "backup_${DOMAIN}_*.zip" -type f ! -name "backup_${DOMAIN}_$TIMESTAMP.zip" -delete - send_gotify_notification "⚠️ Backup Parziale" "Data: $DATE_FORMAT\nBackup di $DOMAIN completato localmente\nFile: backup_${DOMAIN}_$TIMESTAMP.zip\nDimensione: $BACKUP_SIZE\nTrasferimento remoto fallito - File mantenuto in locale" 6 -fi +TOTAL=0 +SUCCESS=0 +FAILED=0 + +for SITE in "${SITES[@]}"; do + USER=$(awk '{print $1}' <<< "$SITE") + DOMAIN=$(awk '{print $2}' <<< "$SITE") + + TOTAL=$((TOTAL + 1)) + + echo "→ Backup $DOMAIN (utente: $USER)" + "$BACKUP_SCRIPT" "$USER" "$DOMAIN" + EXIT_CODE=$? + + if [ $EXIT_CODE -ne 0 ]; then + echo "❌ ERRORE backup $DOMAIN (exit code $EXIT_CODE)" + FAILED=$((FAILED + 1)) + else + echo "✅ Backup completato $DOMAIN" + SUCCESS=$((SUCCESS + 1)) + fi + + echo "" +done + +echo "==========================================" +echo "Backup terminato" +echo "Totale: $TOTAL | Riusciti: $SUCCESS | Falliti: $FAILED" +echo "==========================================" diff --git a/core.sh b/core.sh new file mode 100644 index 0000000..239db8f --- /dev/null +++ b/core.sh @@ -0,0 +1,202 @@ +#!/bin/bash + +# Script di backup per database MySQL e cartella htdocs +# Le credenziali del database devono essere nel file .secret +# Uso: ./backup.sh user dominio + +# Verifica parametri user e dominio +if [ -z "$1" ] || [ -z "$2" ]; then + echo "Errore: Specificare user e dominio come parametri" + echo "Uso: $0 user dominio" + echo "Esempio: $0 utente esempio.com" + exit 1 +fi + +USER="$1" +DOMAIN="$2" + +# Gotify +GOTIFY_URL="https://alert.qwince.com/message" +GOTIFY_TOKEN="ABnq7pJSSPrFRjx" + +# Upload HTTP endpoint +UPLOAD_URL="http://192.168.0.10:8080/upload" + +# Ottieni la directory dello script +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +SECRET_FILE="$SCRIPT_DIR/.secret.$USER" + +# Verifica che il file .secret esista +if [ ! -f "$SECRET_FILE" ]; then + echo "Errore: File .secret non trovato in $SCRIPT_DIR" + echo "Creare il file .secret con le seguenti variabili:" + echo "DB_HOST=localhost" + echo "DB_NAME=nome_database" + echo "DB_USER=utente" + echo "DB_PASS=password" + exit 1 +fi + +# Carica le credenziali dal file .secret +source "$SECRET_FILE" + +# Verifica che le variabili necessarie siano definite +if [ -z "$DB_HOST" ] || [ -z "$DB_NAME" ] || [ -z "$DB_USER" ] || [ -z "$DB_PASS" ]; then + echo "Errore: Una o più variabili mancanti nel file .secret" + echo "Variabili richieste: DB_HOST, DB_NAME, DB_USER, DB_PASS" + exit 1 +fi + +# Funzione per inviare notifica a Gotify +send_gotify_notification() { + local title="$1" + local message="$2" + local priority="${3:-5}" + + if [ -n "$GOTIFY_URL" ] && [ -n "$GOTIFY_TOKEN" ]; then + curl -X POST "$GOTIFY_URL" \ + -H "Content-Type: application/json" \ + -d "{\"title\":\"$title\",\"message\":\"$message\",\"priority\":$priority}" \ + -H "X-Gotify-Key: $GOTIFY_TOKEN" \ + -s > /dev/null 2>&1 + fi +} + +# Funzione per trasferire il backup su server remoto via HTTP +transfer_to_remote() { + local file="$1" + + if [ -z "$UPLOAD_URL" ]; then + echo "Attenzione: URL di upload non configurato, trasferimento saltato" + return 0 + fi + + # Verifica disponibilità del server + echo "Verifica disponibilità server remoto..." + SERVER_CHECK=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 5 --max-time 10 "$UPLOAD_URL" 2>/dev/null) + + if [ $? -ne 0 ] || [ -z "$SERVER_CHECK" ]; then + echo "⚠️ Server remoto non raggiungibile" + send_gotify_notification "⚠️ [ $DOMAIN ] Backup Locale" "Data: $DATE_FORMAT\nBackup di $DOMAIN completato\nServer remoto non disponibile\nFile mantenuto in locale: backup_${DOMAIN}_$TIMESTAMP.zip" 6 + return 2 + fi + + echo "Server disponibile (HTTP $SERVER_CHECK)" + echo "Trasferimento backup su server remoto via HTTP..." + echo "" + + # Upload del file via curl con barra di progresso + RESPONSE=$(curl -X POST "$UPLOAD_URL" -F "file=@$file" -#) + + echo "" + if [ $? -ne 0 ]; then + echo "Errore durante il trasferimento del backup" + send_gotify_notification "⚠️ [ $DOMAIN ] Backup Parziale" "Data: $DATE_FORMAT\nBackup di $DOMAIN completato ma trasferimento remoto fallito" 6 + return 1 + fi + + # Verifica la risposta + if echo "$RESPONSE" | grep -q '"status":"ok"'; then + echo "Backup trasferito con successo" + echo "Risposta server: $RESPONSE" + return 0 + else + echo "Errore: Risposta server non valida" + echo "Risposta: $RESPONSE" + send_gotify_notification "⚠️ [ $DOMAIN ] Backup Parziale" "Data: $DATE_FORMAT\nBackup di $DOMAIN completato ma upload fallito" 6 + return 1 + fi +} + +# Configurazione +TIMESTAMP=$(date +"%Y%m%d_%H%M%S") +DATE_FORMAT=$(date +"%d/%m/%Y") +BACKUP_DIR="$SCRIPT_DIR/backup_${DOMAIN}_$TIMESTAMP" +SITE_DIR="/home/${USER}/htdocs/${DOMAIN}" +DB_DUMP_FILE="$BACKUP_DIR/database_$TIMESTAMP.sql" +ZIP_FILE="$SCRIPT_DIR/backup_${DOMAIN}_$TIMESTAMP.zip" + +# Crea directory di backup temporanea +echo "Creazione directory di backup..." +mkdir -p "$BACKUP_DIR" + +# Esegui dump del database +echo "Esecuzione dump del database $DB_NAME per il dominio $DOMAIN..." +mysqldump --no-tablespaces -h "$DB_HOST" -u "$DB_USER" -p"$DB_PASS" "$DB_NAME" > "$DB_DUMP_FILE" + +if [ $? -ne 0 ]; then + echo "Errore durante il dump del database" + send_gotify_notification "❌ [ $DOMAIN ] Backup Fallito" "Data: $DATE_FORMAT\nErrore durante il dump del database $DB_NAME per $DOMAIN" 8 + rm -rf "$BACKUP_DIR" + exit 1 +fi + +echo "Dump del database completato: $DB_DUMP_FILE" + +# Verifica che la cartella del sito esista +if [ ! -d "$SITE_DIR" ]; then + echo "Attenzione: La cartella $SITE_DIR non esiste" + echo "Continuando solo con il backup del database..." +else + # Copia la cartella del sito + echo "Copia della cartella del sito..." + cp -r "$SITE_DIR" "$BACKUP_DIR/htdocs" + + if [ $? -ne 0 ]; then + echo "Errore durante la copia della cartella del sito" + send_gotify_notification "❌ [ $DOMAIN ] Backup Fallito" "Data: $DATE_FORMAT\nErrore durante la copia della cartella $SITE_DIR" 8 + rm -rf "$BACKUP_DIR" + exit 1 + fi + + echo "Cartella del sito copiata con successo" +fi + +# Crea archivio zip +echo "Creazione archivio zip..." +cd "$SCRIPT_DIR" +zip -r "$ZIP_FILE" "backup_${DOMAIN}_$TIMESTAMP" + +if [ $? -ne 0 ]; then + echo "Errore durante la creazione dell'archivio zip" + send_gotify_notification "❌ [ $DOMAIN ] Backup Fallito" "Data: $DATE_FORMAT\nErrore durante la creazione dell'archivio zip per $DOMAIN" 8 + rm -rf "$BACKUP_DIR" + exit 1 +fi + +echo "Archivio zip creato: $ZIP_FILE" + +# Rimuovi la directory temporanea +echo "Pulizia file temporanei..." +rm -rf "$BACKUP_DIR" + +BACKUP_SIZE=$(du -h "$ZIP_FILE" | cut -f1) + +echo "" +echo "==========================================" +echo "Backup completato con successo!" +echo "File: $ZIP_FILE" +echo "Dimensione: $BACKUP_SIZE" +echo "==========================================" + +# Trasferisci il backup su server remoto +transfer_to_remote "$ZIP_FILE" +TRANSFER_STATUS=$? + +# Se il trasferimento è riuscito, rimuovi il file locale +if [ $TRANSFER_STATUS -eq 0 ]; then + echo "Rimozione file locale..." + rm -f "$ZIP_FILE" + echo "File zip rimosso dal locale, disponibile solo sul server remoto" + send_gotify_notification "✅ [ $DOMAIN ] Backup Completato" "Data: $DATE_FORMAT\nBackup di $DOMAIN completato con successo\nFile: backup_${DOMAIN}_$TIMESTAMP.zip\nDimensione: $BACKUP_SIZE\nCaricato sul server remoto" 5 +elif [ $TRANSFER_STATUS -eq 2 ]; then + # Server non disponibile - mantieni solo l'ultima copia locale + echo "Pulizia backup precedenti..." + find "$SCRIPT_DIR" -name "backup_${DOMAIN}_*.zip" -type f ! -name "backup_${DOMAIN}_$TIMESTAMP.zip" -delete + echo "Mantenuta solo l'ultima copia locale" +else + # Errore durante il trasferimento - mantieni solo l'ultima copia locale + echo "Pulizia backup precedenti..." + find "$SCRIPT_DIR" -name "backup_${DOMAIN}_*.zip" -type f ! -name "backup_${DOMAIN}_$TIMESTAMP.zip" -delete + send_gotify_notification "⚠️ Backup Parziale" "Data: $DATE_FORMAT\nBackup di $DOMAIN completato localmente\nFile: backup_${DOMAIN}_$TIMESTAMP.zip\nDimensione: $BACKUP_SIZE\nTrasferimento remoto fallito - File mantenuto in locale" 6 +fi