Script PowerShell per sysadmin per scaricare regolarmente backup dal server al computer

Recentemente, un mio amico si è trovato nella situazione in cui il provider del VPS è improvvisamente fallito senza preavviso. Purtroppo, per risparmiare, ha scelto un provider di nicchia, uno che non offriva nemmeno il download dei dati. Peggio ancora, non ha nemmeno l’abitudine di scaricare regolarmente i backup. Da un giorno all’altro, il suo sito è scomparso, insieme a tutti i dati contenuti.

Scioccato da questo, ho scritto uno script Powershell che scaricherà automaticamente i backup dal tuo server al tuo computer locale regolarmente, senza dover acquistare alcun servizio aggiuntivo di object storage o spendere un centesimo per altre cose. Tutto ciò di cui hai bisogno è un computer Windows che usi regolarmente (e che abbia molto spazio su disco) e che sia connesso a Internet.

Lo script eliminerà automaticamente i backup più vecchi di 5 giorni. Puoi impostare l’intervallo di backup automatico e l’età massima dei backup salvati localmente in base alle tue esigenze.


$ssh_port = 22
$ssh_address = "username@your.site"


Write-Output "Starting Discourse backup download task..."
Write-Output '------------------------'
Write-Output "Fetching the latest backup file..."
Write-Output ''

while ($true) {

    $filename = ''

    while ($true) {
        try {
            Write-Output "> ssh -p $ssh_port $ssh_address 'cd /var/discourse/shared/standalone/backups/default/ && ls -t | head -n 1'"
            Write-Output ''
            $filename = ssh -p $ssh_port "$ssh_address" 'cd /var/discourse/shared/standalone/backups/default/ && ls -t | head -n 1'
            break
        }
        catch {
            $filename = ''
    
            Write-Output "Failed to fetch... Here is the log:"
            Write-Output '-------------'
            Write-Output $_
            
            $answer = Read-Host "Do you want to re-fetch? (y/N)"
            if ($answer -ne 'y') {
                break
            }
            Write-Output ''
        }
    }
    
    
    if ([String]::IsNullOrEmpty($filename)) {
        Write-Output "Error: Failed to fetch file name $filename"
        Write-Output ''
        $answer = Read-Host 'Retry?(y/N)'
  
        if ($answer -eq 'y') {
  
        }
        else {
      
            exit 1
        }
  
    }
    else {

        Write-Output "Latest backup: $filename"
        Write-Output ''
        
        $need_download = $true
        if (Test-Path ".\backups\$filename") {
            $answer = Read-Host ".\backups\$filename already exists. Do you want to download it again?(y/N)"
            Write-Output ''
            if ($answer -ne 'y') {
                $need_download = $false
            }
        }
        if ($need_download) {
            Write-Output "Start downloading..."
            Write-Output ''
            
            while ($true) {
                try {
                    Write-Output "scp -p $ssh_port ${ssh_address}:/var/discourse/shared/standalone/backups/default/$filename .\\backups\\"
                    Write-Output ''

                    scp -p $ssh_port "${ssh_address}:/var/discourse/shared/standalone/backups/default/$filename" .\\backups\
                    
                    Write-Output "Download completed"
                    Write-Output ''
                    
                    break
                }
                catch {

                    Write-Output "Download failed >_<... The following is the log:"
                    Write-Output ''

                    Write-Output $_
                    
                    $answer = Read-Host "Download again? (y/N)"
                    Write-Output ''
                    if ($answer -ne 'y') {
                        break
                    }
                }
            }

        }
  
        Write-Output "Start trying to clean old backup files..."
        Write-Output ''

        $count = 0
        $backupfiles = Get-ChildItem -Path .\\backups\
  
        foreach ($file in $backupfiles) {
            if ($file.CreationTime -le (Get-Date).AddDays(-5)) {
                try {
                    Write-Output "Delete old backup file $file ..."
                    Write-Output ''
                    $file.Delete()
                    $count = $count + 1
                } catch {
                    Write-Output "An error occurred while deleting old backup file $file >_<"
                    Write-Output '-------------------'
                    Write-Output $_
                    Write-Output '-------------------'
                }
            }
        }

        if ($count -ge 0) {
            Write-Output "Cleaned $count old backup files"
            Write-Output ''
        }
        else {
            Write-Output 'No old backup files need to clean up'
            Write-Output ''
        }

        Pause
  
        exit 0
  
    }
  
  
}


Salva lo script sopra come scriptname.ps1 nel percorso in cui desideri scaricare il backup. Prova “Esegui con Powershell”. Se ha successo, puoi procedere al passaggio successivo.

Per pianificare un’attività

  1. Cerca “Utilità di pianificazione”.
  2. Fai doppio clic su Aggiungi attività pianificata. Viene visualizzata la procedura guidata Utilità di pianificazione.
  3. Fai clic su Avanti, quindi fai clic su Sfoglia. Viene visualizzata la finestra di dialogo Seleziona programma da pianificare.
  4. Naviga fino allo script che hai creato, fai clic su di esso, quindi su Apri. Viene visualizzata la procedura guidata Utilità di pianificazione.
  5. Fornisci un nome per l’attività, o mantieni quello predefinito, che è il nome del file, specifica la frequenza di esecuzione dello script, quindi fai clic su Avanti.
  6. Specifica l’ora e la data di inizio (se hai specificato Giornaliero, Settimanale o Mensile, ecc.) e la ricorrenza, quindi fai clic su Avanti. Questa voce dovrebbe corrispondere al ciclo di backup automatico del tuo discourse
  7. Digita il nome utente e la password per l’account che eseguirà lo script, quindi fai clic su Avanti.
  8. Se desideri configurare proprietà avanzate, seleziona la casella di controllo, quindi fai clic su Fine.
15 Mi Piace

Un buon promemoria di quanto sia importante avere backup remoti. Anche un altro utente di Meta ha subito lo stesso problema qualche mese fa.

Una delle mie istanze utilizza la funzionalità di backup S3 integrata, le altre utilizzano Rclone e un’attività CRON per inviare i backup su Google Drive. C’è una guida per questo: Use rclone to sync backups to Dropbox or Google Drive

Grazie per aver condiviso il tuo script Linca :+1:

3 Mi Piace

Inoltre, un ottimo promemoria. Ho suggerito (qui) che la funzione di aggiornamento potesse verificare e avvisare se i file di backup hanno tempi di ultimo accesso troppo lontani nel passato. Aggiorniamo ogni due o tre mesi, quindi quel controllo non verrebbe eseguito troppo spesso, e il momento di un aggiornamento è un buon momento per essere sicuri che ci sia un backup sicuro. Qualsiasi mezzo per copiare un file di backup altrove dovrebbe aggiornare il timestamp dell’ultimo accesso.

3 Mi Piace

Ottimo punto, grazie per lo script. Lascia che condivida la versione di rsync :slight_smile: .

Nell’esempio seguente, sql e allegati vengono sincronizzati separatamente. Non è necessario includere gli allegati nel file di backup. Non è necessario eliminare nemmeno i vecchi backup.

Uso Chocolatey per installare cwrsync. Dopo l’installazione è sufficiente aggiungere alcune righe alla fine del file cmd + creare una pianificazione:

C:\ProgramData\chocolatey\lib\rsync\tools\cwrsync.cmd

Ad esempio:

rsync -rvm --delete --ignore-errors --ignore-existing --size-only --chmod=ugo=rwX -e "ssh -i /cygdrive/c/Users/user1/.ssh/id_rsa" login@host:/var/discourse/shared/standalone/backups/default/ /cygdrive/d/backup/forum/db/

rsync -rvm --delete --ignore-errors --ignore-existing --size-only --chmod=ugo=rwX -e "ssh -i /cygdrive/c/Users/user1/.ssh/id_rsa" login@host:/var/discourse/shared/standalone/uploads/ /cygdrive/d/backup/forum/uploads/

Nota 1: Usa /cygdrive/c/ invece di C:, leggi il file cmd per riferimento e sintassi.

Nota 2: Puoi modificare il comando per usare la password invece della chiave ssh (formato PEM)

Nota 3: Se non metti uno slash dopo la cartella dump/, rsync copierà la cartella, ma se lo fai, copierà solo il contenuto della cartella.

Nota 4: Se chocolatey aggiorna cwrsync, crea un backup del cmd precedente nella stessa cartella. Devi copiare manualmente i tuoi comandi nel nuovo cmd per continuare i backup.

Importante: Imposta la stessa regola nello Scheduler come scritto dall’OP. La riga dello scheduler è:

C:\ProgramData\chocolatey\lib\rsync\tools\cwrsync.cmd >> d:\backup\cwrsync.txt 2>&1

Aggiungerà l’output al file cwrsync.txt. Tutto qui.

3 Mi Piace

Ho l’abitudine di configurare rclone per copiare automaticamente i backup su un server remoto (un NAS self-hosted a casa) a causa della paranoia riguardo a questo tipo di eventi che accadono all’improvviso. Questo post serve molto bene come promemoria che non dovremmo mettere tutte le uova nello stesso paniere.

5 Mi Piace

Nel frattempo, dovresti anche ottenere una copia di tutto in /var/discourse/containers.

4 Mi Piace

Ottima idea! Distribuisco un aggiornamento

3 Mi Piace

Dove cercare “Scheduled Tasks”? (Principiante chiede consiglio, grazie)

“Scheduled Tasks” è l’Utilità di pianificazione, su win10 e versioni successive è sufficiente premere il tasto win e digitare per cercarla.

2 Mi Piace

Ciao. Come mai ricevo questo errore?

Per chiunque legga questo, ecco istruzioni migliori/più aggiornate poiché ho avuto qualche difficoltà con le istruzioni dell’OP:

  1. Crea/Usa una cartella in cui verrà archiviato questo script. Quindi, crea una cartella chiamata backup all’interno di quella cartella.

  2. Copia/incolla lo script in Blocco note. NOTA: Se usi un VPS, usa il nome utente del tuo VPS e l’indirizzo IP pubblico per la riga $ssh_address = \"username@your.site\". Salva come anyname.ps1 e non dimenticare di impostare il menu a discesa su “Tutti i file”, come mostrato di seguito.
    hhhh

  3. Premi il tasto Windows ⊊ e digita “Utilità di pianificazione”, quindi fai clic su “Utilità di pianificazione”.

  4. Sul lato destro, fai clic su “Crea attività di base”.

  5. Dai un nome/descrizione qualsiasi.

  6. Scegli se vuoi giornaliero/settimanale/annuale/ecc. Consiglio giornaliero.

  7. Imposta la data e l’ora in cui vuoi farlo. Mantieni Ricorrenza a 1. Assicurati di accedere alle impostazioni di Amministrazione del tuo sito Discourse > Backup. Seleziona la casella accanto a backup automatici abilitati.
    Quindi, imposta frequenza backup su quello che desideri. Consiglio 1 ma la chiave qui è farla corrispondere alle impostazioni dell’Utilità di pianificazione. Fai corrispondere le date di backup. Esempio: se imposti l’Utilità di pianificazione per il backup giornaliero, imposta le impostazioni di backup automatico di Amministrazione su 1.

  8. Lascia le impostazioni predefinite su “avvia un programma” e fai clic su Avanti.

  9. Fai clic su Sfoglia e trova lo script che hai salvato. Fai clic su Avanti.

  10. Fai clic su Fine.
    Se vuoi testarlo, fai clic con il pulsante destro del mouse sullo script e scegli “Esegui con Powershell”.

Nota: Se ricevi “impossibile trovare il file specificato”, inserisci la tua password come mostrato in PowerShell e la troverà comunque.

1 Mi Piace

Quando ho salvato lo script PS (ho semplicemente modificato il mio nome utente e il mio indirizzo IP nella seconda riga), e ho fatto clic destro > Esegui con PowerShell, non succede nulla.
Avviene un lampo. E se ho già un terminale aperto nel mio win11, quel terminale viene portato in primo piano. Nient’altro. Solo un lampo.

Mi stavo chiedendo, anche se ho fornito il mio nome utente e il mio indirizzo IP allo script, come avrebbe utilizzato la mia chiave SSH per accedere ed estrarre il backup?

Grazie.!

Ho provato sia la soluzione di OP che quella di 45thj5ej e nessuna delle due funziona per me. Eseguendo lo script con Powershell non trova “/backups/” e child item. Inoltre, non riesco a trovare dove OP intende che dovresti inserire il tuo nome utente e password. Sto eseguendo Discourse su un VPS.