This is a simple PowerShell script which wraps calls to rdiff-backup
with the mounting/dismounting (or connecting/disconnecting) of the backup destination.
This is the same utility as rdiff-backup-wrapper
, but adapted to a Windows environment.
Just like rdiff-backup-wrapper
: I find it useful to keep the system’s backup destination offline (at least from the point of view of the backup source environment, i.e. unmounted) most of the time, significantly reducing the risk of unauthorized access to or accidental corruption of the backups. This makes particular sense in the case the backup destination is local to the backup source.
The script will first connect the system to the backup destination through a "mount" procedure (e.g. the mounting of a local disk or the connecting to a remote one), then, if successful, use rdiff-backup
to delete old backup increments and perform a new backup, and finally "dismount" (e.g. unmount or disconnect) the backup destination.
It also offers a couple of reusable PowerShell modules which could also be useful on their own:
RdiffBackup
module-
A layer of abstraction to help calling Windows or WSL
rdiff-backup
executables from PowerShell. It notably allows dynamically switching between several executables (e.g. installed side-by-side) selecting them at call time through a parameter. It also automatically sets necessary (e.g. for bug workaround) or sensible options according to the version of the calledrdiff-backup
executable, the environment it is run in (e.g. WSL), or the invokedrdiff-backup
action. ToastNotification
module-
A PowerShell module to easily show toast notifications to a user’s Windows desktop. It supports sending a simple toast notification with a title and a message, and automatically displaying the toast on the desktop of the user currently logged into the local machine.
This is a simple script intended mainly for a personal, rather constrained use case.
It only supports a subset of rdiff-backup
functionalities.
As such it comes on an "as-is" basis and without any guarantee whatsoever (see license for details).
It nevertheless features minimal modularity, error-handling and documentation, and should be rather simple to adapt for similar use cases.
SYNTAX rdiffbackup-wrapper.ps1 [-BackupLabel] <String> [-SrcFullPath] <String> [-DestDriveId] <String> [-DestDriveLabel] <String> [-DestPath] <String> [-UseCompatibleTimestamps] [[-IncludeExcludeListFile] <String>] [[-RemoveOlderThan] <String>] [[-RdiffBackupVer] <String>] [[-RdiffBackupRemoveVer] <String>] [<CommonParameters>]
For example:
PS > $BackupParams = @{ BackupLabel = 'System' DestDriveId = 'F1391FF7683E4147BB73340B7CA25810' DestDriveLabel = '_Sys_backup' DestPath = '/Backup' SrcFullPath = 'C:/' IncludeExcludeListFile = 'X:/etc/rdiff-backup/include_filelist' RdiffBackupVer = 'v210a1' RdiffBackupRemoveVer = 'v205' } PS > X:\path\to\rdiffbackup-wrapper.ps1 @BackupParams
You can get a full description of the script including parameters using Get-Help
in PowerShell:
PS > Get-Help X:\path\to\rdiffbackup-wrapper.ps1 -Detailed # (1)
-
Make sure script running is enabled by the current PowerShell execution policy lest
Get-Help
fail to retrieve the script’s local help and start searching for unexisting online help instead.
Once defined in $RdiffBackupExes
, each executable can be specified by passing its hash table key as the script’s -RdiffBackupVer
(for the executable to use to perform the backup) or -RdiffBackupRemoveVer
(for the executable to use to remove old backup increments) parameter ; both parameters are independent and it is possible to specify a different $RdiffBackupExes
key to each of them in a same script call.
Simply put the script together with the Modules
directory in a given directory of your choice (e.g. C:\Users\username\bin\
).
Make sure the execution policy of the PowerShell session you run the script from allows for script running ; see Microsoft documentation on how to do so.
You can install several rdiff-backup
executables (possibly side-by-side) and select at script-call time which one the wrapper script will call internally.
Each executable must be defined in the $RdiffBackupExes
hash table declared in RdiffBackup.psm1
. You can refer to the few predefined entries there for syntax. The RdiffBackupExe::Api
member variable refers to whether the rdiff-backup
executable should be called with the old or new CLI, and the RdiffBackupExe::Environment
should be one of RdiffBackupExeEnv::Win
for "native" Windows executables or RdiffBackupExeEnv::WSL
for ones installed in the Windows Subsystem for Linux.
Executables so defined can then be selected at call time.
Tip
|
Each parameter has a default value which can be modified by editing rdiffbackup-wrapper.ps1 .
|
WSL executables, after the script has mounted the destination drive, need to additionally mount the backup destination within WSL.
Mount options used to mount the backup destination within WSL can be set through the DEST_WSL_MOUNT_*
constants declared in rdiffbackup-wrapper.ps1
.
Additionally, mount
within WSL is called through sudo
, so for it to work unattended the default user of the default WSL distribution must be authorized to run sudo mount
passwordless, for example by adding the following at the end of the sudoers
file:
/etc/sudoers
(or for example /etc/sudoers.d/wslDefaultUserName
— if the sudoers file ends with an @includedir /etc/sudoers.d
statement)wslDefaultUserName ALL=(ALL) NOPASSWD: /usr/bin/mount, /usr/bin/umount # (1)
-
Replace
wslDefaultUserName
with the name of your default WSL user
Alternatively, modules can be stored anywhere ; you just need to change the value of the $MODULES_ABS_PATH
constant in rdiffbackup-wrapper.ps1 to the new location of the Modules
directory. Each module’s path can also be set individually through their respective $MODULE_***_PATH
variable value.
It’s also possible to store some or all modules in a location specified in $env:PSModulePath
; in this case, their respective Import-Module
call in rdiffbackup-wrapper.ps1 can be commented out and the modules will be automatically loaded (see Microsoft documentation on script modules for more on this).
The script ships with a mock implementation (which does nothing) of the backup destination drive mount/dismount operation.
This is fine for backups toward always-mounted drives, but if you want to automatically mount/dismount the destination drive respectively before/after the backup operations, you’ll have to implement the Mount-Drive
and Dismount-Drive
functions in the DriveMount
module to do so according to your use case.
Refer to the source comments and the given mock implementation for documentation.
Note
|
The script assumes such a scheduled usage in its default error messages. |
It often makes sense to have Windows automatically run the script at regular intervals, for automated backups. This can be achieved for example with scheduled jobs:
PS > $RegularBackupParams = @{ BackupLabel = 'System' ... # (1) } PS > Register-ScheduledJob -Name 'System backup' -ScriptBlock { param($parameters); X:\path\to\rdiffbackup-wrapper.ps1 @parameters; } -ArgumentList $RegularBackupParams
-
Rest of the named arguments to pass to the script
Scheduled jobs are registered as regular scheduled tasks, the action of which is to start a PowerShell instance to run the defined job.
As such, scheduled job properties, like its running time or interval, can be set through the command line using the Get-ScheduledJob
and Set-ScheduledJob
cmdlets, or with the Windows Task Scheduler GUI: scheduled jobs are registered under the Microsoft\Windows\PowerShell\ScheduledJobs
folder in the Task Scheduler Library
.
Besides setting the appropriate user to run the task, or the run conditions, it might also be necessary to edit the task action to pass a proper -ExecutionPolicy
argument to powershell.exe
lest the script not get executed when the task run PowerShell.
The output of scheduled jobs can later be retrieved using the Receive-Job
cmdlet. The list of previously run job intances can be retrieved with Get-Job
. For example:
PS > Get-Job Id Name PSJobTypeName State HasMoreData Location Command -- ---- ------------- ----- ----------- -------- ------- ... 16 System backup PSScheduledJob Failed True localhost param($parameters); C... PS > Receive-Job -Keep -Id 16 # (1) ... # job output
-
-Keep
prevents the job from being discarded and allows for potentially retrieving it again in the future with the same command.
The job’s definition and run outputs are stored in XML format at X:\Users\<task-running-user>\AppData\Local\Microsoft\Windows\PowerShell\ScheduledJobs\<scheduled-job-name>
.