V1
This commit is contained in:
commit
ab17ec1e48
4 files changed
+520
No files matched your search
+83
@@ -0,0 +1,83 @@
|
||||
# Installation de wsl-manage
|
||||
|
||||
## 1. Placer les fichiers
|
||||
|
||||
Conservez les fichiers suivants dans un dossier permanent, par exemple :
|
||||
|
||||
```text
|
||||
E:\Drive\Apps\WSL\
|
||||
|-- wsl-manage.cmd
|
||||
|-- wsl-manage-core.ps1
|
||||
|-- README.md
|
||||
`-- Install.md
|
||||
```
|
||||
|
||||
Ne placez pas ce dossier dans un emplacement temporaire.
|
||||
|
||||
## 2. Ajouter le dossier au PATH
|
||||
|
||||
Ouvrez PowerShell et executez :
|
||||
|
||||
```powershell
|
||||
$userPath = [Environment]::GetEnvironmentVariable('Path', 'User')
|
||||
$installPath = 'E:\Drive\Apps\WSL'
|
||||
|
||||
if (($userPath -split ';') -notcontains $installPath) {
|
||||
[Environment]::SetEnvironmentVariable(
|
||||
'Path',
|
||||
(($userPath.TrimEnd(';') + ';' + $installPath).Trim(';')),
|
||||
'User'
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
Fermez puis ouvrez un nouveau terminal PowerShell pour que le changement soit
|
||||
pris en compte.
|
||||
|
||||
## 3. Verifier l'installation
|
||||
|
||||
Executez :
|
||||
|
||||
```powershell
|
||||
Get-Command wsl-manage
|
||||
```
|
||||
|
||||
La commande doit pointer vers :
|
||||
|
||||
```text
|
||||
E:\Drive\Apps\WSL\wsl-manage.cmd
|
||||
```
|
||||
|
||||
Affichez ensuite l'aide :
|
||||
|
||||
```powershell
|
||||
wsl-manage -?
|
||||
```
|
||||
|
||||
## 4. Utiliser le script
|
||||
|
||||
Sauvegarde par defaut :
|
||||
|
||||
```powershell
|
||||
wsl-manage
|
||||
```
|
||||
|
||||
Restauration :
|
||||
|
||||
```powershell
|
||||
wsl-manage restore
|
||||
```
|
||||
|
||||
## Depannage
|
||||
|
||||
Si PowerShell tente de charger directement un fichier `.ps1`, verifiez que le
|
||||
fichier public s'appelle bien `wsl-manage.cmd` et que seul le dossier
|
||||
d'installation est present dans le `PATH`.
|
||||
|
||||
Le lanceur utilise `-ExecutionPolicy Bypass` uniquement pour cette execution.
|
||||
Il n'est normalement pas necessaire de modifier la politique d'execution
|
||||
PowerShell du systeme.
|
||||
|
||||
L'execution en administrateur n'est pas requise pour une sauvegarde standard.
|
||||
Elle peut etre necessaire pour acceder a certains fichiers VHDX ou les
|
||||
compacter.
|
||||
@@ -0,0 +1,116 @@
|
||||
# wsl-manage
|
||||
|
||||
Outil PowerShell interactif de sauvegarde et de restauration des distributions WSL.
|
||||
Il gere aussi les donnees Docker Desktop lorsque la distribution `docker` ou
|
||||
`docker-desktop` est selectionnee.
|
||||
|
||||
## Fichiers
|
||||
|
||||
- `wsl-manage.cmd` : commande a lancer.
|
||||
- `wsl-manage-core.ps1` : implementation PowerShell.
|
||||
|
||||
Le dossier contenant ces fichiers doit etre dans le `PATH` Windows pour pouvoir
|
||||
lancer `wsl-manage` depuis n'importe quel terminal.
|
||||
|
||||
## Prerequis
|
||||
|
||||
- Windows avec WSL installe et accessible par `wsl.exe`.
|
||||
- PowerShell.
|
||||
- Docker Desktop doit etre completement arrete lorsqu'une sauvegarde ou une
|
||||
restauration Docker est concernee.
|
||||
- Le lecteur de destination doit etre accessible et disposer de suffisamment
|
||||
d'espace libre.
|
||||
|
||||
L'execution en administrateur n'est normalement pas necessaire. Elle peut etre
|
||||
necessaire pour acceder a certains fichiers VHDX ou effectuer un compactage.
|
||||
|
||||
## Sauvegarde
|
||||
|
||||
Lancer sans argument :
|
||||
|
||||
```powershell
|
||||
wsl-manage
|
||||
```
|
||||
|
||||
Le script :
|
||||
|
||||
1. Liste les distributions WSL disponibles.
|
||||
2. Demande de sauvegarder toutes les distributions ou une seule.
|
||||
3. Demande le lecteur de destination et affiche son espace libre.
|
||||
4. Demande confirmation.
|
||||
5. Arrete WSL avec `wsl --shutdown`.
|
||||
6. Exporte les distributions selectionnees au format `.tar`.
|
||||
7. Affiche une progression estimee et le temps ecoule.
|
||||
|
||||
Les sauvegardes sont rangees dans un dossier date sous `WSL-Backup` :
|
||||
|
||||
```text
|
||||
D:\WSL-Backup\2026-09-16_20-05-42\
|
||||
|-- Ubuntu.tar
|
||||
|-- Debian.tar
|
||||
`-- ...
|
||||
```
|
||||
|
||||
Le pourcentage affiche est une estimation basee sur l'espace utilise par la
|
||||
distribution. `wsl.exe --export` ne fournit pas de progression native.
|
||||
|
||||
## Donnees Docker Desktop
|
||||
|
||||
Si `docker` ou `docker-desktop` est selectionne, le script :
|
||||
|
||||
1. Verifie que Docker Desktop est arrete.
|
||||
2. Demande le chemin des donnees Docker.
|
||||
3. Utilise par defaut :
|
||||
|
||||
```text
|
||||
E:\WSL\Docker\desktop-data
|
||||
```
|
||||
|
||||
4. Verifie la presence des dossiers `disk` et `main`.
|
||||
5. Copie ces dossiers dans :
|
||||
|
||||
```text
|
||||
D:\WSL-Backup\2026-09-16_20-05-42\Docker\
|
||||
|-- disk\
|
||||
`-- main\
|
||||
```
|
||||
|
||||
La distribution `docker-desktop` exportee en `.tar` contient principalement
|
||||
les fichiers systeme. Les images, conteneurs et volumes Docker sont dans les
|
||||
donnees `disk` et `main`.
|
||||
|
||||
## Restauration
|
||||
|
||||
Lancer avec l'argument `restore` :
|
||||
|
||||
```powershell
|
||||
wsl-manage restore
|
||||
```
|
||||
|
||||
Le script :
|
||||
|
||||
1. Demande le lecteur contenant `WSL-Backup`.
|
||||
2. Demande la date de sauvegarde.
|
||||
3. Demande une distribution ou `Toutes les machines`.
|
||||
4. Demande confirmation apres recapitulatif.
|
||||
5. Arrete WSL.
|
||||
6. Importe les distributions sous `WSL-Install\DATE`.
|
||||
7. Restaure les donnees Docker uniquement si `docker` ou `docker-desktop` est
|
||||
selectionne.
|
||||
|
||||
Une distribution restauree porte le nom de son fichier sans extension :
|
||||
|
||||
```text
|
||||
Ubuntu.tar -> Ubuntu
|
||||
```
|
||||
|
||||
Le dossier d'installation d'une distribution ne doit pas deja exister.
|
||||
|
||||
## Conseils
|
||||
|
||||
- Quitter Docker Desktop depuis son icone de notification avant une operation
|
||||
Docker.
|
||||
- Ne pas interrompre la copie des fichiers VHDX.
|
||||
- Conserver une copie de secours des donnees Docker avant restauration.
|
||||
- Les anciennes sauvegardes ne contenant pas de dossier `Docker` ne permettent
|
||||
pas de restaurer les donnees Docker.
|
||||
@@ -0,0 +1,318 @@
|
||||
# Gestion interactive des distributions WSL.
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[ValidateSet('backup', 'restore')]
|
||||
[string]$Mode = 'backup'
|
||||
)
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
function Stop-WithMessage {
|
||||
param([string]$Message)
|
||||
Write-Error $Message
|
||||
exit 1
|
||||
}
|
||||
|
||||
if (-not (Get-Command wsl.exe -ErrorAction SilentlyContinue)) {
|
||||
Stop-WithMessage 'wsl.exe est introuvable. Lancez ce script depuis Windows avec WSL installe.'
|
||||
}
|
||||
|
||||
function Invoke-Wsl {
|
||||
param([string[]]$Arguments)
|
||||
|
||||
$output = & wsl.exe @Arguments 2>&1
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
$details = (($output | ForEach-Object { $_.ToString() }) -join ' ').Trim()
|
||||
if (-not $details) { $details = 'aucun detail fourni par wsl.exe' }
|
||||
throw ('wsl.exe a retourne le code {0} : {1}' -f $LASTEXITCODE, $details)
|
||||
}
|
||||
return $output
|
||||
}
|
||||
|
||||
function Get-Distros {
|
||||
@(Invoke-Wsl @('--list', '--quiet') | ForEach-Object {
|
||||
($_.ToString() -replace '\x00', '').Trim()
|
||||
} | Where-Object { $_ })
|
||||
}
|
||||
|
||||
function Select-Drive {
|
||||
$drives = @(Get-PSDrive -PSProvider FileSystem | Where-Object {
|
||||
$_.Root -and (Test-Path -LiteralPath $_.Root)
|
||||
} | Sort-Object Name)
|
||||
|
||||
if ($drives.Count -eq 0) {
|
||||
Stop-WithMessage 'Aucun disque accessible n''a ete trouve.'
|
||||
}
|
||||
|
||||
Write-Host ''
|
||||
Write-Host 'Disques disponibles :' -ForegroundColor Cyan
|
||||
for ($i = 0; $i -lt $drives.Count; $i++) {
|
||||
$drive = New-Object -TypeName System.IO.DriveInfo -ArgumentList $drives[$i].Root
|
||||
$free = '{0:N2} Go libres' -f ($drive.AvailableFreeSpace / 1GB)
|
||||
Write-Host ('[{0}] {1} ({2}) - {3}' -f ($i + 1), $drives[$i].Name, $drives[$i].Root, $free)
|
||||
}
|
||||
|
||||
$selection = Read-Host ('Choisissez le disque (1-{0})' -f $drives.Count)
|
||||
$driveIndex = 0
|
||||
if (-not [int]::TryParse($selection, [ref]$driveIndex) -or
|
||||
$driveIndex -lt 1 -or $driveIndex -gt $drives.Count) {
|
||||
Stop-WithMessage 'Selection de disque invalide.'
|
||||
}
|
||||
return $drives[$driveIndex - 1]
|
||||
}
|
||||
|
||||
function Confirm-Action {
|
||||
param([string]$Message)
|
||||
$answer = Read-Host "$Message (o/n)"
|
||||
return $answer -match '^(o|oui|y|yes)$'
|
||||
}
|
||||
|
||||
function Get-DockerDataPath {
|
||||
param([bool]$RequireData)
|
||||
$defaultPath = 'E:\WSL\Docker\desktop-data'
|
||||
$path = Read-Host ('Chemin des donnees Docker Desktop [{0}]' -f $defaultPath)
|
||||
if (-not $path) { $path = $defaultPath }
|
||||
$path = [IO.Path]::GetFullPath($path)
|
||||
if ($RequireData -and (-not (Test-Path -LiteralPath (Join-Path $path 'disk')) -or
|
||||
-not (Test-Path -LiteralPath (Join-Path $path 'main')))) {
|
||||
Stop-WithMessage ('Le chemin Docker doit contenir les dossiers disk et main : {0}' -f $path)
|
||||
}
|
||||
if (-not $RequireData -and -not (Test-Path -LiteralPath $path)) {
|
||||
New-Item -ItemType Directory -Path $path -Force | Out-Null
|
||||
}
|
||||
return $path
|
||||
}
|
||||
|
||||
function Assert-DockerStopped {
|
||||
$dockerProcesses = @(Get-Process -ErrorAction SilentlyContinue | Where-Object {
|
||||
$_.ProcessName -in @('Docker Desktop', 'com.docker.backend', 'com.docker.proxy', 'com.docker.build')
|
||||
})
|
||||
if ($dockerProcesses.Count -gt 0) {
|
||||
Stop-WithMessage 'Docker Desktop est encore en cours d''execution. Quittez-le completement puis relancez la commande.'
|
||||
}
|
||||
}
|
||||
|
||||
function Copy-DockerData {
|
||||
param([string]$SourceRoot, [string]$DestinationRoot)
|
||||
New-Item -ItemType Directory -Path $DestinationRoot -Force | Out-Null
|
||||
foreach ($folder in @('disk', 'main')) {
|
||||
$source = Join-Path $SourceRoot $folder
|
||||
$destination = Join-Path $DestinationRoot $folder
|
||||
New-Item -ItemType Directory -Path $destination -Force | Out-Null
|
||||
& robocopy.exe $source $destination /E /COPY:DAT /DCOPY:DAT /R:2 /W:2 /XJ
|
||||
if ($LASTEXITCODE -gt 7) {
|
||||
throw ('La copie Docker a echoue pour {0} (code robocopy {1}).' -f $folder, $LASTEXITCODE)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function Get-DistroSize {
|
||||
param([string]$Distro)
|
||||
try {
|
||||
$sizeOutput = & wsl.exe --distribution $Distro -- df -B1 --output=used / 2>$null
|
||||
$value = @($sizeOutput | ForEach-Object { $_.ToString() -replace '\x00', '' } |
|
||||
Where-Object { $_ -match '^\s*\d+\s*$' } | Select-Object -Last 1)
|
||||
if ($value) { return [int64]$value.Trim() }
|
||||
} catch { }
|
||||
return 0
|
||||
}
|
||||
|
||||
function Export-Distro {
|
||||
param(
|
||||
[string]$Distro,
|
||||
[string]$Archive,
|
||||
[int64]$EstimatedBytes
|
||||
)
|
||||
|
||||
$psi = New-Object System.Diagnostics.ProcessStartInfo
|
||||
$psi.FileName = 'wsl.exe'
|
||||
$psi.Arguments = '--export "' + $Distro.Replace('"', '\"') + '" "' + $Archive.Replace('"', '\"') + '"'
|
||||
$psi.UseShellExecute = $false
|
||||
$psi.CreateNoWindow = $true
|
||||
$psi.RedirectStandardOutput = $true
|
||||
$psi.RedirectStandardError = $true
|
||||
$process = New-Object System.Diagnostics.Process
|
||||
$process.StartInfo = $psi
|
||||
[void]$process.Start()
|
||||
$stdoutTask = $process.StandardOutput.ReadToEndAsync()
|
||||
$stderrTask = $process.StandardError.ReadToEndAsync()
|
||||
$started = Get-Date
|
||||
do {
|
||||
Start-Sleep -Milliseconds 500
|
||||
$percent = 0
|
||||
if ($EstimatedBytes -gt 0 -and (Test-Path -LiteralPath $Archive)) {
|
||||
$percent = [math]::Min(99, [int](100 * ((Get-Item -LiteralPath $Archive).Length / $EstimatedBytes)))
|
||||
}
|
||||
$elapsed = ((Get-Date) - $started).ToString('hh\:mm\:ss')
|
||||
Write-Progress -Activity ('Export de {0}' -f $Distro) -Status ('{0}% - {1} ecoule' -f $percent, $elapsed) -PercentComplete $percent
|
||||
} while (-not $process.HasExited)
|
||||
$process.WaitForExit()
|
||||
Write-Progress -Activity ('Export de {0}' -f $Distro) -Completed
|
||||
if ($process.ExitCode -ne 0) {
|
||||
$details = $stderrTask.Result.Trim()
|
||||
if (-not $details) { $details = 'aucun detail fourni par wsl.exe' }
|
||||
throw ('wsl.exe a retourne le code {0} : {1}' -f $process.ExitCode, $details)
|
||||
}
|
||||
}
|
||||
|
||||
if ($Mode -eq 'restore') {
|
||||
$drive = Select-Drive
|
||||
$backupRoot = Join-Path $drive.Root 'WSL-Backup'
|
||||
$dates = @(Get-ChildItem -LiteralPath $backupRoot -Directory -ErrorAction SilentlyContinue |
|
||||
Sort-Object Name -Descending)
|
||||
if ($dates.Count -eq 0) {
|
||||
Stop-WithMessage ('Aucune sauvegarde trouvee dans {0}.' -f $backupRoot)
|
||||
}
|
||||
|
||||
Write-Host ''
|
||||
Write-Host 'Sauvegardes disponibles :' -ForegroundColor Cyan
|
||||
for ($i = 0; $i -lt $dates.Count; $i++) {
|
||||
Write-Host ('[{0}] {1}' -f ($i + 1), $dates[$i].Name)
|
||||
}
|
||||
$dateSelection = Read-Host ('Choisissez une date (1-{0})' -f $dates.Count)
|
||||
$dateIndex = 0
|
||||
if (-not [int]::TryParse($dateSelection, [ref]$dateIndex) -or
|
||||
$dateIndex -lt 1 -or $dateIndex -gt $dates.Count) {
|
||||
Stop-WithMessage 'Selection de date invalide.'
|
||||
}
|
||||
$dateFolder = $dates[$dateIndex - 1]
|
||||
$dockerBackupPath = Join-Path $dateFolder.FullName 'Docker'
|
||||
$archives = @(Get-ChildItem -LiteralPath $dateFolder.FullName -File |
|
||||
Where-Object { $_.Name -match '\.tar(\.gz|\.xz)?$' } | Sort-Object Name)
|
||||
if ($archives.Count -eq 0) {
|
||||
Stop-WithMessage 'Cette sauvegarde ne contient aucune archive exploitable.'
|
||||
}
|
||||
|
||||
Write-Host ''
|
||||
Write-Host 'Machines disponibles :' -ForegroundColor Cyan
|
||||
Write-Host '[1] Toutes les machines'
|
||||
for ($i = 0; $i -lt $archives.Count; $i++) {
|
||||
Write-Host ('[{0}] {1}' -f ($i + 2), $archives[$i].Name)
|
||||
}
|
||||
$machineSelection = Read-Host ('Choisissez une machine (1-{0})' -f ($archives.Count + 1))
|
||||
$machineIndex = 0
|
||||
if (-not [int]::TryParse($machineSelection, [ref]$machineIndex) -or
|
||||
$machineIndex -lt 1 -or $machineIndex -gt ($archives.Count + 1)) {
|
||||
Stop-WithMessage 'Selection de machine invalide.'
|
||||
}
|
||||
if ($machineIndex -eq 1) { $selectedArchives = $archives } else { $selectedArchives = @($archives[$machineIndex - 2]) }
|
||||
|
||||
$restoreDocker = @($selectedArchives | Where-Object {
|
||||
(($_.Name -replace '\.tar(\.gz|\.xz)?$', '') -ieq 'docker' -or
|
||||
($_.Name -replace '\.tar(\.gz|\.xz)?$', '') -ieq 'docker-desktop')
|
||||
}).Count -gt 0
|
||||
if ($restoreDocker) {
|
||||
if (-not (Test-Path -LiteralPath (Join-Path $dockerBackupPath 'disk')) -or
|
||||
-not (Test-Path -LiteralPath (Join-Path $dockerBackupPath 'main'))) {
|
||||
Stop-WithMessage 'Cette sauvegarde ne contient pas les donnees Docker (disk et main).'
|
||||
}
|
||||
Assert-DockerStopped
|
||||
$dockerDataPath = Get-DockerDataPath $false
|
||||
}
|
||||
|
||||
Write-Host ''
|
||||
Write-Host 'Recapitulatif :' -ForegroundColor Cyan
|
||||
Write-Host (' Date : {0}' -f $dateFolder.Name)
|
||||
Write-Host (' Machine(s) : {0}' -f (($selectedArchives | ForEach-Object { $_.BaseName -replace '\.tar$' }) -join ', '))
|
||||
if ($restoreDocker) { Write-Host (' Donnees Docker : {0}' -f $dockerDataPath) }
|
||||
Write-Host (' Lecteur : {0}' -f $drive.Root)
|
||||
if (-not (Confirm-Action 'Lancer la restauration')) { Write-Host 'Operation annulee.'; exit 0 }
|
||||
|
||||
try { Invoke-Wsl @('--shutdown') | Out-Null } catch { Stop-WithMessage ('Impossible d''arreter WSL : {0}' -f $_.Exception.Message) }
|
||||
if ($restoreDocker) { try {
|
||||
Copy-DockerData -SourceRoot $dockerBackupPath -DestinationRoot $dockerDataPath
|
||||
Write-Host 'Donnees Docker restaurees.' -ForegroundColor Green
|
||||
} catch { Stop-WithMessage ('Restauration Docker impossible : {0}' -f $_.Exception.Message) } }
|
||||
$failed = @()
|
||||
$installRoot = Join-Path $drive.Root ('WSL-Install\' + $dateFolder.Name)
|
||||
New-Item -ItemType Directory -Path $installRoot -Force | Out-Null
|
||||
foreach ($archive in $selectedArchives) {
|
||||
$name = $archive.Name -replace '\.tar(\.gz|\.xz)?$', ''
|
||||
$installPath = Join-Path $installRoot $name
|
||||
try {
|
||||
if (Test-Path -LiteralPath $installPath) {
|
||||
throw ('Le dossier d''installation existe deja : {0}' -f $installPath)
|
||||
}
|
||||
Invoke-Wsl @('--import', $name, $installPath, $archive.FullName) | Out-Null
|
||||
Write-Host ('Restauration OK : {0}' -f $name) -ForegroundColor Green
|
||||
} catch { $failed += $name; Write-Warning ('Echec pour {0} : {1}' -f $name, $_.Exception.Message) }
|
||||
}
|
||||
if ($failed.Count -gt 0) { Stop-WithMessage ('Restauration terminee avec erreurs : {0}' -f ($failed -join ', ')) }
|
||||
Write-Host 'Restauration terminee avec succes.' -ForegroundColor Green
|
||||
exit 0
|
||||
}
|
||||
|
||||
$distros = Get-Distros
|
||||
|
||||
if ($distros.Count -eq 0) {
|
||||
Stop-WithMessage 'Aucune distribution WSL n''a ete trouvee.'
|
||||
}
|
||||
|
||||
Write-Host ''
|
||||
Write-Host 'Distributions a sauvegarder :' -ForegroundColor Cyan
|
||||
Write-Host '[1] Toutes les distributions'
|
||||
for ($i = 0; $i -lt $distros.Count; $i++) {
|
||||
Write-Host ('[{0}] {1}' -f ($i + 2), $distros[$i])
|
||||
}
|
||||
$distroSelection = Read-Host ('Choisissez une option (1-{0})' -f ($distros.Count + 1))
|
||||
$distroIndex = 0
|
||||
if (-not [int]::TryParse($distroSelection, [ref]$distroIndex) -or
|
||||
$distroIndex -lt 1 -or $distroIndex -gt ($distros.Count + 1)) {
|
||||
Stop-WithMessage 'Selection de distribution invalide.'
|
||||
}
|
||||
if ($distroIndex -eq 1) { $selectedDistros = $distros } else { $selectedDistros = @($distros[$distroIndex - 2]) }
|
||||
|
||||
$includeDockerData = @($selectedDistros | Where-Object {
|
||||
$_ -ieq 'docker' -or $_ -ieq 'docker-desktop'
|
||||
}).Count -gt 0
|
||||
if ($includeDockerData) {
|
||||
Assert-DockerStopped
|
||||
$dockerDataPath = Get-DockerDataPath $true
|
||||
}
|
||||
|
||||
$drive = Select-Drive
|
||||
$backupRoot = Join-Path -Path $drive.Root -ChildPath 'WSL-Backup'
|
||||
$backupFolder = Join-Path -Path $backupRoot -ChildPath (Get-Date -Format 'yyyy-MM-dd_HH-mm-ss')
|
||||
New-Item -ItemType Directory -Path $backupFolder -Force | Out-Null
|
||||
Write-Host ('Sauvegarde dans : {0}' -f $backupFolder) -ForegroundColor Green
|
||||
Write-Host ('Distributions : {0}' -f ($selectedDistros -join ', '))
|
||||
$freeSpace = New-Object -TypeName System.IO.DriveInfo -ArgumentList $drive.Root
|
||||
Write-Host ('Espace libre : {0:N2} Go' -f ($freeSpace.AvailableFreeSpace / 1GB)) -ForegroundColor Cyan
|
||||
$estimatedSizes = @{}
|
||||
foreach ($distro in $selectedDistros) { $estimatedSizes[$distro] = Get-DistroSize $distro }
|
||||
if (-not (Confirm-Action 'Lancer la sauvegarde')) { Remove-Item -LiteralPath $backupFolder -Force; Write-Host 'Operation annulee.'; exit 0 }
|
||||
|
||||
try { Invoke-Wsl @('--shutdown') | Out-Null } catch { Stop-WithMessage ('Impossible d''arreter WSL : {0}' -f $_.Exception.Message) }
|
||||
|
||||
if ($includeDockerData) {
|
||||
$dockerBackupPath = Join-Path $backupFolder 'Docker'
|
||||
try {
|
||||
Copy-DockerData -SourceRoot $dockerDataPath -DestinationRoot $dockerBackupPath
|
||||
Write-Host ('Donnees Docker sauvegardees dans : {0}' -f $dockerBackupPath) -ForegroundColor Green
|
||||
} catch {
|
||||
Stop-WithMessage ('Sauvegarde Docker impossible : {0}' -f $_.Exception.Message)
|
||||
}
|
||||
}
|
||||
|
||||
$failed = @()
|
||||
foreach ($distro in $selectedDistros) {
|
||||
$archive = Join-Path -Path $backupFolder -ChildPath ($distro + '.tar')
|
||||
Write-Host ('Export de {0}...' -f $distro) -ForegroundColor Yellow
|
||||
|
||||
try {
|
||||
Export-Distro -Distro $distro -Archive $archive -EstimatedBytes $estimatedSizes[$distro]
|
||||
Write-Host (' OK : {0}' -f $archive) -ForegroundColor Green
|
||||
}
|
||||
catch {
|
||||
$failed += $distro
|
||||
Write-Warning ('Echec pour {0} : {1}' -f $distro, $_.Exception.Message)
|
||||
}
|
||||
}
|
||||
|
||||
if ($failed.Count -gt 0) {
|
||||
Write-Warning ('Sauvegarde terminee avec des erreurs : {0}' -f ($failed -join ', '))
|
||||
exit 1
|
||||
}
|
||||
|
||||
Write-Host ''
|
||||
Write-Host 'Sauvegarde terminee avec succes.' -ForegroundColor Green
|
||||
@@ -0,0 +1,3 @@
|
||||
@echo off
|
||||
chcp 65001 >nul
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File "%~dp0wsl-manage-core.ps1" %*
|
||||
Reference in new issue
Block a user