giovedì 26 ottobre 2017

PowerShell: script per copiare files.

Windows PowerShell è una shell con un linguaggio di scripting avanzato, questa la definizione che dà Microsoft "Windows PowerShell™ is a new task-based command-line shell and scripting language designed especially for system administration".

In effetti è molto potente, quasi un linguaggio di programmazione vero e proprio.

Ho provato a creare uno script per risolvere un problema pratico: volevo copiare da una cartella sorgente il file più recente, con una certa estensione, in una cartella di destinazione (nota: nella cartella sorgente ci sono più file con la stessa estensione, ma voglio copiare solo l'ultimo in ordine di data).

Per spiegare con un esempio concreto: il software di backup delle macchine virtuali salva il full backup in una cartella (una differente per ogni job) su una NAS; ne tiene n copie come definito nel job di backup; voglio copiare il più recente su un disco esterno per poi tenerlo protetto in una cassaforte ignifuga.

Durante la costruzione dello script e i vari tentativi mi sono imbattuto in diversi problemi, poichè era la prima volta che usavo questo ambiente e non conoscevo bene le sue potenzialità.

Qui alcuni appunti utili:

Gestione errori:

il linguaggio consente l'utilizzo del costrutto try - catch per la gestione degli errori, ma questo funziona solo per le eccezioni; gli eventuali errori di esecuzione di un comando spesso non producono una eccezione ma solamente un messaggio di errore.

Per verificare se un comando è stato eseguito correttamente si deve controllare la variabile di sistema $? che restituisce i seguenti valori
  • $? = True  -> operazione eseguita correttamente
  • $? = False -> operazione eseguita con errori

inoltre $error è un array che contiene i messaggi di errore, l'ultimo si trova nel primo record $error[0].

Variabili globali

Se si vogliono usare variabili globali all'interno di una funzione bisogna anteporre "global:", per esempio in questo modo

$global:<nomevariabile>

Concatenazione di stringhe

Si può usare semplicemente il comando "+", esempio

$full_name = $path + $bkp + "\" + $latest.name

Inserire un fine riga in una stringa.

Si devono inserire questi caratteri: "`r`n"

Cancellare files

Usare Remove-Item <nome file>

Inviare mail

Si usa il comando Send-MailMessage

Attenzione che il corpo della mail è una stringa di testo, pertanto bisogna inserire i caratteri di fine riga per andare a capo e scrivere una mail su più righe.

questo lo script, evidenziati in azzurro i parametri da modificare

#----------------------------------------------------------------------+
# Script     : salva_bkp versione 1.0 del 10/10/2017                   |
#----------------------------------------------------------------------+
# Autore     : Fabio Giacobbe - 10/10/2017                             |
# Descrizione: Copia file più recente da cartella a cartella           |
#----------------------------------------------------------------------+
# Modifiche  :            by                                           |
# Note       :                                                         |
#----------------------------------------------------------------------+

# Variabili globali
$Lista_Errori = ""
$Invia_Mail = 0
$path = "<source_path>"       # Percorso base
$save_dir = "<dest_path>"     # Cartella destinazione
$est = ".<est>"               # Estensione dei file

# Variabili per invio mail
$From = "<mail-from>"
$To = "<mail-to>"
$Subject = "<oggetto mail>"
$Body = ""
$SMTPServer = "<smtp_server>"

#------------------------------------------------------------------------------
# CopyLastBackup : Copia il file più recente
#------------------------------------------------------------------------------
# input : Cartella sorgente
# return: nulla
#------------------------------------------------------------------------------
function CopyLastBackup ([string]$bkp)
{
    # Costruisco percorso completo con tipo "H:\percorso\cartella\*.est"
    $dir = $path + $bkp + "\*" + $est
    
    try
    {
        
        # costruisco una lista con tutti i file e ordino per data 
        $latest = Get-ChildItem -Path $dir | Sort-Object LastAccessTime -Descending | Select-Object -First 1
        if (-not $?) {
           $global:Invia_Mail = 1
           $Testo = "Errori salva Veeam BKP: " + $bkp + " - " + $error[0]
           $global:Lista_Errori = $global:Lista_Errori + $Testo +  "`r`n"
           return 1        
        }
        
        # costruisco il nome esatto del file da copiare
        $full_name = $path + $bkp + "\" + $latest.name
        
        # costruisco
        
        # Copia file nella cartella destinazione
        copy $full_name $save_dir
        if (-not $?) {
           $global:Invia_Mail = 1
           $Testo = "Errori salva Veeam BKP: " + $bkp + " - " + $error[0]
           $global:Lista_Errori = $global:Lista_Errori + $Testo +  "`r`n"
           return 1        
        }
        
    return 0;        
        
    }
    catch
    {
        $global:Invia_Mail = 1
        $Testo = "Errori salva Veeam BKP: " + $bkp + " - " + $error[0]
        $global:Lista_Errori = $global:Lista_Errori + $Testo +  "`r`n"
        return 1
    }
    
}

$Lista_elimina = $save_dir + '*' + $est

# Cancello tutti i fle dalla cartella destinazione
Remove-Item $Lista_elimina

# Chiamata alla funzione per copiare il file più recente
$ret = CopyLastBackup("<cartella1>")
$ret = CopyLastBackup("<cartella2>") 
$ret = CopyLastBackup("<cartella3>") 
<etc>

# se ci sono stati errori invio mail di avviso
if ($Invia_Mail -eq 1) {
  
  $Body = $Lista_Errori
  Send-MailMessage -From $From -to $To -Subject $Subject -Body $Body -SmtpServer $SMTPServer 
  
}  

exit
#------

Descrizione funzionamento:

Supponendo di avere i seguenti parametri:

percorso sorgente = F:\Backup
percorso destinazione = H:\Save
estensione = .vbk
Cartella backup = \VM1

nello script troveremo:

$path = "F:\Backup"       # Percorso base
$save_dir = "H:\Save"     # Cartella destinazione
$est = ".vbk"             # Estensione dei file

e la chiamata alla funzione

$ret = CopyLastBackup("VM1")

Lo script copierà il file più recente con estensione ".vbk" dalla cartella "F:\Backup\VM1" alla cartella "H:\Save".

In caso di errori o eccezioni viene inviata una mail di avviso (si devono impostare i parametri relativi).

Nessun commento:

Posta un commento