param ( [cmdletbinding()] [string]$conf= "", [switch]$debug = $false, [switch]$log = $false ) Set-StrictMode -Version 2 #$PSDefaultParameterValues['Out-File:Encoding'] = 'utf8' #$OutputEncoding = [console]::InputEncoding = [console]::OutputEncoding = New-Object System.Text.UTF8Encoding $net_default_letter = "S" $global:logfile = $false $tmp_path = "$PSScriptRoot\tmp" $global:bin_path = "$PSScriptRoot\bin" $ProgressPreference = "SilentlyContinue" $ErrorActionPreference = "Stop" $DebugPreference = "SilentlyContinue" if ( $debug ) { $DebugPreference = "Continue" } Import-Module -Name "$PSScriptRoot\lib\backupscript-global_utils.psm1" -Scope Global -Force function json_to_hash () { [CmdletBinding()] Param( [Parameter( Mandatory=$True, ValueFromPipeline=$True )] $json ) Write-Debug "Call json_to_hash with $json" $r = @{} $json.psobject.properties | Foreach { Write-Debug "Found value $_" $r[$_.Name] = $_.Value } Write-debug "End json_to_hash" return $r } function eval_var () { [CmdletBinding()] Param( [Parameter(Mandatory=$True)] [string] $var ) Write-Debug "$var Need to be evaluated" $var = $ExecutionContext.InvokeCommand.ExpandString($var) Write-Debug "Result $var" return $var } if ( -not $conf ) { $conf = "$PSScriptRoot\etc\backup.json" Write-Debug "Configuration file not provided, use $conf" } if ( $log ) { $logname = (Get-Item $conf ).Basename $global:logfile = "$PSScriptRoot\log\$((Get-Date).ToString("yyyy.MM.dd"))_$($logname).log" write-debug "Write to logfile: $($global:logfile) " # Zip old messah=ges (Archives) # TODO: Test this functionnality if ( Test-Path "$($PSScriptRoot)/bin/7za.exe") { $command = -join( $PSScriptRoot, "/bin/7za.exe", " u") Write-Debug " Archive old loh file with $($command)" # Select Set-Message file older than 15 days Get-ChildItem "$($PSScriptRoot)\log\*$($logname).log" -Recurse -File | Where CreationTime -lt (Get-Date).AddDays(-15) | % { # Put file in the right zip file by name $execute = -join( $command, " `"", $PSScriptRoot, "\log\", $logname, ".archives.", ($_.CreationTime).ToString("yyyy.MM"), ".log.7z`"", " `"", $_.FullName, "`"" ) write-debug "Set-Message command archive: $($execute)" try { Invoke-Expression $execute | Out-Null Remove-Item -Path $_.FullName } catch { Set-Message "WARNING" "Can't zip $($_.Fullname) log files" } } } } Write-Debug "Loaded script from $PSScriptRoot" # Temporary directory creation / clean if ( Test-Path $tmp_path ) { Write-Debug "Remove file in $tmp_path" Remove-Item -Path $tmp_path\* -recurse -Force } else { Write-Debug "Create directory $tmp_path" New-Item -ItemType Directory -Force -Path $tmp_path } # Parse JSON try { $backup = Get-Content $(Get-ChildItem $conf -).FullName -Raw | ConvertFrom-Json } catch { Set-Error "Error While Loading JSON : $conf" exit } Write-Debug "configuration $conf loaded successfully" $backup.actions | % { $destination = "" $source = "" Set-Message "---" Set-Message "Process action : $($_.name) | type: $($_.type)" Set-Message "---" # Process source if ( $_.psobject.properties.match('source_eval').Count -and $_.source_eval -eq $true ) { $_.source = eval_var $($_.source) Write-Debug "Result $($_.source)" } if ( $_.source -eq "{{tmpdir}}" ) { Write-Debug "source is the temp directory" $source = $tmp_path } elseif ( -not (Test-Path $_.source) -and $_.source ) { Set-Message "Source path $($_.source) not found `n`n" continue } else { Write-Debug "Source is a regular directory" $source = $_.source } # Test output path if ( $_.dest -match "^\\.*$"){ Write-Debug "Destination is a network path" if ( -not $_.username -or -not $_.pass ) { Set-Error "you must specify a username and a password" return } #Mount Network Drive $cred = New-Object System.Management.Automation.PSCredential($_.username, ($_.pass | ConvertTo-SecureString)) try { # get-psdrive # Use Securestring to secure Password # get secured password : # ("Passw00rd" | ConvertTo-SecureString -AsPlainText -Force | ConvertFrom-SecureString) New-PSDrive -Credential $cred -Name $net_default_letter -Root $($_.dest) -PSProvider FileSystem -Persist -Scope Script -ErrorAction Stop | Out-Null $destination = "$($net_default_letter):" } catch { Set-Error "Can't mount the network share" Write-Debug $error[0].Exception return } } elseif ( $_.dest -eq "{{tmpdir}}" ){ Write-Debug "Destination is the temporary folder ($tmp_path)" $destination = $tmp_path } else { Write-Debug "$($_.dest) seems to le a local path" if ( Test-Path $_.dest ) { $destination = $_.dest } else { Set-Error "Destination '$($_.dest)' doest not exit" return } } Write-Debug "Begin backup of $($_.name)" if ( $_.psobject.Properties.Name -contains "options") { $opt = $_.options | json_to_hash } else{ $opt = $false } try { Write-Debug "Import module $($_.type)" Import-Module -Name "$PSScriptRoot\lib\backupscript-$($_.type).psm1" Backup-Create -source $source -dest $destination -name $_.name -opt $opt if ( $_.psobject.properties.match('hook_postexec').Count -and $_.hook_postexec -ne "" ) { Set-Message "Postexec hook : execute $($_.hook_postexec)" Invoke-Expression $_.hook_postexec } } catch { Set-Error $Error[0].FullyQualifiedErrorId } finally{ # Properly remove net drive if mounted if ( Test-Path "$($net_default_letter):" ){ Remove-PSDrive -Name $net_default_letter } # Remove Module Get-Module -Name "backupscript-$($_.type)" | Remove-Module -Force } } Set-Message "Backup operation done"