août
2009
Bonsoir à tous.
Comme beaucoup, je sauvegarde régulièrement mes données. Pour faciliter cette tache plutôt contraignante, j’ai entrepris de développer un script PowerShell. Mon cahier des charges était le suivant :
- Les données devront être sauvegardés dans des volumes virtuels VHD (exigence de perennité –> standard)
- Les données non modifiés ne devront pas être réécrites (exigence de performance)
- Seul les outils disponibles en standard dans Windows 7 devront être utilisés (exigence de gratuité et de portabilité)
Je crois que j’ai réussi mon pari . Comme le script me semble plutôt sympa, je vous le met à disposition dans l’espoir qu’il vous soit profitable. Il ne fonctionne qu’avec Windows 7.
Voici les deux fonctions en question :
{
param([array]$commands)
$tempfile = [System.IO.Path]::GetTempFileName()
foreach ($com in $commands)
{
Add-Content $tempfile $com
}
$output = DiskPart /s $tempfile
Remove-Item $tempfile
$output
}
function Start-VhdBackup
{
param([string]$sourceVolume = $(throw "Vous devez spécifier le nom du volume à sauvegarder (source)"),
[string]$destinationVolume = $(throw "Vous devez spécifier le nom du volume VHD une fois monté (destination)"),
[string]$backupVolume = $(throw "Vous devez spécifier le nom du volume contenant le fichier VHD à monter"),
[string]$vdiskPath = $(throw "Vous devez spécifier le chemin du fichier VHD à monter"),
[string]$logPath = $(throw "Vous devez spécifier le chemin du fichier log qui sera généré lors des opérations de sauvegarde"))
$sourceID = (Get-WmiObject Win32_LogicalDisk | Where-Object { $_.VolumeName -eq $sourceVolume }).DeviceID
$backupID = (Get-WmiObject Win32_LogicalDisk | Where-Object { $_.VolumeName -eq $backupVolume }).DeviceID
if (($sourceID -eq $null) -or ($backupID -eq $null))
{
Write-Host "Volume '$sourceVolume' ou '$backupVolume' introuvable !"
}
else
{
Run-DiskPart "select vdisk file=$backupID\$vdiskPath", "attach vdisk"
Start-Sleep -m 3000
$destID = (Get-WmiObject Win32_LogicalDisk | Where-Object { $_.VolumeName -eq $destinationVolume }).DeviceID
if ($destID -eq $null)
{
Write-Host "Volume '$destinationVolume' introuvable !"
}
else
{
&robocopy $sourceID $destID /mir /log:"$logPath" /np /xd *"System Volume Information" *RECYCLER $*
Run-DiskPart "select vdisk file=$backupID\$vdiskPath", "detach vdisk"
}
}
}
Comme vous pouvez le constater, j’utilise l’utilitaire en ligne de commande « DiskPart » pour monter et démonter les fichiers VHD dans le système de fichiers. Ceci implique de lancer ce script avec des privilèges administrateurs. Le script ne crée pas le volume virtuel. Il reviendra à l’utilisateur de le générer préalablement soit avec l’outil DiskPart, soit à l’aide de la console MMC « gestion des disques ». Créez de préférence un volume avec une taille dynamique ; ainsi, la taille du fichier VHD s’adaptera automatiquement au volume de données à sauvegarder.
Le script se fie au nom des volumes plutôt qu’à leur lettre d’accès (d:, d:, etc.). Cela permet d’améliorer la fiabilité du script car un volume amovible peut se voir attribuer des lettres différentes selon les circonstances, comme la présence ou non d’un lecteur de carte mémoire.
La copie proprement dite se fait grâce à l’outil RoboCopy qui permet de synchroniser le contenu de deux répertoires.
Il suffit alors d’appeler la méthode Start-VhdBackup avec les paramètres adéquats pour lancer les opérations de sauvegarde :
$sourceVolume = "Documents"
$destinationVolume = "Documents 2"
$backupVolume = "Backup"
$vdiskPath = "CyberSinh\Documents.vhd"
$logPath = "$exec\backup_documents.log"
Get-Process | Where-Object { $_.ProcessName -eq "firefox" } | Stop-Process
Get-Process | Where-Object { $_.ProcessName -eq "thunderbird" } | Stop-Process
Start-VhdBackup $sourceVolume $destinationVolume $backupVolume $vdiskPath $logPath
J’ai ajouté deux commandes pour fermer Firefox et Thunderbird préalablement à la sauvegarde, et permettre ainsi la copie des fichiers qu’ils verrouillent lorsque ces logiciels sont lancés.
Au final, un script très simple mais très pratique.
Pour ceux qui trouvent mes scripts PowerShell utiles, sachez que sont également disponibles des scripts pour transcoder les fichiers audio Wave, Ogg Vorbis, FLAC et Speex.
Salut,
une petite remarque sur le nom de fonction. Il est préférable d’utiliser le verbe Invoke en lieu et place du verbe Run.
Ensuite on peut filtrer les objets coté WMI et non plus coté PowerShell, ce qui limite les échanges :
$NomDeVolume="primaire" <br />
measure-command{(Get-WmiObject Win32_LogicalDisk | Where-Object { $_.VolumeName -eq $NomDeVolume}).DeviceID} <br />
measure-command{(Get-WmiObject Win32_LogicalDisk -filter "VolumeName='$NomDeVolume'").DeviceID} <br />
Et enfin le cas où 2 disques portent le même nom de volume n’est pas pris en compte.