Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e406209d35 | |||
| ef0784262c | |||
| 0e43525a97 | |||
| 62a9698427 | |||
| b8e9d4bbf1 | |||
| 8bafb04735 | |||
| 5949555747 |
114
README.md
114
README.md
@@ -5,8 +5,8 @@
|
|||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<span>English</span> |
|
<span>English</span> |
|
||||||
<!-- a href="lang/spanish#dsnap-sync">Spanish</a> | -->
|
<!-- a href="lang/spanish">Spanish</a> | -->
|
||||||
<a href="lang/german#dsnap-sync">Deutsch</a>
|
<a href="lang/german">Deutsch</a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
## About
|
## About
|
||||||
@@ -140,17 +140,17 @@ Following tools are used:
|
|||||||
`dsnap-sync` is a shell script. Thus no compilation is required.
|
`dsnap-sync` is a shell script. Thus no compilation is required.
|
||||||
To simplify correct target locations, this project uses a Makefile.
|
To simplify correct target locations, this project uses a Makefile.
|
||||||
|
|
||||||
# make install
|
# make install
|
||||||
|
|
||||||
If your system uses a non-default location for the snapper
|
If your system uses a non-default location for the snapper
|
||||||
configuration defaults, specify the location with an environment variable
|
configuration defaults, specify the location with an environment variable
|
||||||
(`SNAPPER_CONFIG`).
|
(`SNAPPER_CONFIG`).
|
||||||
|
|
||||||
Arch Linux/Fedora/Gentoo:
|
Arch Linux/Fedora/Gentoo:
|
||||||
# make SNAPPER_CONFIG=/etc/conf.d/snapper install
|
# make SNAPPER_CONFIG=/etc/conf.d/snapper install
|
||||||
|
|
||||||
Debian/Ubuntu:
|
Debian/Ubuntu:
|
||||||
# make SNAPPER_CONFIG=/etc/default/snapper install
|
# make SNAPPER_CONFIG=/etc/default/snapper install
|
||||||
|
|
||||||
The local `snapper` configuration will be extended to make use
|
The local `snapper` configuration will be extended to make use
|
||||||
of a new template 'dsnap-sync'.
|
of a new template 'dsnap-sync'.
|
||||||
@@ -172,41 +172,41 @@ Please use your host software package manager.
|
|||||||
|
|
||||||
## Options
|
## Options
|
||||||
|
|
||||||
Usage: dsnap-sync [options]
|
Usage: dsnap-sync [options]
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
-a, --automount <path> start automount for given path to get a valid target mountpoint.
|
-a, --automount <path> start automount for given path to get a valid target mountpoint.
|
||||||
-b, --backupdir <prefix> backupdir is a relative path that will be appended to target backup-root
|
-b, --backupdir <prefix> backupdir is a relative path that will be appended to target backup-root
|
||||||
--backuptype <type> Specify backup type <archive | child | parent>
|
--backuptype <type> Specify backup type <archive | child | parent>
|
||||||
--batch no user interaction
|
--batch no user interaction
|
||||||
-d, --description <desc> Change the snapper description. Default: "latest incremental backup"
|
-d, --description <desc> Change the snapper description. Default: "latest incremental backup"
|
||||||
--label-finished <desc> snapper description tagging successful jobs. Default: "dsnap-sync backup"
|
--label-finished <desc> snapper description tagging successful jobs. Default: "dsnap-sync backup"
|
||||||
--label-running <desc> snapper description tagging active jobs. Default: "dsnap-sync in progress"
|
--label-running <desc> snapper description tagging active jobs. Default: "dsnap-sync in progress"
|
||||||
--label-synced <desc> snapper description tagging last synced jobs.
|
--label-synced <desc> snapper description tagging last synced jobs.
|
||||||
Default: "dsnap-sync last incremental"
|
Default: "dsnap-sync last incremental"
|
||||||
--color Enable colored output messages
|
--color Enable colored output messages
|
||||||
-c, --config <config> Specify the snapper configuration to use. Otherwise will perform for each snapper
|
-c, --config <config> Specify the snapper configuration to use. Otherwise will perform for each snapper
|
||||||
configuration. You can select multiple configurations
|
configuration. You can select multiple configurations
|
||||||
(e.g. -c "root" -c "home"; --config root --config home)
|
(e.g. -c "root" -c "home"; --config root --config home)
|
||||||
--config-postfix <name> Specify a postfix that will be appended to the destination snapper config name.
|
--config-postfix <name> Specify a postfix that will be appended to the destination snapper config name.
|
||||||
--dry-run perform a trial run (no changes are written).
|
--dry-run perform a trial run (no changes are written).
|
||||||
--mediapool Specify the name of the tape MediaPool
|
--mediapool Specify the name of the tape MediaPool
|
||||||
-n, --noconfirm Do not ask for confirmation for each configuration. Will still prompt for backup
|
-n, --noconfirm Do not ask for confirmation for each configuration. Will still prompt for backup
|
||||||
--nonotify Disable graphical notification (via dbus)
|
--nonotify Disable graphical notification (via dbus)
|
||||||
--nopv Disable graphical progress output (disable pv)
|
--nopv Disable graphical progress output (disable pv)
|
||||||
--noionice Disable setting of I/O class and priority options on target
|
--noionice Disable setting of I/O class and priority options on target
|
||||||
-r, --remote <address> Send the snapshot backup to a remote machine. The snapshot will be sent via ssh
|
-r, --remote <address> Send the snapshot backup to a remote machine. The snapshot will be sent via ssh
|
||||||
You should specify the remote machine's hostname or ip address. The 'root' user
|
You should specify the remote machine's hostname or ip address. The 'root' user
|
||||||
must be permitted to login on the remote machine
|
must be permitted to login on the remote machine
|
||||||
-p, --port <port> The remote port
|
-p, --port <port> The remote port
|
||||||
-s, --subvolid <subvlid> Specify the subvolume id of the mounted BTRFS subvolume to back up to. Defaults to 5.
|
-s, --subvolid <subvlid> Specify the subvolume id of the mounted BTRFS subvolume to back up to. Defaults to 5.
|
||||||
--use-btrfs-quota use btrfs-quota to calculate snapshot size
|
--use-btrfs-quota use btrfs-quota to calculate snapshot size
|
||||||
-u, --uuid <UUID> Specify the UUID of the mounted BTRFS subvolume to back up to. Otherwise will prompt
|
-u, --uuid <UUID> Specify the UUID of the mounted BTRFS subvolume to back up to. Otherwise will prompt
|
||||||
If multiple mount points are found with the same UUID, will prompt for user selection
|
If multiple mount points are found with the same UUID, will prompt for user selection
|
||||||
-t, --target <target> Specify the mountpoint of the backup device
|
-t, --target <target> Specify the mountpoint of the backup device
|
||||||
--volumename Specify the name of the tape volume
|
--volumename Specify the name of the tape volume
|
||||||
-v, --verbose Be verbose on what's going on (min: --verbose=1, max: --verbose=3)
|
-v, --verbose Be verbose on what's going on (min: --verbose=1, max: --verbose=3)
|
||||||
--version show program version
|
--version show program version
|
||||||
|
|
||||||
## First run
|
## First run
|
||||||
|
|
||||||
@@ -259,7 +259,7 @@ backup types are differenciated:
|
|||||||
* create a config specific subdirectory (`archive-<config-name>`)
|
* create a config specific subdirectory (`archive-<config-name>`)
|
||||||
* create a snapshot-id subdirectory (`<snapper-id>`)
|
* create a snapshot-id subdirectory (`<snapper-id>`)
|
||||||
* create the btrfs stream file inside the subdirectory
|
* create the btrfs stream file inside the subdirectory
|
||||||
(`<snapper-id>_[full | incremental].btrfs`)
|
(`<snapper-id>_[full | incremental].btrfs`)
|
||||||
* the proccess metadata are saved to a file called `info.xml`
|
* the proccess metadata are saved to a file called `info.xml`
|
||||||
|
|
||||||
If you enabled the `ltfs` package, support for backups to tape is possible.
|
If you enabled the `ltfs` package, support for backups to tape is possible.
|
||||||
@@ -304,6 +304,34 @@ FUSE). Read and write access can be managed using common OS tools.
|
|||||||
An open-source implementation can be found at
|
An open-source implementation can be found at
|
||||||
[LinearTapeFileSystem](https://github.com/LinearTapeFileSystem/ltfs).
|
[LinearTapeFileSystem](https://github.com/LinearTapeFileSystem/ltfs).
|
||||||
|
|
||||||
|
## Restore
|
||||||
|
|
||||||
|
### From Tape
|
||||||
|
|
||||||
|
When `dsnap-sync` did save the data with method `btrfs-archive`, you will find
|
||||||
|
the corresponding data in a snapper compatible directory structure on the tape.
|
||||||
|
|
||||||
|
The structure may look like:
|
||||||
|
|
||||||
|
└── backups
|
||||||
|
└── @<server-name>
|
||||||
|
├── archive-<subvol-name>
|
||||||
|
│ └── <subvol-id>
|
||||||
|
│ ├── <subvol-id>_full.btrfs
|
||||||
|
│ └── info.xml
|
||||||
|
|
||||||
|
The file `info.xml` provide the metadata corresponding to the snapshot.
|
||||||
|
The data of the snapshot is stored in the file `<subvol-id>_full.btrfs`.
|
||||||
|
This file has to be decrypted with btrfs tool `btrfs-send` to a btrfs
|
||||||
|
restore directory:
|
||||||
|
|
||||||
|
cd /target_btrfs_path
|
||||||
|
cp /path_to_tape_root/backups/@<server-name>/archive-<subvol-name>/<subvol-id>_full.btrfs .
|
||||||
|
cat <subvol-id>_full.btrfs | btrfs receive -v .
|
||||||
|
rm <subvol-id>_full.btrfs
|
||||||
|
|
||||||
|
Please consult btrfs-send man-page for further info.
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
Help is very welcome! Feel free to fork and issue a pull request to add
|
Help is very welcome! Feel free to fork and issue a pull request to add
|
||||||
@@ -331,4 +359,4 @@ This work is licensed under a [Creative Common License 4.0][License-CC_BY]
|
|||||||
![Creative Common Logo][Logo-CC_BY]
|
![Creative Common Logo][Logo-CC_BY]
|
||||||
|
|
||||||
© 2016, 2017 James W. Barnett;
|
© 2016, 2017 James W. Barnett;
|
||||||
© 2017 - 2018 Ralf Zerres
|
© 2017 - 2019 Ralf Zerres
|
||||||
|
|||||||
446
bin/dsnap-sync
446
bin/dsnap-sync
@@ -27,7 +27,7 @@
|
|||||||
# difference for the next incremental snapshot.
|
# difference for the next incremental snapshot.
|
||||||
|
|
||||||
progname="${0##*/}"
|
progname="${0##*/}"
|
||||||
version="0.6.5"
|
version="0.6.5.1"
|
||||||
|
|
||||||
# The following lines are modified by the Makefile or
|
# The following lines are modified by the Makefile or
|
||||||
# find_snapper_config script
|
# find_snapper_config script
|
||||||
@@ -79,6 +79,7 @@ snapper_backup_type='none'
|
|||||||
#snapper_config_postfix="."`hostname`
|
#snapper_config_postfix="."`hostname`
|
||||||
snapper_config_postfix=
|
snapper_config_postfix=
|
||||||
snap_cleanup_algorithm="timeline"
|
snap_cleanup_algorithm="timeline"
|
||||||
|
transfer_size=0
|
||||||
verbose=0
|
verbose=0
|
||||||
volume_name=
|
volume_name=
|
||||||
|
|
||||||
@@ -133,7 +134,7 @@ check_snapper_failed_ids () {
|
|||||||
| awk '/'"$snap_description_running"'/ {cnt++} END {print cnt}')
|
| awk '/'"$snap_description_running"'/ {cnt++} END {print cnt}')
|
||||||
#snapper_failed_ids="snapper --config $selected_config list --type single \
|
#snapper_failed_ids="snapper --config $selected_config list --type single \
|
||||||
# | awk '/'"$snap_description_running"'/' \
|
# | awk '/'"$snap_description_running"'/' \
|
||||||
# | awk ' /'host='"$remote"'/ {cnt++} END {print cnt}'"
|
# | awk ' /'host='"$remote"'/ {cnt++} END {print cnt}'"
|
||||||
|
|
||||||
if [ ${#snapper_failed_ids} -gt 0 ]; then
|
if [ ${#snapper_failed_ids} -gt 0 ]; then
|
||||||
if [ "$batch" ]; then
|
if [ "$batch" ]; then
|
||||||
@@ -161,6 +162,103 @@ check_snapper_failed_ids () {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
check_transfer_size () {
|
||||||
|
local source_snapshot=${1##source_snapshot=}
|
||||||
|
local clone_snapshot=${2##clone_snapshot=}
|
||||||
|
|
||||||
|
if [ $verbose -ge 3 ]; then
|
||||||
|
printf "${MAGENTA}check_transfer_size()...${NO_COLOR}\n"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $dryrun -eq 0 ]; then
|
||||||
|
transfer_size=0
|
||||||
|
if [ "$interactive" -eq 1 ]; then
|
||||||
|
if [ $verbose -ge 2 ]; then
|
||||||
|
if [ ${#clone_snapshot} -gt 0 ]; then
|
||||||
|
printf "${MAGENTA}Calculate transfer size for incremental snapshot (clone=${GREEN}'%s'${MAGENTA}, source=${GREEN}'%s'${MAGENTA})${NO_COLOR} ...\n" \
|
||||||
|
"$clone_snapshot" "$source_snapshot"
|
||||||
|
else
|
||||||
|
printf "${MAGENTA}Calculate transfer size for snapshot (source=${GREEN}'%s'${MAGENTA})${NO_COLOR} ...\n" \
|
||||||
|
"$ssource_snapshot"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if [ $btrfs_quota -eq 1 ]; then
|
||||||
|
# qgroup for given path, exclude ancestrals
|
||||||
|
# qgroup identifiers conform to level/id where level 0 is reserved to the qgroups associated with subvolumes
|
||||||
|
transfer_size=$(btrfs qgroup show -f --raw $source_snapshot 2>/dev/null \
|
||||||
|
| awk 'FNR>2 {print $2}')
|
||||||
|
if [ $? -eq 1 ]; then
|
||||||
|
# subvolume is not configured for quota, (temporary?, expensive?) enable that
|
||||||
|
if [ $btrfs_quota_tmp -eq 1 ]; then
|
||||||
|
btrfs quota enable $source_snapshot 2>/dev/null
|
||||||
|
btrfs quota rescan -w $source_snapshot 2>/dev/null
|
||||||
|
transfer_size=$(btrfs qgroup show -f --raw $source_snapshot 2>/dev/null \
|
||||||
|
| awk 'FNR>2 {print $2}')
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $verbose -ge 3 ]; then
|
||||||
|
printf "${MAGENTA}BTRFS qgroup show result: ${GREEN}'%s'\b${NO_COLOR}'%s'\n" \
|
||||||
|
"$?" "$transfer_size"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# need to substitue btrfs 'x.yyGiB' suffix, since pv will need 'xG'
|
||||||
|
if [ $transfer_size -ge 1048576 ]; then
|
||||||
|
transfer_size=$(btrfs qgroup show -f --gbytes $source_snapshot 2>/dev/null \
|
||||||
|
| awk 'FNR>2 { gsub(/.[0-9][0-9]GiB/,"G"); print $2}')
|
||||||
|
fi
|
||||||
|
if [ $verbose -ge 2 ]; then
|
||||||
|
printf "${MAGENTA}BTRFS quota size for ${GREEN}source snapshot${MAGENTA}: size=${GREEN}'%s'${NO_COLOR} ...\n" \
|
||||||
|
"$snapper_source_id" "$transfer_size"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# should we disable quota usage again?
|
||||||
|
if [ $btrfs_quota_tmp -eq 1 ]; then btrfs quota disable $source_snapshot; fi
|
||||||
|
else
|
||||||
|
if [ ${#clone_snapshot} -gt 0 ]; then
|
||||||
|
# WIP: dry run with btrfs send
|
||||||
|
# need to substitue btrfs 'x.yyGiB' suffix, since pv will need 'xG'
|
||||||
|
transfer_size=$(btrfs send -v -p $clone_snapshot $source_snapshot 2>$BTRFS_PIPE \
|
||||||
|
| pv -f 2>&1 >/dev/null \
|
||||||
|
| awk -F ' ' '{ gsub(/.[0-9][0-9]MiB/,"M"); gsub(/.[0-9][0-9]GiB/,"G"); print $1 }' )
|
||||||
|
else
|
||||||
|
# filesystem size
|
||||||
|
transfer_size=$(du --one-file-system --summarize $snapper_source_snapshot 2>/dev/null \
|
||||||
|
| awk -F ' ' '{print $1}')
|
||||||
|
if [ $transfer_size -ge 1048576 ]; then
|
||||||
|
transfer_size=$(($transfer_size / 1024 / 1024))G
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if [ $verbose -ge 2 ]; then
|
||||||
|
printf "${MAGENTA}BTRFS transfer size for ${GREEN}source snapshot${MAGENTA}: size=${GREEN}'%s'${NO_COLOR} ...\n" \
|
||||||
|
"$transfer_size"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
if [ $verbose -ge 2 ]; then
|
||||||
|
printf "${MAGENTA}dryrun: Would calculate transfer size for BTRFS ${GREEN}source snapshot${NO_COLOR} ...\n" \
|
||||||
|
"$snapper_source_id"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
create_pv_cmd () {
|
||||||
|
if [ $verbose -ge 3 ]; then
|
||||||
|
printf "${MAGENTA}create_pv_cmd()...${NO_COLOR}\n"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# prepare cmdline output settings for interactive progress status
|
||||||
|
if [ $do_pv_cmd -eq 1 ]; then
|
||||||
|
pv_options="--delay-start 2 --interval 5 --format \"time elapsed [%t] | avg rate %a | rate %r | transmitted [%b] | %p | time remaining [%e]\" "
|
||||||
|
cmd_pv="pv --size $transfer_size $pv_options | "
|
||||||
|
#cmd_pv="pv $pv_options --size ${transfer_size} | dialog --gauge \"$progname: Progress for config '$selected_config'\" 6 85 |"
|
||||||
|
else
|
||||||
|
cmd_pv=''
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
create_snapshot () {
|
create_snapshot () {
|
||||||
if [ $verbose -ge 3 ]; then
|
if [ $verbose -ge 3 ]; then
|
||||||
printf "${MAGENTA}create_snapshot()...${NO_COLOR}\n" $snapper_config
|
printf "${MAGENTA}create_snapshot()...${NO_COLOR}\n" $snapper_config
|
||||||
@@ -278,12 +376,12 @@ get_archive_last_sync_id () {
|
|||||||
case ${archive_type} in
|
case ${archive_type} in
|
||||||
#incremental)
|
#incremental)
|
||||||
# cmd="find ${selected_target}/${backupdir}/${snapper_target_config} -name *_${archive_type}.btrfs \
|
# cmd="find ${selected_target}/${backupdir}/${snapper_target_config} -name *_${archive_type}.btrfs \
|
||||||
# | awk -F '.*/' '{ gsub(/_${archive_type}.btrfs\$/,"_"); print \$2}' \
|
# | awk -F '.*/' '{ gsub(/_${archive_type}.btrfs\$/,"_"); print \$2}' \
|
||||||
# | awk ' \$1 == $snapper_source_sync_id {print \$1} ' "
|
# | awk ' \$1 == $snapper_source_sync_id {print \$1} ' "
|
||||||
# ;;
|
# ;;
|
||||||
*)
|
*)
|
||||||
cmd="find ${selected_target}/${backupdir}/${snapper_target_config} -name *_${archive_type}.btrfs \
|
cmd="find ${selected_target}/${backupdir}/${snapper_target_config} -name *_${archive_type}.btrfs \
|
||||||
| awk -F '.*/' '{ gsub(/_${archive_type}.btrfs\$/,"_"); cnt++} END {print cnt}'"
|
| awk -F '.*/' '{ gsub(/_${archive_type}.btrfs\$/,"_"); cnt++} END {print cnt}'"
|
||||||
ret=$(eval $run_ssh "$cmd" 2>/dev/null)
|
ret=$(eval $run_ssh "$cmd" 2>/dev/null)
|
||||||
if [ ${#ret} -ge 1 ]; then
|
if [ ${#ret} -ge 1 ]; then
|
||||||
if [ $verbose -ge 3 ]; then
|
if [ $verbose -ge 3 ]; then
|
||||||
@@ -292,7 +390,7 @@ get_archive_last_sync_id () {
|
|||||||
fi
|
fi
|
||||||
# get last sync-id
|
# get last sync-id
|
||||||
cmd="find ${selected_target}/${backupdir}/${snapper_target_config} -name *_${archive_type}.btrfs \
|
cmd="find ${selected_target}/${backupdir}/${snapper_target_config} -name *_${archive_type}.btrfs \
|
||||||
| awk -F '.*/' '{ gsub(/_${archive_type}.btrfs\$/,"_") } END {print \$2}'"
|
| awk -F '.*/' '{ gsub(/_${archive_type}.btrfs\$/,"_") } END {print \$2}'"
|
||||||
else
|
else
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
@@ -565,7 +663,7 @@ get_disk_infos () {
|
|||||||
# local root filesystem will be excluded as a valid target location
|
# local root filesystem will be excluded as a valid target location
|
||||||
exclude_uuid=$(findmnt --noheadings --nofsroot --mountpoint / --output UUID)
|
exclude_uuid=$(findmnt --noheadings --nofsroot --mountpoint / --output UUID)
|
||||||
disk_uuids=$(findmnt --noheadings --nofsroot --types btrfs --output UUID,TARGET --list \
|
disk_uuids=$(findmnt --noheadings --nofsroot --types btrfs --output UUID,TARGET --list \
|
||||||
| grep -v $exclude_uuid \
|
| grep -v $exclude_uuid \
|
||||||
| awk '{print $1}')
|
| awk '{print $1}')
|
||||||
disk_targets=$(findmnt --noheadings --nofsroot --types btrfs --output UUID,TARGET --list \
|
disk_targets=$(findmnt --noheadings --nofsroot --types btrfs --output UUID,TARGET --list \
|
||||||
| grep -v $exclude_uuid \
|
| grep -v $exclude_uuid \
|
||||||
@@ -579,7 +677,7 @@ get_disk_infos () {
|
|||||||
exclude_uuid=$($ssh findmnt --noheadings --nofsroot --mountpoint / --output UUID)
|
exclude_uuid=$($ssh findmnt --noheadings --nofsroot --mountpoint / --output UUID)
|
||||||
sleep 0.2
|
sleep 0.2
|
||||||
disk_uuids=$($ssh "findmnt --noheadings --nofsroot --types btrfs --output UUID,TARGET --list \
|
disk_uuids=$($ssh "findmnt --noheadings --nofsroot --types btrfs --output UUID,TARGET --list \
|
||||||
| grep -v \"$exclude_uuid\" \
|
| grep -v \"$exclude_uuid\" \
|
||||||
| awk '{print \$1}'")
|
| awk '{print \$1}'")
|
||||||
sleep 0.2
|
sleep 0.2
|
||||||
disk_targets=$($ssh "findmnt --noheadings --nofsroot --types btrfs --output UUID,TARGET --list \
|
disk_targets=$($ssh "findmnt --noheadings --nofsroot --types btrfs --output UUID,TARGET --list \
|
||||||
@@ -589,7 +687,7 @@ get_disk_infos () {
|
|||||||
fs_options=$($ssh "findmnt --noheadings --nofsroot --types btrfs --output UUID,OPTIONS --list \
|
fs_options=$($ssh "findmnt --noheadings --nofsroot --types btrfs --output UUID,OPTIONS --list \
|
||||||
| grep -v \"$exclude_uuid\" \
|
| grep -v \"$exclude_uuid\" \
|
||||||
| awk '{print \$2}'")
|
| awk '{print \$2}'")
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
# target location is not mounted as root subvolume
|
# target location is not mounted as root subvolume
|
||||||
sleep 0.2
|
sleep 0.2
|
||||||
@@ -781,13 +879,13 @@ get_snapper_last_sync_id () {
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
if [ ${#snapper_subvolid} -ge 1 -a ${#snapper_uuid} -ge 1 ]; then
|
if [ ${#snapper_subvolid} -ge 1 -a ${#snapper_uuid} -ge 1 ]; then
|
||||||
cmd="snapper --config $snapper_config list --type single \
|
cmd="snapper --config $snapper_config list --type single \
|
||||||
| awk '/$snapper_description/' \
|
| awk '/$snapper_description/' \
|
||||||
| awk '/subvolid="$snapper_subvolid", uuid="$snapper_uuid"/' \
|
| awk '/subvolid="$snapper_subvolid", uuid="$snapper_uuid"/' \
|
||||||
| awk 'END {print \$1}'"
|
| awk 'END {print \$1}'"
|
||||||
elif [ ${#snapper_tapeid} -ge 1 ]; then
|
elif [ ${#snapper_tapeid} -ge 1 ]; then
|
||||||
# | awk '/"$snapper_description"' '/"$snap_description_finished/"' \
|
# | awk '/"$snapper_description"' '/"$snap_description_finished/"' \
|
||||||
cmd="snapper --config $snapper_config list --type single \
|
cmd="snapper --config $snapper_config list --type single \
|
||||||
| awk '/$snapper_description/' \
|
| awk '/$snapper_description/' \
|
||||||
| awk '/tapeid="$snapper_tapeid"/' \
|
| awk '/tapeid="$snapper_tapeid"/' \
|
||||||
| awk 'END {print \$1}'"
|
| awk 'END {print \$1}'"
|
||||||
@@ -810,17 +908,17 @@ get_snapper_last_sync_id () {
|
|||||||
# no snapshot found, grap latest successfull sync
|
# no snapshot found, grap latest successfull sync
|
||||||
if [ ${#snapper_subvolid} -ge 1 -a ${#snapper_uuid} -ge 1 ]; then
|
if [ ${#snapper_subvolid} -ge 1 -a ${#snapper_uuid} -ge 1 ]; then
|
||||||
cmd="snapper --config $snapper_config list --type single \
|
cmd="snapper --config $snapper_config list --type single \
|
||||||
| awk '/$snap_description_finished/' \
|
| awk '/$snap_description_finished/' \
|
||||||
| awk '/subvolid="$selected_subvol", uuid="$selected_uuid"/' \
|
| awk '/subvolid="$selected_subvol", uuid="$selected_uuid"/' \
|
||||||
| awk 'END {print \$1}'"
|
| awk 'END {print \$1}'"
|
||||||
elif [ ${#snapper_tapeid} -ge 1 ]; then
|
elif [ ${#snapper_tapeid} -ge 1 ]; then
|
||||||
cmd="snapper --config $snapper_config list --type single \
|
cmd="snapper --config $snapper_config list --type single \
|
||||||
| awk '/$snap_description_finished/' \
|
| awk '/$snap_description_finished/' \
|
||||||
| awk '/tapeid="$snapper_tapeid"/' \
|
| awk '/tapeid="$snapper_tapeid"/' \
|
||||||
| awk 'END {print \$1}'"
|
| awk 'END {print \$1}'"
|
||||||
else
|
else
|
||||||
cmd="snapper --config $snapper_config list --type single \
|
cmd="snapper --config $snapper_config list --type single \
|
||||||
| awk '/$snap_description_finished/' \
|
| awk '/$snap_description_finished/' \
|
||||||
| awk 'END {print \$1}'"
|
| awk 'END {print \$1}'"
|
||||||
fi
|
fi
|
||||||
snapper_sync_id=$(eval $run_ssh "$cmd")
|
snapper_sync_id=$(eval $run_ssh "$cmd")
|
||||||
@@ -857,7 +955,7 @@ get_snapper_sync_id () {
|
|||||||
[ ${#remote} -gt 0 ] && run_ssh=$ssh
|
[ ${#remote} -gt 0 ] && run_ssh=$ssh
|
||||||
|
|
||||||
cmd="snapper --config "$snapper_config" list --type single \
|
cmd="snapper --config "$snapper_config" list --type single \
|
||||||
| awk -F '|' ' \$1 == $snapper_sync_id { gsub(/ /,_); print \$1} '"
|
| awk -F '|' ' \$1 == $snapper_sync_id { gsub(/ /,_); print \$1} '"
|
||||||
|
|
||||||
ret=$(eval $run_ssh "$cmd")
|
ret=$(eval $run_ssh "$cmd")
|
||||||
if [ ${#ret} -ge 1 ]; then
|
if [ ${#ret} -ge 1 ]; then
|
||||||
@@ -1193,7 +1291,7 @@ parse_params () {
|
|||||||
else
|
else
|
||||||
$ssh which sh >/dev/null 2>&1 || \
|
$ssh which sh >/dev/null 2>&1 || \
|
||||||
{ printf "'remote shell' is not working!\n \
|
{ printf "'remote shell' is not working!\n \
|
||||||
Please correct your public authentication and try again.\n" && exit 1; }
|
Please correct your public authentication and try again.\n" && exit 1; }
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -1406,12 +1504,12 @@ run_config_preparation () {
|
|||||||
# get backupdir from snapper target
|
# get backupdir from snapper target
|
||||||
get_snapper_target_backupdir $backupdir
|
get_snapper_target_backupdir $backupdir
|
||||||
if [ $verbose -ge 3 ]; then
|
if [ $verbose -ge 3 ]; then
|
||||||
if [ $remote ]; then
|
if [ $remote ]; then
|
||||||
printf "${MAGENTA}backupdir on remote '%s': ${GREEN}'%s'${NO_COLOR}\n" \
|
printf "${MAGENTA}backupdir on remote '%s': ${GREEN}'%s'${NO_COLOR}\n" \
|
||||||
"$remote" "$backupdir"
|
"$remote" "$backupdir"
|
||||||
else
|
else
|
||||||
printf "${MAGENTA}backupdir: ${GREEN}'%s'${NO_COLOR}\n" \
|
printf "${MAGENTA}backupdir: ${GREEN}'%s'${NO_COLOR}\n" \
|
||||||
"$backupdir"
|
"$backupdir"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
# set target sync_snapshot path
|
# set target sync_snapshot path
|
||||||
@@ -1428,13 +1526,13 @@ run_config_preparation () {
|
|||||||
snapper_target_sync_snapshot=$backup_root/.snapshots/$snapper_target_sync_id/$snapper_snapshot_name
|
snapper_target_sync_snapshot=$backup_root/.snapshots/$snapper_target_sync_id/$snapper_snapshot_name
|
||||||
fi
|
fi
|
||||||
if [ $verbose -ge 3 ]; then
|
if [ $verbose -ge 3 ]; then
|
||||||
if [ $remote ]; then
|
if [ $remote ]; then
|
||||||
printf "${MAGENTA}backup_root on remote '%s': ${GREEN}'%s'${NO_COLOR}\n" \
|
printf "${MAGENTA}backup_root on remote '%s': ${GREEN}'%s'${NO_COLOR}\n" \
|
||||||
"$remote" "$backup_root"
|
"$remote" "$backup_root"
|
||||||
else
|
else
|
||||||
printf "${MAGENTA}backup_root: ${GREEN}'%s'${NO_COLOR}\n" \
|
printf "${MAGENTA}backup_root: ${GREEN}'%s'${NO_COLOR}\n" \
|
||||||
"$backup_root"
|
"$backup_root"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
@@ -1539,15 +1637,15 @@ run_backup () {
|
|||||||
|
|
||||||
if [ $verbose -ge 3 ]; then
|
if [ $verbose -ge 3 ]; then
|
||||||
printf "${MAGENTA}snapper_source_config: ${GREEN}'%s'${NO_COLOR}\n" \
|
printf "${MAGENTA}snapper_source_config: ${GREEN}'%s'${NO_COLOR}\n" \
|
||||||
"$snapper_source_config"
|
"$snapper_source_config"
|
||||||
printf "${MAGENTA}snapper_target_config: ${GREEN}'%s'${NO_COLOR}\n" \
|
printf "${MAGENTA}snapper_target_config: ${GREEN}'%s'${NO_COLOR}\n" \
|
||||||
"$snapper_target_config"
|
"$snapper_target_config"
|
||||||
printf "${MAGENTA}snapper_backup_type: ${GREEN}'%s'${NO_COLOR}\n" \
|
printf "${MAGENTA}snapper_backup_type: ${GREEN}'%s'${NO_COLOR}\n" \
|
||||||
"$snapper_backup_type"
|
"$snapper_backup_type"
|
||||||
printf "${MAGENTA}snapper_source_sync_id: ${GREEN}'%s'${NO_COLOR}\n" \
|
printf "${MAGENTA}snapper_source_sync_id: ${GREEN}'%s'${NO_COLOR}\n" \
|
||||||
"$snapper_source_sync_id"
|
"$snapper_source_sync_id"
|
||||||
printf "${MAGENTA}snapper_common_sync_id: ${GREEN}'%s'${NO_COLOR}\n" \
|
printf "${MAGENTA}snapper_common_sync_id: ${GREEN}'%s'${NO_COLOR}\n" \
|
||||||
"$snapper_common_sync_id"
|
"$snapper_common_sync_id"
|
||||||
printf "${MAGENTA}backup_dir: ${GREEN}'%s'${NO_COLOR}\n" "$backup_dir"
|
printf "${MAGENTA}backup_dir: ${GREEN}'%s'${NO_COLOR}\n" "$backup_dir"
|
||||||
printf "${MAGENTA}backup_root: ${GREEN}'%s'${NO_COLOR}\n" "$backup_root"
|
printf "${MAGENTA}backup_root: ${GREEN}'%s'${NO_COLOR}\n" "$backup_root"
|
||||||
fi
|
fi
|
||||||
@@ -1616,64 +1714,6 @@ run_backup () {
|
|||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ $dryrun -eq 0 ]; then
|
|
||||||
snapper_source_snapshot_size=0
|
|
||||||
if [ "$interactive" -eq 1 ]; then
|
|
||||||
if [ $verbose -ge 2 ]; then
|
|
||||||
printf "${MAGENTA}Get size for given source snapshot (id=${GREEN}'%s'${MAGENTA}, path=${GREEN}'%s'${MAGENTA})${NO_COLOR} ...\n" \
|
|
||||||
"$snapper_source_id" "$snapper_source_snapshot"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ $btrfs_quota -eq 1 ]; then
|
|
||||||
# qgroup for given path, exclude ancestrals
|
|
||||||
# qgroup identifiers conform to level/id where level 0 is reserved to the qgroups associated with subvolumes
|
|
||||||
snapper_source_snapshot_size=$(btrfs qgroup show -f --raw $snapper_source_snapshot 2>/dev/null \
|
|
||||||
| awk 'FNR>2 {print $2}')
|
|
||||||
if [ $? -eq 1 ]; then
|
|
||||||
# subvolume is not configured for quota, (temporary?) enable that
|
|
||||||
if [ $btrfs_quota_tmp -eq 1 ]; then
|
|
||||||
btrfs quota enable $snapper_source_snapshot 2>/dev/null
|
|
||||||
btrfs quota rescan -w $snapper_source_snapshot 2>/dev/null
|
|
||||||
snapper_source_snapshot_size=$(btrfs qgroup show -f --raw $snapper_source_snapshot 2>/dev/null \
|
|
||||||
| awk 'FNR>2 {print $2}')
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ $verbose -ge 3 ]; then
|
|
||||||
printf "${MAGENTA}BTRFS qgroup show result: ${GREEN}'%s'\b${NO_COLOR}'%s'\n" \
|
|
||||||
"$?" "$snapper_source_snapshot_size"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# need to substitue btrfs 'x.yyGiB' suffix, since pv will need 'xG'
|
|
||||||
if [ $snapper_source_snapshot_size -ge 1048576 ]; then
|
|
||||||
snapper_source_snapshot_size=$(btrfs qgroup show -f --gbytes $snapper_source_snapshot 2>/dev/null \
|
|
||||||
| awk 'FNR>2 { gsub(/.[0-9][0-9]GiB/,"G"); print $2}')
|
|
||||||
fi
|
|
||||||
if [ $verbose -ge 2 ]; then
|
|
||||||
printf "${MAGENTA}BTRFS quota size for ${GREEN}source snapshot${MAGENTA}: id=${GREEN}'%s'${MAGENTA}, size=${GREEN}'%s'${NO_COLOR} ...\n" \
|
|
||||||
"$snapper_source_id" "$snapper_source_snapshot_size"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# should we disable quota usage again?
|
|
||||||
if [ $btrfs_quota_tmp -eq 1 ]; then btrfs quota disable $snapper_source_snapshot; fi
|
|
||||||
else
|
|
||||||
snapper_source_snapshot_size=$(du --one-file-system --summarize $snapper_source_snapshot 2>/dev/null \
|
|
||||||
| awk -F ' ' '{print $1}')
|
|
||||||
if [ $snapper_source_snapshot_size -ge 1048576 ]; then
|
|
||||||
snapper_source_snapshot_size=$(($snapper_source_snapshot_size / 1024 / 1024))G
|
|
||||||
fi
|
|
||||||
if [ $verbose -ge 2 ]; then
|
|
||||||
printf "${MAGENTA}BTRFS subvolume size for ${GREEN}source snapshot${MAGENTA}: id=${GREEN}'%s'${MAGENTA}, size=${GREEN}'%s'${NO_COLOR} ...\n" \
|
|
||||||
"$snapper_source_id" "$snapper_source_snapshot_size"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
if [ $verbose -ge 2 ]; then
|
|
||||||
printf "${MAGENTA}dryrun: Would calculate BTRFS subvolume size for ${GREEN}source snapshot${NO_COLOR} ...\n" \
|
|
||||||
"$snapper_source_id"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
# setting process I/O scheduling options
|
# setting process I/O scheduling options
|
||||||
if [ $do_ionice_cmd -eq 1 ]; then
|
if [ $do_ionice_cmd -eq 1 ]; then
|
||||||
# class: best-efford, priority: medium
|
# class: best-efford, priority: medium
|
||||||
@@ -1684,59 +1724,58 @@ run_backup () {
|
|||||||
cmd_ionice=''
|
cmd_ionice=''
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# settings for interactive progress status
|
# prepare pipe command
|
||||||
if [ $do_pv_cmd -eq 1 ]; then
|
|
||||||
pv_options="--delay-start 2 --interval 5 --format \"time elapsed [%t] | avg rate %a | rate %r | transmitted [%b] | %p | time remaining [%e]\" "
|
|
||||||
cmd_pv="pv --size $snapper_source_snapshot_size $pv_options | "
|
|
||||||
#cmd_pv="pv $pv_options --size ${snapper_source_snapshot_size} | dialog --gauge \"$progname: Progress for config '$selected_config'\" 6 85 |"
|
|
||||||
else
|
|
||||||
cmd_pv=''
|
|
||||||
fi
|
|
||||||
|
|
||||||
case $selected_fstype in
|
|
||||||
btrfs)
|
|
||||||
cmd="btrfs send $btrfs_verbose_flag $snapper_source_snapshot 2>$BTRFS_PIPE \
|
|
||||||
| $cmd_pv \
|
|
||||||
$cmd_ionice $ssh btrfs receive $btrfs_verbose_flag $snapper_target_snapshot/ 1>$BTRFS_PIPE 2>&1"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
# Can't use btrfs receive, since target filesystem can't support btrfs snapshot feature
|
|
||||||
snapper_target_stream=${snapper_target_id}_${archive_type}.btrfs
|
|
||||||
if [ ! -f $snapper_target_snapshot/$snapper_target_stream ]; then
|
|
||||||
if [ -z $remote ]; then
|
|
||||||
cmd="btrfs send $btrfs_verbose_flag $snapper_source_snapshot 2>/dev/null \
|
|
||||||
| $cmd_pv \
|
|
||||||
$cmd_ionice cat > $snapper_target_snapshot/$snapper_target_stream"
|
|
||||||
else
|
|
||||||
cmd="btrfs send $btrfs_verbose_flag $snapper_source_snapshot 2>/dev/null \
|
|
||||||
| $cmd_pv \
|
|
||||||
$cmd_ionice $ssh 'cat > $snapper_target_snapshot/$snapper_target_stream' 2>$BTRFS_PIPE"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
if [ $verbose -ge 2 ]; then
|
|
||||||
printf "${RED}BTRFS_Stream: %s${NO_COLOR} already saved.\n" \
|
|
||||||
"$snapper_target_snapshot/$snapper_target_stream"
|
|
||||||
fi
|
|
||||||
# go for next configuration
|
|
||||||
i=$(($i+1))
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
if [ "$dryrun" -eq 0 ]; then
|
if [ "$dryrun" -eq 0 ]; then
|
||||||
if [ "$snapper_source_sync_id" -eq 0 ] \
|
if [ "$snapper_source_sync_id" -eq 0 ] \
|
||||||
|| [ "$snapper_target_sync_id" -eq 0 ] \
|
|| [ "$snapper_target_sync_id" -eq 0 ] \
|
||||||
|| [ "$backup_mode" = "full" ] ; then
|
|| [ "$backup_mode" = "full" ] ; then
|
||||||
|
|
||||||
|
# get size of stream that needs to be transfered
|
||||||
|
check_transfer_size "source_snapshot=$snapper_source_snapshot"
|
||||||
|
|
||||||
|
# prepare send pipe command
|
||||||
|
create_pv_cmd
|
||||||
|
case $selected_fstype in
|
||||||
|
btrfs)
|
||||||
|
cmd="btrfs send $btrfs_verbose_flag $snapper_source_snapshot 2>$BTRFS_PIPE \
|
||||||
|
| $cmd_pv \
|
||||||
|
$cmd_ionice $ssh btrfs receive $btrfs_verbose_flag $snapper_target_snapshot/ 1>$BTRFS_PIPE 2>&1"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
# Can't use btrfs receive, since target filesystem can't support btrfs snapshot feature
|
||||||
|
snapper_target_stream=${snapper_target_id}_${archive_type}.btrfs
|
||||||
|
if [ ! -f $snapper_target_snapshot/$snapper_target_stream ]; then
|
||||||
|
if [ -z $remote ]; then
|
||||||
|
cmd="btrfs send $btrfs_verbose_flag $snapper_source_snapshot 2>/dev/null \
|
||||||
|
| $cmd_pv \
|
||||||
|
$cmd_ionice cat > $snapper_target_snapshot/$snapper_target_stream"
|
||||||
|
else
|
||||||
|
cmd="btrfs send $btrfs_verbose_flag $snapper_source_snapshot 2>/dev/null \
|
||||||
|
| $cmd_pv \
|
||||||
|
$cmd_ionice $ssh 'cat > $snapper_target_snapshot/$snapper_target_stream' 2>$BTRFS_PIPE"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
if [ $verbose -ge 2 ]; then
|
||||||
|
printf "${RED}BTRFS_Stream: %s${NO_COLOR} already saved.\n" \
|
||||||
|
"$snapper_target_snapshot/$snapper_target_stream"
|
||||||
|
fi
|
||||||
|
# go for next configuration
|
||||||
|
i=$(($i+1))
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
# send full snapshot to target
|
# send full snapshot to target
|
||||||
if [ $verbose -ge 2 ]; then
|
if [ $verbose -ge 2 ]; then
|
||||||
if [ ${#snapper_source_snapshot_size} -gt 0 ]; then
|
if [ ${#transfer_size} -gt 0 ]; then
|
||||||
printf "${MAGENTA}Sending ${GREEN}snapshot${NO_COLOR} for snapper config ${GREEN}'%s' ${MAGENTA}(id='%s', size='%s')${NO_COLOR} ...\n" \
|
printf "${MAGENTA}Sending ${GREEN}snapshot${NO_COLOR} for snapper config ${GREEN}'%s' ${MAGENTA}(id='%s', size='%s')${NO_COLOR} ...\n" \
|
||||||
"$selected_config" "$snapper_source_id" "$snapper_source_snapshot_size"
|
"$selected_config" "$snapper_source_id" "$transfer_size"
|
||||||
else
|
else
|
||||||
printf "${MAGENTA}Sending ${GREEN}snapshot${NO_COLOR} for snapper config ${GREEN}'%s' ${MAGENTA}(id='%s')${NO_COLOR} ...\n" \
|
printf "${MAGENTA}Sending ${GREEN}snapshot${NO_COLOR} for snapper config ${GREEN}'%s' ${MAGENTA}(id='%s')${NO_COLOR} ...\n" \
|
||||||
"$selected_config"
|
"$selected_config"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
# the actual data sync to the target
|
# the actual data sync to the target
|
||||||
# this may take a while, depending on datasize and line-speed
|
# this may take a while, depending on datasize and line-speed
|
||||||
if [ $verbose -ge 3 ]; then
|
if [ $verbose -ge 3 ]; then
|
||||||
@@ -1751,8 +1790,8 @@ run_backup () {
|
|||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
# source holds synced snapshots
|
# source holds synced snapshots
|
||||||
if [ $verbose -ge 3 ]; then
|
if [ $verbose -ge 3 ]; then
|
||||||
printf "New ${GREEN}source${NO_COLOR} snapshot id: ${GREEN}'%s'${NO_COLOR} (path: ${GREEN}'%s'${NO_COLOR})\n" \
|
printf "New ${GREEN}source${NO_COLOR} snapshot id: ${GREEN}'%s'${NO_COLOR} (path: ${GREEN}'%s'${NO_COLOR})\n" \
|
||||||
"$snapper_source_id" "$snapper_source_snapshot"
|
"$snapper_source_id" "$snapper_source_snapshot"
|
||||||
printf "New ${GREEN}target${NO_COLOR} snapshot id: ${GREEN}'%s'${NO_COLOR} (path: ${GREEN}'%s'${NO_COLOR})\n" \
|
printf "New ${GREEN}target${NO_COLOR} snapshot id: ${GREEN}'%s'${NO_COLOR} (path: ${GREEN}'%s'${NO_COLOR})\n" \
|
||||||
@@ -1763,17 +1802,18 @@ run_backup () {
|
|||||||
"$snapper_source_sync_id" "$snapper_source_sync_snapshot"
|
"$snapper_source_sync_id" "$snapper_source_sync_snapshot"
|
||||||
printf "Last synced ${GREEN}target${NO_COLOR} snapshot id: ${GREEN}'%s'${NO_COLOR} (path: ${GREEN}'%s'${NO_COLOR})\n" \
|
printf "Last synced ${GREEN}target${NO_COLOR} snapshot id: ${GREEN}'%s'${NO_COLOR} (path: ${GREEN}'%s'${NO_COLOR})\n" \
|
||||||
"$snapper_target_sync_id" "$snapper_target_sync_snapshot"
|
"$snapper_target_sync_id" "$snapper_target_sync_snapshot"
|
||||||
fi
|
fi
|
||||||
if [ $verbose -ge 2 ]; then
|
if [ $verbose -ge 2 ]; then
|
||||||
printf "${MAGENTA}Prepare ${GREEN}incremental snapshot${NO_COLOR} (id: ${GREEN}'%s'${NO_COLOR}) for snapper config ${GREEN}'%s'${NO_COLOR} ...\n" \
|
printf "${MAGENTA}Prepare ${GREEN}incremental snapshot${NO_COLOR} (id: ${GREEN}'%s'${NO_COLOR}) for snapper config ${GREEN}'%s'${NO_COLOR} ...\n" \
|
||||||
"$snapper_target_id" "$selected_config"
|
"$snapper_target_id" "$selected_config"
|
||||||
fi
|
fi
|
||||||
# verify that we have a matching source and target snapshot-id
|
|
||||||
if [ $snapper_common_sync_id -eq 0 ]; then
|
# verify that we have a matching source and target snapshot-id
|
||||||
|
if [ $snapper_common_sync_id -eq 0 ]; then
|
||||||
if [ ${snapper_source_id} -eq ${snapper_target_sync_id} ]; then
|
if [ ${snapper_source_id} -eq ${snapper_target_sync_id} ]; then
|
||||||
# nothing to do, snapshot already in sync
|
# nothing to do, snapshot already in sync
|
||||||
if [ $verbose -ge 3 ]; then
|
if [ $verbose -ge 3 ]; then
|
||||||
printf "${MAGENTA}Nothing to do! Source and target snapshot (id: ${GREEN}'%s'${MAGENTA}) are in sync.${NO_COLOR}\n" \
|
printf "${MAGENTA}Nothing to do! Source and target snapshot (id: ${GREEN}'%s'${MAGENTA}) are in sync.${NO_COLOR}\n" \
|
||||||
"$snapper_target_sync_id"
|
"$snapper_target_sync_id"
|
||||||
fi
|
fi
|
||||||
# go for next configuration
|
# go for next configuration
|
||||||
@@ -1782,17 +1822,17 @@ run_backup () {
|
|||||||
elif [ ${snapper_source_sync_id} != ${snapper_target_sync_id} ]; then
|
elif [ ${snapper_source_sync_id} != ${snapper_target_sync_id} ]; then
|
||||||
if [ $snapper_target_sync_id -lt $snapper_target_id ]; then
|
if [ $snapper_target_sync_id -lt $snapper_target_id ]; then
|
||||||
# try to find last target_sync_id in source_config
|
# try to find last target_sync_id in source_config
|
||||||
get_snapper_sync_id "snapper_config=${snapper_source_config}" "remote="
|
get_snapper_sync_id "snapper_config=${snapper_source_config}" "remote="
|
||||||
if [ $? -eq 0 ]; then
|
if [ $? -eq 0 ]; then
|
||||||
snapper_source_sync_id=$snapper_sync_id
|
snapper_source_sync_id=$snapper_sync_id
|
||||||
snapper_source_sync_snapshot=$SUBVOLUME/.snapshots/$snapper_sync_id/$snapper_snapshot_name
|
snapper_source_sync_snapshot=$SUBVOLUME/.snapshots/$snapper_sync_id/$snapper_snapshot_name
|
||||||
else
|
else
|
||||||
printf "${RED}Error: ${MAGENTA}No common sync id found. Aborting backup for config ${GREEN}'%s'${NO_COLOR}\n"
|
printf "${RED}Error: ${MAGENTA}No common sync id found. Aborting backup for config ${GREEN}'%s'${NO_COLOR}\n"
|
||||||
error_count=$(($error_count+1))
|
error_count=$(($error_count+1))
|
||||||
# go for next configuration
|
# go for next configuration
|
||||||
i=$(($i+1))
|
i=$(($i+1))
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
elif [ ${snapper_source_id} != ${snapper_source_sync_id} ]; then
|
elif [ ${snapper_source_id} != ${snapper_source_sync_id} ]; then
|
||||||
snapper_common_sync_id=$snapper_source_sync_id
|
snapper_common_sync_id=$snapper_source_sync_id
|
||||||
@@ -1811,18 +1851,22 @@ run_backup () {
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cmd="$ssh stat --format %i $snapper_target_snapshot 2>/dev/null"
|
cmd="$ssh stat --format %i $snapper_target_snapshot 2>/dev/null"
|
||||||
ret=$(eval $cmd)
|
ret=$(eval $cmd)
|
||||||
if [ $? -eq 0 ]; then
|
if [ $? -eq 0 ]; then
|
||||||
|
# get size of stream that needs to be transfered
|
||||||
|
check_transfer_size "source_snapshot=$snapper_source_snapshot" "clone_snapshot=$snapper_common_sync_snapshot"
|
||||||
|
create_pv_cmd
|
||||||
|
|
||||||
case $selected_fstype in
|
case $selected_fstype in
|
||||||
btrfs)
|
btrfs)
|
||||||
# Sends the difference between the new snapshot and old synced snapshot.
|
# Sends the difference between the new snapshot and old synced snapshot.
|
||||||
# Using the flag -c (clone-src) will require the availibility of an identical readonly
|
# Using the flag -c (clone-src) will require the availibility of an identical readonly
|
||||||
# subvolume on the source and the receiving location (the parent-id).
|
# subvolume on the source and the receiving location (the parent-id).
|
||||||
# using "btrfs send -p" instead of "btrfs send -c", then no parent search would be
|
# using "btrfs send -p" instead of "btrfs send -c", then no parent search would be
|
||||||
# needed (Andreij explained in: https://www.spinics.net/lists/linux-btrfs/msg69369.html)
|
# needed (Andreij explained in: https://www.spinics.net/lists/linux-btrfs/msg69369.html)
|
||||||
cmd="btrfs send $btrfs_verbose_flag -p $snapper_common_sync_snapshot $snapper_source_snapshot 2>$BTRFS_PIPE \
|
cmd="btrfs send $btrfs_verbose_flag -p $snapper_common_sync_snapshot $snapper_source_snapshot 2>$BTRFS_PIPE \
|
||||||
| $cmd_pv \
|
| $cmd_pv \
|
||||||
$cmd_ionice $ssh btrfs receive $btrfs_verbose_flag $snapper_target_snapshot/ 1>$BTRFS_PIPE 2>&1"
|
$cmd_ionice $ssh btrfs receive $btrfs_verbose_flag $snapper_target_snapshot/ 1>$BTRFS_PIPE 2>&1"
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
@@ -1830,23 +1874,23 @@ run_backup () {
|
|||||||
snapper_target_stream=${snapper_target_id}_incremental.btrfs
|
snapper_target_stream=${snapper_target_id}_incremental.btrfs
|
||||||
if [ -z $remote ]; then
|
if [ -z $remote ]; then
|
||||||
cmd="btrfs send $btrfs_verbose_flag -p $snapper_common_sync_snapshot $snapper_source_snapshot 2>$BTRFS_PIPE \
|
cmd="btrfs send $btrfs_verbose_flag -p $snapper_common_sync_snapshot $snapper_source_snapshot 2>$BTRFS_PIPE \
|
||||||
| $cmd_pv \
|
| $cmd_pv \
|
||||||
$cmd_ionice cat > $snapper_target_snapshot/$snapper_target_stream 2>$BTRFS_PIPE"
|
$cmd_ionice cat > $snapper_target_snapshot/$snapper_target_stream 2>$BTRFS_PIPE"
|
||||||
else
|
else
|
||||||
cmd="btrfs send $btrfs_verbose_flag -p $snapper_common_sync_snapshot $snapper_source_snapshot 2>$BTRFS_PIPE \
|
cmd="btrfs send $btrfs_verbose_flag -p $snapper_common_sync_snapshot $snapper_source_snapshot 2>$BTRFS_PIPE \
|
||||||
| $cmd_pv \
|
| $cmd_pv \
|
||||||
$cmd_ionice $ssh 'cat > $snapper_target_snapshot/$snapper_target_stream' 2>$BTRFS_PIPE"
|
$cmd_ionice $ssh 'cat > $snapper_target_snapshot/$snapper_target_stream' 2>$BTRFS_PIPE"
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
if [ $verbose -ge 2 ]; then
|
if [ $verbose -ge 2 ]; then
|
||||||
printf "%b" "${GREEN}btrfs send${NO_COLOR} is using\n" \
|
printf "%b" "${GREEN}btrfs send${NO_COLOR} is using\n" \
|
||||||
" parent snapshot id: ${GREEN}'$snapper_common_sync_id'${NO_COLOR} (path: ${GREEN}'$snapper_common_sync_snapshot'${NO_COLOR}) and\n" \
|
" parent snapshot id: ${GREEN}'$snapper_common_sync_id'${NO_COLOR} (path: ${GREEN}'$snapper_common_sync_snapshot'${NO_COLOR}) and\n" \
|
||||||
" snapshot id: ${GREEN}'$snapper_source_id'${NO_COLOR} (path: ${GREEN}'$snapper_source_snapshot'${NO_COLOR})\n" \
|
" snapshot id: ${GREEN}'$snapper_source_id'${NO_COLOR} (path: ${GREEN}'$snapper_source_snapshot'${NO_COLOR})\n" \
|
||||||
" to construct an incremental data-stream ...\n"
|
" to construct an incremental data-stream ...\n"
|
||||||
fi
|
fi
|
||||||
if [ $verbose -ge 3 ]; then
|
if [ $verbose -ge 3 ]; then
|
||||||
printf "${GREEN}btrfs command:${NO_COLOR} '%s'\n" "$cmd"
|
printf "${GREEN}btrfs command:${NO_COLOR} '%s'\n" "$cmd"
|
||||||
fi
|
fi
|
||||||
$(eval $cmd)
|
$(eval $cmd)
|
||||||
ret=$?
|
ret=$?
|
||||||
@@ -1874,10 +1918,10 @@ run_backup () {
|
|||||||
continue
|
continue
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
else
|
else
|
||||||
# is this clause possible?
|
# is this clause possible?
|
||||||
if [ $verbose -ge 3 ]; then
|
if [ $verbose -ge 3 ]; then
|
||||||
printf "${RED}Error: ${MAGENTA}No commen sync snapshot ${GREEN}'%s'${MAGENTA} on ${GREEN}source${MAGENTA} to sync metadata ...${NO_COLOR} \n" \
|
printf "${RED}Error: ${MAGENTA}No commen sync snapshot ${GREEN}'%s'${MAGENTA} on ${GREEN}source${MAGENTA} to sync metadata ...${NO_COLOR} \n" \
|
||||||
"$snapper_common_sync_snapshot"
|
"$snapper_common_sync_snapshot"
|
||||||
error_count=$(($error_count+1))
|
error_count=$(($error_count+1))
|
||||||
# go for next configuration
|
# go for next configuration
|
||||||
@@ -1885,14 +1929,14 @@ run_backup () {
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
printf "${MAGENTA}dryrun${NO_COLOR}: Would run btrfs send / btrfs receive pipe\n"
|
printf "${MAGENTA}dryrun${NO_COLOR}: Would run btrfs send / btrfs receive pipe\n"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# send the snapper info metadata
|
# send the snapper info metadata
|
||||||
if [ $dryrun -eq 0 ]; then
|
if [ $dryrun -eq 0 ]; then
|
||||||
if [ -z "$remote" ]; then
|
if [ -z "$remote" ]; then
|
||||||
cp "$snapper_source_info" "$snapper_target_snapshot/info.xml"
|
cp "$snapper_source_info" "$snapper_target_snapshot/info.xml"
|
||||||
else
|
else
|
||||||
@@ -1957,9 +2001,9 @@ run_finalize () {
|
|||||||
SNAP_SYNC_EXCLUDE=no
|
SNAP_SYNC_EXCLUDE=no
|
||||||
|
|
||||||
if [ -f "/etc/snapper/configs/$selected_config" ]; then
|
if [ -f "/etc/snapper/configs/$selected_config" ]; then
|
||||||
. /etc/snapper/configs/$selected_config
|
. /etc/snapper/configs/$selected_config
|
||||||
else
|
else
|
||||||
printf "${RED}Error: ${MAGENTA}Selected snapper configuration ${GREEN}'$selected_config'${MAGENTA} does not exist${NO_COLOR}"
|
printf "${RED}Error: ${MAGENTA}Selected snapper configuration ${GREEN}'$selected_config'${MAGENTA} does not exist${NO_COLOR}"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -1967,7 +2011,7 @@ run_finalize () {
|
|||||||
if [ "$cont_backup" = "no" ] || [ "$SNAP_SYNC_EXCLUDE" = "yes" ]; then
|
if [ "$cont_backup" = "no" ] || [ "$SNAP_SYNC_EXCLUDE" = "yes" ]; then
|
||||||
if [ $donotify -gt 0 ]; then
|
if [ $donotify -gt 0 ]; then
|
||||||
notify_info "Finalize backup" "NOTE: Skipping '$selected_config' configuration."
|
notify_info "Finalize backup" "NOTE: Skipping '$selected_config' configuration."
|
||||||
fi
|
fi
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -2038,8 +2082,8 @@ run_finalize () {
|
|||||||
# save target-id
|
# save target-id
|
||||||
if [ $snapper_source_id -gt 0 ]; then
|
if [ $snapper_source_id -gt 0 ]; then
|
||||||
cmd="snapper --config $selected_config modify \
|
cmd="snapper --config $selected_config modify \
|
||||||
--cleanup-algorithm \"dsnap-sync\" \
|
--cleanup-algorithm \"dsnap-sync\" \
|
||||||
--userdata \"tapeid=$volume_name\" \
|
--userdata \"tapeid=$volume_name\" \
|
||||||
$snapper_source_id"
|
$snapper_source_id"
|
||||||
|
|
||||||
if [ $verbose -ge 3 ]; then
|
if [ $verbose -ge 3 ]; then
|
||||||
@@ -2068,8 +2112,8 @@ run_finalize () {
|
|||||||
;;
|
;;
|
||||||
btrfs-snapshot)
|
btrfs-snapshot)
|
||||||
# create btrfs-snapshot on target
|
# create btrfs-snapshot on target
|
||||||
cmd="$ssh snapper --config \"$snapper_target_config\" list --type single \
|
cmd="$ssh snapper --config \"$snapper_target_config\" list --type single \
|
||||||
| awk ' /'\"$snap_description_running\"'/ ' \
|
| awk ' /'\"$snap_description_running\"'/ ' \
|
||||||
| awk -F '|' ' \$1 == $snapper_target_id {print \$1} ' "
|
| awk -F '|' ' \$1 == $snapper_target_id {print \$1} ' "
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
@@ -2087,7 +2131,7 @@ run_finalize () {
|
|||||||
printf "${MAGENTA}Found${NO_COLOR} snapper id ${GREEN}'%s'${NO_COLOR} on target for configuration ${GREEN}'%s'${NO_COLOR}\n" \
|
printf "${MAGENTA}Found${NO_COLOR} snapper id ${GREEN}'%s'${NO_COLOR} on target for configuration ${GREEN}'%s'${NO_COLOR}\n" \
|
||||||
"$snapper_target_id" "$snapper_target_config"
|
"$snapper_target_id" "$snapper_target_config"
|
||||||
fi
|
fi
|
||||||
if [ $verbose -ge 3 ]; then
|
if [ $verbose -ge 3 ]; then
|
||||||
printf "${MAGENTA}Tagging metadata${NO_COLOR} for snapper id ${GREEN}'%s'${NO_COLOR} on target for configuration ${GREEN}'%s'${NO_COLOR} ...\n" \
|
printf "${MAGENTA}Tagging metadata${NO_COLOR} for snapper id ${GREEN}'%s'${NO_COLOR} on target for configuration ${GREEN}'%s'${NO_COLOR} ...\n" \
|
||||||
"$snapper_target_id" "$snapper_target_config"
|
"$snapper_target_id" "$snapper_target_config"
|
||||||
#printf "calling: '%s'\n" "$($cmd)"
|
#printf "calling: '%s'\n" "$($cmd)"
|
||||||
@@ -2095,16 +2139,16 @@ run_finalize () {
|
|||||||
# call command (respect needed quotes)
|
# call command (respect needed quotes)
|
||||||
if [ $remote ]; then
|
if [ $remote ]; then
|
||||||
ret=$(eval $ssh snapper --config \\\'$snapper_target_config\\\' modify \
|
ret=$(eval $ssh snapper --config \\\'$snapper_target_config\\\' modify \
|
||||||
--description \\\'$snap_description_finished\\\' \
|
--description \\\'$snap_description_finished\\\' \
|
||||||
--userdata \\\'host=$src_host, subvolid=$src_subvolid, uuid=$src_uuid\\\' \
|
--userdata \\\'host=$src_host, subvolid=$src_subvolid, uuid=$src_uuid\\\' \
|
||||||
--cleanup-algorithm \'timeline\' \
|
--cleanup-algorithm \'timeline\' \
|
||||||
\'$snapper_target_id\')
|
\'$snapper_target_id\')
|
||||||
else
|
else
|
||||||
ret=$(eval snapper --config $snapper_target_config modify \
|
ret=$(eval snapper --config $snapper_target_config modify \
|
||||||
--description "$snap_description_finished" \
|
--description "$snap_description_finished" \
|
||||||
--userdata "host=$src_host, subvolid=$src_subvolid, uuid=$src_uuid" \
|
--userdata "host=$src_host, subvolid=$src_subvolid, uuid=$src_uuid" \
|
||||||
--cleanup-algorithm "timeline" \
|
--cleanup-algorithm "timeline" \
|
||||||
$snapper_target_id)
|
$snapper_target_id)
|
||||||
fi
|
fi
|
||||||
if [ $verbose -ge 3 ]; then
|
if [ $verbose -ge 3 ]; then
|
||||||
printf "return: '%s'\n" "$ret"
|
printf "return: '%s'\n" "$ret"
|
||||||
@@ -2127,7 +2171,7 @@ run_finalize () {
|
|||||||
fi
|
fi
|
||||||
if [ $snapper_source_id -gt 0 ]; then
|
if [ $snapper_source_id -gt 0 ]; then
|
||||||
cmd="snapper --config $selected_config modify \
|
cmd="snapper --config $selected_config modify \
|
||||||
--description \"$snap_description_synced\" \
|
--description \"$snap_description_synced\" \
|
||||||
--userdata \"backupdir=$backupdir, important=yes, host=$remote, subvolid=$selected_subvol, uuid=$selected_uuid\" \
|
--userdata \"backupdir=$backupdir, important=yes, host=$remote, subvolid=$selected_subvol, uuid=$selected_uuid\" \
|
||||||
--cleanup-algorithm \"timeline\" \
|
--cleanup-algorithm \"timeline\" \
|
||||||
$snapper_source_id"
|
$snapper_source_id"
|
||||||
@@ -2152,7 +2196,7 @@ run_finalize () {
|
|||||||
if [ ${#snapper_source_sync_id} -gt 0 ]; then
|
if [ ${#snapper_source_sync_id} -gt 0 ]; then
|
||||||
# TODO: no snapper method to remove userdata pair, use awk
|
# TODO: no snapper method to remove userdata pair, use awk
|
||||||
cmd="snapper --config $selected_config modify \
|
cmd="snapper --config $selected_config modify \
|
||||||
--description \"$snap_description_finished\" \
|
--description \"$snap_description_finished\" \
|
||||||
--userdata \"important=no\" \
|
--userdata \"important=no\" \
|
||||||
$snapper_source_sync_id"
|
$snapper_source_sync_id"
|
||||||
|
|
||||||
@@ -2208,9 +2252,9 @@ select_target () {
|
|||||||
# print selection table
|
# print selection table
|
||||||
if [ $verbose -ge 2 ]; then
|
if [ $verbose -ge 2 ]; then
|
||||||
if [ -z "$remote" ]; then
|
if [ -z "$remote" ]; then
|
||||||
printf "Selecting a mounted device for backups on your local machine.\n"
|
printf "Selecting a mounted device for backups on your local machine.\n"
|
||||||
else
|
else
|
||||||
printf "Selecting a mounted device for backups on %s.\n" "$remote"
|
printf "Selecting a mounted device for backups on %s.\n" "$remote"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
while [ "$target_id" -eq 0 ] || [ "$target_id" -le $target_count ]; do
|
while [ "$target_id" -eq 0 ] || [ "$target_id" -le $target_count ]; do
|
||||||
@@ -2310,7 +2354,7 @@ select_target () {
|
|||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
if [ "$target_selected" = x ]; then
|
if [ "$target_selected" = x ]; then
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
selected_target=$(eval echo \$target_$target_selected)
|
selected_target=$(eval echo \$target_$target_selected)
|
||||||
@@ -2376,9 +2420,9 @@ select_target_disk () {
|
|||||||
# print selection table
|
# print selection table
|
||||||
if [ $verbose -ge 2 ]; then
|
if [ $verbose -ge 2 ]; then
|
||||||
if [ -z "$remote" ]; then
|
if [ -z "$remote" ]; then
|
||||||
printf "Selecting a mounted BTRFS device for backups on your local machine.\n"
|
printf "Selecting a mounted BTRFS device for backups on your local machine.\n"
|
||||||
else
|
else
|
||||||
printf "Selecting a mounted BTRFS device for backups on %s.\n" "$remote"
|
printf "Selecting a mounted BTRFS device for backups on %s.\n" "$remote"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
while [ "$disk_id" -eq -1 ] || [ "$disk_id" -le $disk_count ]; do
|
while [ "$disk_id" -eq -1 ] || [ "$disk_id" -le $disk_count ]; do
|
||||||
@@ -2450,7 +2494,7 @@ select_target_disk () {
|
|||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
if [ "$disk_selected" = x ]; then
|
if [ "$disk_selected" = x ]; then
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
selected_uuid=$(eval echo \$disk_uuid_$disk_selected)
|
selected_uuid=$(eval echo \$disk_uuid_$disk_selected)
|
||||||
@@ -2507,9 +2551,9 @@ select_target_tape () {
|
|||||||
# print selection table
|
# print selection table
|
||||||
if [ $verbose -ge 2 ]; then
|
if [ $verbose -ge 2 ]; then
|
||||||
if [ -z "$remote" ]; then
|
if [ -z "$remote" ]; then
|
||||||
printf "Selecting a mounted LTFS tape for backups on your local machine.\n"
|
printf "Selecting a mounted LTFS tape for backups on your local machine.\n"
|
||||||
else
|
else
|
||||||
printf "Selecting a mounted LTFS tape for backups on %s.\n" "$remote"
|
printf "Selecting a mounted LTFS tape for backups on %s.\n" "$remote"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
while [ "$tape_id" -eq -1 ] || [ "$tape_id" -le $tape_count ]; do
|
while [ "$tape_id" -eq -1 ] || [ "$tape_id" -le $tape_count ]; do
|
||||||
@@ -2582,7 +2626,7 @@ select_target_tape () {
|
|||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
if [ "$tape_selected" = x ]; then
|
if [ "$tape_selected" = x ]; then
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
selected_tape_id=$(eval echo \$tape_id_$tape_selected)
|
selected_tape_id=$(eval echo \$tape_id_$tape_selected)
|
||||||
@@ -2665,11 +2709,11 @@ Options:
|
|||||||
--label-finished <desc> snapper description tagging successful jobs. Default: "dsnap-sync backup"
|
--label-finished <desc> snapper description tagging successful jobs. Default: "dsnap-sync backup"
|
||||||
--label-running <desc> snapper description tagging active jobs. Default: "dsnap-sync in progress"
|
--label-running <desc> snapper description tagging active jobs. Default: "dsnap-sync in progress"
|
||||||
--label-synced <desc> snapper description tagging last synced jobs
|
--label-synced <desc> snapper description tagging last synced jobs
|
||||||
Default: "dsnap-sync last incremental"
|
Default: "dsnap-sync last incremental"
|
||||||
--color Enable colored output messages
|
--color Enable colored output messages
|
||||||
-c, --config <config> Specify the snapper configuration to use. Otherwise will perform for each snapper
|
-c, --config <config> Specify the snapper configuration to use. Otherwise will perform for each snapper
|
||||||
configuration. You can select multiple configurations
|
configuration. You can select multiple configurations
|
||||||
(e.g. -c "root" -c "home"; --config root --config home)
|
(e.g. -c "root" -c "home"; --config root --config home)
|
||||||
--config-postfix <name> Specify a postfix that will be appended to the destination snapper config name
|
--config-postfix <name> Specify a postfix that will be appended to the destination snapper config name
|
||||||
--dry-run perform a trial run (no changes are written)
|
--dry-run perform a trial run (no changes are written)
|
||||||
--mediapool Specify the name of the tape MediaPool
|
--mediapool Specify the name of the tape MediaPool
|
||||||
@@ -2680,12 +2724,12 @@ Options:
|
|||||||
--noionice Disable setting of I/O class and priority options on target
|
--noionice Disable setting of I/O class and priority options on target
|
||||||
-p, --port <port> The remote port
|
-p, --port <port> The remote port
|
||||||
-r, --remote <address> Send the snapshot backup to a remote machine. The snapshot will be sent via ssh
|
-r, --remote <address> Send the snapshot backup to a remote machine. The snapshot will be sent via ssh
|
||||||
You should specify the remote machine's hostname or ip address. The 'root' user
|
You should specify the remote machine's hostname or ip address. The 'root' user
|
||||||
must be permitted to login on the remote machine
|
must be permitted to login on the remote machine
|
||||||
-s, --subvolid <subvlid> Specify the subvolume id of the mounted BTRFS subvolume to back up to. Defaults to 5
|
-s, --subvolid <subvlid> Specify the subvolume id of the mounted BTRFS subvolume to back up to. Defaults to 5
|
||||||
--use-btrfs-quota use btrfs-quota to calculate snapshot size
|
--use-btrfs-quota use btrfs-quota to calculate snapshot size
|
||||||
-u, --uuid <UUID> Specify the UUID of the mounted BTRFS subvolume to back up to. Otherwise will prompt
|
-u, --uuid <UUID> Specify the UUID of the mounted BTRFS subvolume to back up to. Otherwise will prompt
|
||||||
If multiple mount points are found with the same UUID, will prompt user selection
|
If multiple mount points are found with the same UUID, will prompt user selection
|
||||||
-t, --target <target> Specify the mountpoint of the backup device
|
-t, --target <target> Specify the mountpoint of the backup device
|
||||||
--volumename Specify the name of the tape volume
|
--volumename Specify the name of the tape volume
|
||||||
-v, --verbose Be verbose on what's going on (min: --verbose=1, max: --verbose=3)
|
-v, --verbose Be verbose on what's going on (min: --verbose=1, max: --verbose=3)
|
||||||
@@ -2918,13 +2962,13 @@ verify_snapper_structure () {
|
|||||||
# no inode for given backup_root
|
# no inode for given backup_root
|
||||||
if [ $dryrun -eq 0 ]; then
|
if [ $dryrun -eq 0 ]; then
|
||||||
if [ $verbose -ge 2 ]; then
|
if [ $verbose -ge 2 ]; then
|
||||||
if [ -z "$remote" ]; then
|
if [ -z "$remote" ]; then
|
||||||
printf "${MAGENTA}Create${NO_COLOR} new snapper capable BTRFS ${MAGENTA}subvolume ${GREEN}'%s'${NO_COLOR} ...\n" \
|
printf "${MAGENTA}Create${NO_COLOR} new snapper capable BTRFS ${MAGENTA}subvolume ${GREEN}'%s'${NO_COLOR} ...\n" \
|
||||||
"$backup_root"
|
"$backup_root"
|
||||||
else
|
else
|
||||||
printf "${MAGENTA}Create${NO_COLOR} new snapper capable BTRFS ${MAGENTA}subvolume ${GREEN}'%s'${NO_COLOR} on ${MAGENTA}remote host ${GREEN}'%s'${NO_COLOR} ...\n" \
|
printf "${MAGENTA}Create${NO_COLOR} new snapper capable BTRFS ${MAGENTA}subvolume ${GREEN}'%s'${NO_COLOR} on ${MAGENTA}remote host ${GREEN}'%s'${NO_COLOR} ...\n" \
|
||||||
"$backup_root" "$remote_host"
|
"$backup_root" "$remote_host"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
# verify that we can use the correct snapper template
|
# verify that we can use the correct snapper template
|
||||||
cmd="$ssh stat --format %i $SNAPPER_TEMPLATE_DIR/$snapper_subvolume_template 2>/dev/null"
|
cmd="$ssh stat --format %i $SNAPPER_TEMPLATE_DIR/$snapper_subvolume_template 2>/dev/null"
|
||||||
@@ -2937,7 +2981,7 @@ verify_snapper_structure () {
|
|||||||
#die "snapper template %s to configure the snapper subvolume %s is missing in %s on %s.\n" \
|
#die "snapper template %s to configure the snapper subvolume %s is missing in %s on %s.\n" \
|
||||||
# "$snapper_subvolume_template" "$snapper_config" "$SNAPPER_TEMPLATE_DIR" "$remote_host"
|
# "$snapper_subvolume_template" "$snapper_config" "$SNAPPER_TEMPLATE_DIR" "$remote_host"
|
||||||
fi
|
fi
|
||||||
# create the non existing remote BTRFS subvolume for given config
|
# create the non existing remote BTRFS subvolume for given config
|
||||||
cmd="$ssh btrfs subvolume create $backup_root 1>/dev/null"
|
cmd="$ssh btrfs subvolume create $backup_root 1>/dev/null"
|
||||||
ret=$(eval $cmd)
|
ret=$(eval $cmd)
|
||||||
if [ $? -ne 0 ]; then
|
if [ $? -ne 0 ]; then
|
||||||
@@ -2992,14 +3036,14 @@ verify_snapper_structure () {
|
|||||||
if [ $? -eq 1 ]; then
|
if [ $? -eq 1 ]; then
|
||||||
# path does not exist, let snapper create the structure
|
# path does not exist, let snapper create the structure
|
||||||
# and path $backup_root/.snapshots
|
# and path $backup_root/.snapshots
|
||||||
cmd="$ssh snapper --config $snapper_config create-config \
|
cmd="$ssh snapper --config $snapper_config create-config \
|
||||||
--template $snapper_subvolume_template \
|
--template $snapper_subvolume_template \
|
||||||
--fstype btrfs $backup_root"
|
--fstype btrfs $backup_root"
|
||||||
if [ $verbose -ge 2 ]; then
|
if [ $verbose -ge 2 ]; then
|
||||||
printf "${MAGENTA}Create new BTRFS subvolume ${GREEN}'%s'${NO_COLOR} using template ${GREEN}'%s'${NO_COLOR}\n" \
|
printf "${MAGENTA}Create new BTRFS subvolume ${GREEN}'%s'${NO_COLOR} using template ${GREEN}'%s'${NO_COLOR}\n" \
|
||||||
$snapper_config $snapper_subvolume_template
|
$snapper_config $snapper_subvolume_template
|
||||||
fi
|
fi
|
||||||
$(eval $cmd)
|
$(eval $cmd)
|
||||||
if [ $? -ne 0 ]; then
|
if [ $? -ne 0 ]; then
|
||||||
if [ $remote ]; then
|
if [ $remote ]; then
|
||||||
printf "${RED}Error: ${MAGENTA}Creation of snapper capable config ${GREEN}%s${MAGENTA} on ${GREEN}%s${MAGENTA} failed${NO_COLOR}\n" \
|
printf "${RED}Error: ${MAGENTA}Creation of snapper capable config ${GREEN}%s${MAGENTA} on ${GREEN}%s${MAGENTA} failed${NO_COLOR}\n" \
|
||||||
@@ -3010,8 +3054,8 @@ verify_snapper_structure () {
|
|||||||
fi
|
fi
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
# WIP:
|
# WIP:
|
||||||
# snapper_config exist, now verify if SUBVOLUME needs to be updated
|
# snapper_config exist, now verify if SUBVOLUME needs to be updated
|
||||||
cmd="$ssh snapper list-configs | awk -F '|' '/'\"^$snapper_config\"'/ {print \$1}'"
|
cmd="$ssh snapper list-configs | awk -F '|' '/'\"^$snapper_config\"'/ {print \$1}'"
|
||||||
#cmd="$ssh snapper list-configs | awk '/'\"^$snapper_config\"'/' | awk -F '|' ' /'\$1 == "$snapper_config"'/ {print \$1}'"
|
#cmd="$ssh snapper list-configs | awk '/'\"^$snapper_config\"'/' | awk -F '|' ' /'\$1 == "$snapper_config"'/ {print \$1}'"
|
||||||
@@ -3039,10 +3083,10 @@ verify_snapper_structure () {
|
|||||||
$backup_root/$snapper_snapshots
|
$backup_root/$snapper_snapshots
|
||||||
fi
|
fi
|
||||||
cmd="$ssh btrfs subvolume create $backup_root/$snapper_snapshots 2>/dev/null"
|
cmd="$ssh btrfs subvolume create $backup_root/$snapper_snapshots 2>/dev/null"
|
||||||
ret=$(eval $cmd)
|
ret=$(eval $cmd)
|
||||||
if [ $? -ne 0 ]; then
|
if [ $? -ne 0 ]; then
|
||||||
printf "${RED}Error: ${MAGENTA}Creation of snapper subvolume ${GREEN}%s${MAGENTA} failed${NO_COLOR}\n" \
|
printf "${RED}Error: ${MAGENTA}Creation of snapper subvolume ${GREEN}%s${MAGENTA} failed${NO_COLOR}\n" \
|
||||||
"$backup_root/$snapper_snapshots"
|
"$backup_root/$snapper_snapshots"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
@@ -3083,7 +3127,7 @@ verify_snapper_structure () {
|
|||||||
cmd="$ssh stat --format %i $backup_root/$snapper_snapshots/$snapper_id/$snapper_snapshot_name 2>/dev/null"
|
cmd="$ssh stat --format %i $backup_root/$snapper_snapshots/$snapper_id/$snapper_snapshot_name 2>/dev/null"
|
||||||
ret=$(eval $cmd)
|
ret=$(eval $cmd)
|
||||||
if [ $? -eq 0 ] && [ $ret -ne 256 ]; then
|
if [ $? -eq 0 ] && [ $ret -ne 256 ]; then
|
||||||
# a snapshot path exists, but is not a btrfs snapshot
|
# a snapshot path exists, but is not a btrfs snapshot
|
||||||
if [ -z "$remote" ]; then
|
if [ -z "$remote" ]; then
|
||||||
printf "${RED}Cancel snapshot creation${NO_COLOR}: Directory with id ${GREEN}'%s'${NO_COLOR} already exist in ${BLUE}'%s'${NO_COLOR}, but isn't a btrfs snapshot\n" \
|
printf "${RED}Cancel snapshot creation${NO_COLOR}: Directory with id ${GREEN}'%s'${NO_COLOR} already exist in ${BLUE}'%s'${NO_COLOR}, but isn't a btrfs snapshot\n" \
|
||||||
"$snapper_id" "$backup_root/$snapper_snapshots"
|
"$snapper_id" "$backup_root/$snapper_snapshots"
|
||||||
|
|||||||
404
bin/tape-admin
404
bin/tape-admin
@@ -22,7 +22,7 @@
|
|||||||
# Helper routines for tape handling
|
# Helper routines for tape handling
|
||||||
|
|
||||||
progname="${0##*/}"
|
progname="${0##*/}"
|
||||||
version="0.0.14"
|
version="0.0.15"
|
||||||
|
|
||||||
# global variables
|
# global variables
|
||||||
color=0
|
color=0
|
||||||
@@ -140,7 +140,7 @@ add_retensiondays_to_retensiondate () {
|
|||||||
if [ $? -eq 0 ]; then
|
if [ $? -eq 0 ]; then
|
||||||
cmd="jq --monochrome-output --ascii-output '(.MediaPool[] \
|
cmd="jq --monochrome-output --ascii-output '(.MediaPool[] \
|
||||||
| select(.Name == \"$mediapool_name\") \
|
| select(.Name == \"$mediapool_name\") \
|
||||||
| .Member[$tape_index] \
|
| .Member[$tape_index] \
|
||||||
| .RetensionDate) \
|
| .RetensionDate) \
|
||||||
|= \"$volume_retensiondate\" ' \
|
|= \"$volume_retensiondate\" ' \
|
||||||
${mediapools_json} > $XDG_RUNTIME_DIR/$json_file"
|
${mediapools_json} > $XDG_RUNTIME_DIR/$json_file"
|
||||||
@@ -148,10 +148,10 @@ add_retensiondays_to_retensiondate () {
|
|||||||
if [ $? -eq 0 ]; then
|
if [ $? -eq 0 ]; then
|
||||||
cp "$XDG_RUNTIME_DIR/$json_file" "$mediapools_json"
|
cp "$XDG_RUNTIME_DIR/$json_file" "$mediapools_json"
|
||||||
else
|
else
|
||||||
if [ $verbose -ge 1 ]; then
|
if [ $verbose -ge 1 ]; then
|
||||||
printf "${RED}Error:${MAGENTA} Can't update RetensionDate ${GREEN}'%s'${MAGENTA} for Tape ${GREEN}'%s'${NO_COLOR}\n" \
|
printf "${RED}Error:${MAGENTA} Can't update RetensionDate ${GREEN}'%s'${MAGENTA} for Tape ${GREEN}'%s'${NO_COLOR}\n" \
|
||||||
"$volume_retensiondate" "$volume_name"
|
"$volume_retensiondate" "$volume_name"
|
||||||
fi
|
fi
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
@@ -294,15 +294,15 @@ get_lastwrite () {
|
|||||||
|
|
||||||
# select last write date for given volume
|
# select last write date for given volume
|
||||||
cmd="jq --monochrome-output --ascii-output ' .MediaPool[] \
|
cmd="jq --monochrome-output --ascii-output ' .MediaPool[] \
|
||||||
| select(.Name == \"${mediapool_name}\") \
|
| select(.Name == \"${mediapool_name}\") \
|
||||||
| .Member[] \
|
| .Member[] \
|
||||||
| select(.VolumeName == \"${volume_name}\") \
|
| select(.VolumeName == \"${volume_name}\") \
|
||||||
| .LastWrite ' \
|
| .LastWrite ' \
|
||||||
${mediapools_json}"
|
${mediapools_json}"
|
||||||
else
|
else
|
||||||
# select volume with latest write date
|
# select volume with latest write date
|
||||||
cmd="jq --monochrome-output --ascii-output ' .MediaPool[] \
|
cmd="jq --monochrome-output --ascii-output ' .MediaPool[] \
|
||||||
| select(.Name == \"${mediapool_name}\") \
|
| select(.Name == \"${mediapool_name}\") \
|
||||||
| .Member \
|
| .Member \
|
||||||
| map({ \"VolumeName\" : .VolumeName, \"LastWrite\" : ( .LastWrite | scan(\"[0-9]{14}\")) }) \
|
| map({ \"VolumeName\" : .VolumeName, \"LastWrite\" : ( .LastWrite | scan(\"[0-9]{14}\")) }) \
|
||||||
| sort_by(.LastWrite) \
|
| sort_by(.LastWrite) \
|
||||||
@@ -312,7 +312,7 @@ get_lastwrite () {
|
|||||||
volume_name=$(eval $cmd)
|
volume_name=$(eval $cmd)
|
||||||
volume_name=$(echo $volume_name | sed -e 's/"//g')
|
volume_name=$(echo $volume_name | sed -e 's/"//g')
|
||||||
cmd="jq --monochrome-output --ascii-output ' .MediaPool[] \
|
cmd="jq --monochrome-output --ascii-output ' .MediaPool[] \
|
||||||
| select(.Name == \"${mediapool_name}\") \
|
| select(.Name == \"${mediapool_name}\") \
|
||||||
| .Member \
|
| .Member \
|
||||||
| map({ \"VolumeName\" : .VolumeName, \"LastWrite\" : ( .LastWrite | scan(\"[0-9]{14}\")) }) \
|
| map({ \"VolumeName\" : .VolumeName, \"LastWrite\" : ( .LastWrite | scan(\"[0-9]{14}\")) }) \
|
||||||
| sort_by(.LastWrite) \
|
| sort_by(.LastWrite) \
|
||||||
@@ -351,9 +351,9 @@ get_mediapolicy () {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
cmd="jq --monochrome-output --ascii-output ' .MediaPool[] \
|
cmd="jq --monochrome-output --ascii-output ' .MediaPool[] \
|
||||||
| select(.Name == \"${mediapool_name}\") \
|
| select(.Name == \"${mediapool_name}\") \
|
||||||
| .Member[] \
|
| .Member[] \
|
||||||
| select(.VolumeName == \"${volume_name}\") \
|
| select(.VolumeName == \"${volume_name}\") \
|
||||||
| .MediaPolicy ' \
|
| .MediaPolicy ' \
|
||||||
${mediapools_json}"
|
${mediapools_json}"
|
||||||
volume_mediapolicy=$(eval $cmd)
|
volume_mediapolicy=$(eval $cmd)
|
||||||
@@ -444,8 +444,8 @@ get_mediapool_retensiondays () {
|
|||||||
if [ ${#mediapool_name} -ge 1 ]; then
|
if [ ${#mediapool_name} -ge 1 ]; then
|
||||||
# select default retension days for given pool
|
# select default retension days for given pool
|
||||||
cmd="jq --monochrome-output --ascii-output ' .MediaPool[] \
|
cmd="jq --monochrome-output --ascii-output ' .MediaPool[] \
|
||||||
| select(.Name == \"${mediapool_name}\") \
|
| select(.Name == \"${mediapool_name}\") \
|
||||||
| .DefaultRetensionDays ' \
|
| .DefaultRetensionDays ' \
|
||||||
${mediapools_json}"
|
${mediapools_json}"
|
||||||
fi
|
fi
|
||||||
mediapool_defaultretensiondays=$(eval $cmd)
|
mediapool_defaultretensiondays=$(eval $cmd)
|
||||||
@@ -483,8 +483,8 @@ get_poolmember () {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
cmd="jq --monochrome-output --ascii-output '.MediaPool[] \
|
cmd="jq --monochrome-output --ascii-output '.MediaPool[] \
|
||||||
| select(.Name == \"${mediapool_name}\") \
|
| select(.Name == \"${mediapool_name}\") \
|
||||||
| .Member[].VolumeName' \
|
| .Member[].VolumeName' \
|
||||||
${mediapools_json}"
|
${mediapools_json}"
|
||||||
poolmember=$(eval $cmd)
|
poolmember=$(eval $cmd)
|
||||||
poolmember=$(echo $poolmember | sed -e 's/"//g')
|
poolmember=$(echo $poolmember | sed -e 's/"//g')
|
||||||
@@ -496,16 +496,16 @@ get_poolmember () {
|
|||||||
|
|
||||||
i=0
|
i=0
|
||||||
for i in $poolmember ; do
|
for i in $poolmember ; do
|
||||||
if [ "$volume_name" = "any" ]; then
|
if [ "$volume_name" = "any" ]; then
|
||||||
volume_name=$i
|
volume_name=$i
|
||||||
if [ $verbose -ge 2 ]; then
|
if [ $verbose -ge 2 ]; then
|
||||||
printf "${MAGENTA}selecting first volume_name ${GREEN}'%s'${MAGENTA} from media-pool ${GREEN}'%s'${NO_COLOR}\n" \
|
printf "${MAGENTA}selecting first volume_name ${GREEN}'%s'${MAGENTA} from media-pool ${GREEN}'%s'${NO_COLOR}\n" \
|
||||||
"$i" "$mediapool_name"
|
"$i" "$mediapool_name"
|
||||||
fi
|
fi
|
||||||
return 0
|
return 0
|
||||||
break
|
break
|
||||||
fi
|
fi
|
||||||
if test "$i" = "${volume_name}"; then
|
if test "$i" = "${volume_name}"; then
|
||||||
if [ $verbose -ge 2 ]; then
|
if [ $verbose -ge 2 ]; then
|
||||||
printf "${MAGENTA}volume_name ${GREEN}'%s'${MAGENTA} is member of media-pool ${GREEN}'%s'${NO_COLOR}\n" \
|
printf "${MAGENTA}volume_name ${GREEN}'%s'${MAGENTA} is member of media-pool ${GREEN}'%s'${NO_COLOR}\n" \
|
||||||
"$i" "$mediapool_name"
|
"$i" "$mediapool_name"
|
||||||
@@ -541,7 +541,7 @@ get_poolmember_next () {
|
|||||||
return 1
|
return 1
|
||||||
|
|
||||||
cmd="jq --monochrome-output --ascii-output ' .MediaPool[] \
|
cmd="jq --monochrome-output --ascii-output ' .MediaPool[] \
|
||||||
| select(.Name == \"${mediapool_name}\") \
|
| select(.Name == \"${mediapool_name}\") \
|
||||||
| .Member \
|
| .Member \
|
||||||
| map({ \"VolumeName\" : .VolumeName, \"LastWrite\" : ( .LastWrite | scan(\"[0-9]{14}\")) }) \
|
| map({ \"VolumeName\" : .VolumeName, \"LastWrite\" : ( .LastWrite | scan(\"[0-9]{14}\")) }) \
|
||||||
| sort_by(.LastWrite) \
|
| sort_by(.LastWrite) \
|
||||||
@@ -601,9 +601,9 @@ get_slot () {
|
|||||||
return 1
|
return 1
|
||||||
|
|
||||||
cmd="jq --monochrome-output --ascii-output ' .MediaPool[] \
|
cmd="jq --monochrome-output --ascii-output ' .MediaPool[] \
|
||||||
| select(.Name == \"${mediapool_name}\") \
|
| select(.Name == \"${mediapool_name}\") \
|
||||||
| .Member[] \
|
| .Member[] \
|
||||||
| select(.VolumeName == \"${volume_name}\") \
|
| select(.VolumeName == \"${volume_name}\") \
|
||||||
| .Slot ' \
|
| .Slot ' \
|
||||||
${mediapools_json}"
|
${mediapools_json}"
|
||||||
volume_slot=$(eval $cmd)
|
volume_slot=$(eval $cmd)
|
||||||
@@ -639,9 +639,9 @@ get_retensiondate () {
|
|||||||
return 1
|
return 1
|
||||||
|
|
||||||
cmd="jq --monochrome-output --ascii-output '(.MediaPool[] \
|
cmd="jq --monochrome-output --ascii-output '(.MediaPool[] \
|
||||||
| select(.Name == \"${mediapool_name}\") \
|
| select(.Name == \"${mediapool_name}\") \
|
||||||
| .Member[] \
|
| .Member[] \
|
||||||
| select(.VolumeName == \"${volume_name}\")) \
|
| select(.VolumeName == \"${volume_name}\")) \
|
||||||
| .RetensionDate ' \
|
| .RetensionDate ' \
|
||||||
${mediapools_json}"
|
${mediapools_json}"
|
||||||
volume_retensiondate=$(eval $cmd)
|
volume_retensiondate=$(eval $cmd)
|
||||||
@@ -724,8 +724,8 @@ ltfs_format () {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if [ ${#volume_serial} -eq 0 ]; then
|
if [ ${#volume_serial} -eq 0 ]; then
|
||||||
tape_id=$(echo $volume_name | sed -e 's/\([[:alpha:]]*-\)//g')
|
tape_id=$(echo $volume_name | sed -e 's/\([[:alpha:]]*-\)//g')
|
||||||
# tape_id needs to be exactly 6 character long
|
# tape_id needs to be exactly 6 character long
|
||||||
volume_serial=$(printf "%0.s0" $(seq 1 $((6 - ${#tape_id}))))
|
volume_serial=$(printf "%0.s0" $(seq 1 $((6 - ${#tape_id}))))
|
||||||
volume_serial="${volume_serial}${tape_id}"
|
volume_serial="${volume_serial}${tape_id}"
|
||||||
fi
|
fi
|
||||||
@@ -778,7 +778,7 @@ ltfs_mount () {
|
|||||||
if [ ! -d $ltfs_mountpoint ]; then
|
if [ ! -d $ltfs_mountpoint ]; then
|
||||||
mkdir -p $ltfs_mountpoint
|
mkdir -p $ltfs_mountpoint
|
||||||
fi
|
fi
|
||||||
make_err_file
|
make_err_file
|
||||||
if [ $verbose -ge 2 ]; then
|
if [ $verbose -ge 2 ]; then
|
||||||
printf "${MAGENTA}LTFS mounting tape ${GREEN}'%s'${MAGENTA} to ${GREEN}'%s'${NO_COLOR}\n" \
|
printf "${MAGENTA}LTFS mounting tape ${GREEN}'%s'${MAGENTA} to ${GREEN}'%s'${NO_COLOR}\n" \
|
||||||
"$ltfs_devname" "$ltfs_mountpoint"
|
"$ltfs_devname" "$ltfs_mountpoint"
|
||||||
@@ -791,16 +791,16 @@ ltfs_mount () {
|
|||||||
return 0
|
return 0
|
||||||
else
|
else
|
||||||
# format tape if needed
|
# format tape if needed
|
||||||
if [ -z $volume_name_active ]; then
|
if [ -z $volume_name_active ]; then
|
||||||
slot_source="0"
|
slot_source="0"
|
||||||
mtx_getlabel $slot_source
|
mtx_getlabel $slot_source
|
||||||
fi
|
fi
|
||||||
need_format=$(grep "medium is not partitioned" ${ERRFILE})
|
need_format=$(grep "medium is not partitioned" ${ERRFILE})
|
||||||
rm -f ${ERRFILE}
|
rm -f ${ERRFILE}
|
||||||
if [ ${#need_format} -ge 1 ]; then
|
if [ ${#need_format} -ge 1 ]; then
|
||||||
ltfs_format ${volume_name_active}
|
ltfs_format ${volume_name_active}
|
||||||
ltfs_mount
|
ltfs_mount
|
||||||
fi
|
fi
|
||||||
return $?
|
return $?
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
@@ -901,8 +901,8 @@ ltfs_reformat () {
|
|||||||
fi
|
fi
|
||||||
# wiping: put tape in an unformatted state
|
# wiping: put tape in an unformatted state
|
||||||
ltfs_wipe
|
ltfs_wipe
|
||||||
# RET = 8 -> error?
|
|
||||||
if [ $? -eq 0 ]; then
|
if [ $? -eq 0 ]; then
|
||||||
|
# format: create the ltfs partitions
|
||||||
ltfs_format $volume_name_active $volume_serial
|
ltfs_format $volume_name_active $volume_serial
|
||||||
if [ $? -eq 0 ]; then
|
if [ $? -eq 0 ]; then
|
||||||
ltfs_mount
|
ltfs_mount
|
||||||
@@ -1091,7 +1091,7 @@ mount_tape () {
|
|||||||
|
|
||||||
ltfs_is_mounted
|
ltfs_is_mounted
|
||||||
if test $? -eq 0; then
|
if test $? -eq 0; then
|
||||||
# get date from last written tape in given mediapool
|
# if no explicit tape should be mounted, get date from last written tape in given mediapool
|
||||||
if [ "${#volume_name}" -eq 0 ]; then
|
if [ "${#volume_name}" -eq 0 ]; then
|
||||||
get_lastwrite ${mediapool_name}
|
get_lastwrite ${mediapool_name}
|
||||||
if [ $? != 0 ]; then
|
if [ $? != 0 ]; then
|
||||||
@@ -1106,7 +1106,7 @@ mount_tape () {
|
|||||||
printf "${MAGENTA}Active tape in drive: ${GREEN}%s${NO_COLOR}\n" \
|
printf "${MAGENTA}Active tape in drive: ${GREEN}%s${NO_COLOR}\n" \
|
||||||
"${volume_name_active}"
|
"${volume_name_active}"
|
||||||
fi
|
fi
|
||||||
if [ "${#volume_name_active}" -ge 1 ] && [ "${volume_name_active}" != "${volume_name}" ]; then
|
if [ "${#volume_name_active}" -ge 1 ] && [ "${volume_name_active}" != "${volume_name}" ]; then
|
||||||
if [ $verbose -ge 2 ]; then
|
if [ $verbose -ge 2 ]; then
|
||||||
printf "${MAGENTA}Re-Mounting requested Tape: ${GREEN}%s${NO_COLOR}\n" \
|
printf "${MAGENTA}Re-Mounting requested Tape: ${GREEN}%s${NO_COLOR}\n" \
|
||||||
"${volume_name}"
|
"${volume_name}"
|
||||||
@@ -1128,92 +1128,94 @@ mount_tape () {
|
|||||||
# check if given tape is poolmember of selected pool
|
# check if given tape is poolmember of selected pool
|
||||||
get_poolmember ${mediapool_name} ${volume_name}
|
get_poolmember ${mediapool_name} ${volume_name}
|
||||||
if [ $? -eq 0 ]; then
|
if [ $? -eq 0 ]; then
|
||||||
# volume_name is member of given mediapool
|
# check the mediapolicy for given volume_name
|
||||||
get_mediapolicy ${mediapool_name} ${volume_name_active}
|
get_mediapolicy ${mediapool_name} ${volume_name_active}
|
||||||
if [ ${#volume_mediapolicy} -gt 0 ]; then
|
if [ ${#volume_mediapolicy} -gt 0 ]; then
|
||||||
if [ ${volume_mediapolicy} = "append" ] ; then
|
if [ ${volume_mediapolicy} = "append" ] ; then
|
||||||
if [ $verbose -ge 2 ]; then
|
if [ $verbose -ge 2 ]; then
|
||||||
printf "${MAGENTA}Valid tape mediapolicy: ${GREEN}%s${NO_COLOR}\n" \
|
printf "${MAGENTA}Valid tape mediapolicy: ${GREEN}%s${NO_COLOR}\n" \
|
||||||
"${volume_mediapolicy}"
|
"${volume_mediapolicy}"
|
||||||
fi
|
fi
|
||||||
volume_retensiondate="20180101000000"
|
volume_retensiondate="20180101000000"
|
||||||
get_retensiondate ${mediapool_name} ${volume_name}
|
get_retensiondate ${mediapool_name} ${volume_name}
|
||||||
if [ $? -eq 0 ]; then
|
if [ $? -eq 0 ]; then
|
||||||
date_now=$($date_cmd)
|
date_now=$($date_cmd)
|
||||||
compare_date $date_now $volume_retensiondate
|
compare_date $date_now $volume_retensiondate
|
||||||
if [ $? -eq 2 ]; then
|
if [ $? -eq 2 ]; then
|
||||||
# retensiondate has exposed: use it
|
# retensiondate has exposed: use it
|
||||||
if [ $verbose -ge 3 ]; then
|
if [ $verbose -ge 3 ]; then
|
||||||
printf "${MAGENTA}Valid tape, retensiondate has exposed: ${GREEN}%s${NO_COLOR}\n" \
|
printf "${MAGENTA}Valid tape, retensiondate has exposed: ${GREEN}%s${NO_COLOR}\n" \
|
||||||
"${volume_retensiondate}"
|
"${volume_retensiondate}"
|
||||||
fi
|
fi
|
||||||
|
#ltfs_format ${volume_name_active}
|
||||||
|
ltfs_reformat ${volume_name_active}
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
if [ $? -eq 1 ]; then
|
if [ $? -eq 1 ]; then
|
||||||
# respect active retensiondate: unload given tape
|
# respect active retensiondate: unload given tape
|
||||||
if [ $verbose -ge 3 ]; then
|
if [ $verbose -ge 3 ]; then
|
||||||
printf "${MAGENTA}Invalid tape ${GREEN}%s${MAGANTA}, respect retensiondate: ${GREEN}%s${NO_COLOR}\n" \
|
printf "${MAGENTA}Invalid tape ${GREEN}%s${MAGANTA}, respect retensiondate: ${GREEN}%s${NO_COLOR}\n" \
|
||||||
"${volume_name}" "${volume_retensiondate}"
|
"${volume_name}" "${volume_retensiondate}"
|
||||||
fi
|
fi
|
||||||
ltfs_umount
|
ltfs_umount
|
||||||
mtx_unload
|
mtx_unload
|
||||||
# use next volume_name from pool
|
# use next volume_name from pool
|
||||||
if [ $verbose -ge 3 ]; then
|
if [ $verbose -ge 3 ]; then
|
||||||
printf "${MAGENTA}Get next tape from MediaPool ${GREEN}%s${MAGANTA}\n" \
|
printf "${MAGENTA}Get next tape from MediaPool ${GREEN}%s${MAGANTA}\n" \
|
||||||
"${mediapool_name}"
|
"${mediapool_name}"
|
||||||
fi
|
fi
|
||||||
get_poolmember_next ${mediapool_name} ${volume_name}
|
get_poolmember_next ${mediapool_name} ${volume_name}
|
||||||
get_slot ${mediapool_name} ${volume_name_next}
|
get_slot ${mediapool_name} ${volume_name_next}
|
||||||
mtx_load ${volume_slot}
|
mtx_load ${volume_slot}
|
||||||
ltfs_mount
|
ltfs_mount
|
||||||
if [ $? -eq 0 ]; then
|
if [ $? -eq 0 ]; then
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
if [ ${volume_mediapolicy} = "overwrite" ] ; then
|
if [ ${volume_mediapolicy} = "overwrite" ] ; then
|
||||||
if [ $verbose -ge 2 ]; then
|
if [ $verbose -ge 2 ]; then
|
||||||
printf "${MAGENTA}Valid tape mediapolicy: ${GREEN}%s${NO_COLOR}\n" \
|
printf "${MAGENTA}Valid tape mediapolicy: ${GREEN}%s${NO_COLOR}\n" \
|
||||||
"${volume_mediapolicy}"
|
"${volume_mediapolicy}"
|
||||||
fi
|
fi
|
||||||
volume_retensiondate="20180101000000"
|
volume_retensiondate="20180101000000"
|
||||||
get_retensiondate ${mediapool_name} ${volume_name}
|
get_retensiondate ${mediapool_name} ${volume_name}
|
||||||
date_now=$($date_cmd)
|
date_now=$($date_cmd)
|
||||||
compare_date $date_now $volume_retensiondate
|
compare_date $date_now $volume_retensiondate
|
||||||
if [ $? -eq 2 ]; then
|
if [ $? -eq 2 ]; then
|
||||||
# retensiondate has exposed: wipe given tape
|
# retensiondate has exposed: wipe given tape
|
||||||
if [ $verbose -ge 3 ]; then
|
if [ $verbose -ge 3 ]; then
|
||||||
printf "${MAGENTA}Valid tape, wipe and reformat: ${GREEN}%s${NO_COLOR}\n" \
|
printf "${MAGENTA}Valid tape, wipe and reformat: ${GREEN}%s${NO_COLOR}\n" \
|
||||||
"${volume_name}"
|
"${volume_name}"
|
||||||
fi
|
fi
|
||||||
ltfs_wipe
|
ltfs_wipe
|
||||||
#ltfs_format ${volume_name} ${volume_serial}
|
#ltfs_reformat ${volume_name_active}
|
||||||
if [ $? -eq 0 ]; then
|
if [ $? -eq 0 ]; then
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
if [ $? -eq 1 ]; then
|
if [ $? -eq 1 ]; then
|
||||||
# respect active retensiondate: unload given tape
|
# respect active retensiondate: unload given tape
|
||||||
if [ $verbose -ge 3 ]; then
|
if [ $verbose -ge 3 ]; then
|
||||||
printf "${MAGENTA}Invalid tape ${GREEN}%s${MAGANTA}, respect retensiondate: ${GREEN}%s${NO_COLOR}\n" \
|
printf "${MAGENTA}Invalid tape ${GREEN}%s${MAGANTA}, respect retensiondate: ${GREEN}%s${NO_COLOR}\n" \
|
||||||
"${volume_name}" "${volume_retensiondate}"
|
"${volume_name}" "${volume_retensiondate}"
|
||||||
fi
|
fi
|
||||||
ltfs_umount
|
ltfs_umount
|
||||||
mtx_unload
|
mtx_unload
|
||||||
# use next volume_name from pool
|
# use next volume_name from pool
|
||||||
if [ $verbose -ge 3 ]; then
|
if [ $verbose -ge 3 ]; then
|
||||||
printf "${MAGENTA}Get next tape from MediaPool ${GREEN}%s${MAGANTA}\n" \
|
printf "${MAGENTA}Get next tape from MediaPool ${GREEN}%s${MAGANTA}\n" \
|
||||||
"${mediapool_name}"
|
"${mediapool_name}"
|
||||||
fi
|
fi
|
||||||
get_poolmember_next ${mediapool_name} ${volume_name}
|
get_poolmember_next ${mediapool_name} ${volume_name}
|
||||||
get_slot ${mediapool_name} ${volume_name_next}
|
get_slot ${mediapool_name} ${volume_name_next}
|
||||||
mtx_load ${volume_slot}
|
mtx_load ${volume_slot}
|
||||||
ltfs_mount
|
ltfs_mount
|
||||||
if [ $? -eq 0 ]; then
|
if [ $? -eq 0 ]; then
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
@@ -1258,14 +1260,14 @@ mount_tape () {
|
|||||||
printf "${MAGENTA}Tape in drive: ${GREEN}%s${NO_COLOR}\n" \
|
printf "${MAGENTA}Tape in drive: ${GREEN}%s${NO_COLOR}\n" \
|
||||||
"${volume_name_active}"
|
"${volume_name_active}"
|
||||||
fi
|
fi
|
||||||
if [ "${#volume_name_active}" -gt 1 ] && [ "${volume_name_active}" != "${volume_name}" ]; then
|
if [ "${#volume_name_active}" -gt 1 ] && [ "${volume_name_active}" != "${volume_name}" ]; then
|
||||||
if [ $verbose -ge 2 ]; then
|
if [ $verbose -ge 2 ]; then
|
||||||
printf "${MAGENTA}Active tape ${GREEN}%s${MAGENTA} needs to be exchanged with ${GREEN}%s${NO_COLOR}\n" \
|
printf "${MAGENTA}Active tape ${GREEN}%s${MAGENTA} needs to be exchanged with ${GREEN}%s${NO_COLOR}\n" \
|
||||||
"${volume_name_active}" "${volume_name}"
|
"${volume_name_active}" "${volume_name}"
|
||||||
fi
|
fi
|
||||||
mtx_unload
|
mtx_unload
|
||||||
if [ $? -eq 0 ]; then
|
if [ $? -eq 0 ]; then
|
||||||
mount_tape "${mediapool_name}" "${volume_name}"
|
mount_tape "${mediapool_name}" "${volume_name}"
|
||||||
if [ $? -eq 0 ]; then
|
if [ $? -eq 0 ]; then
|
||||||
return 0
|
return 0
|
||||||
else
|
else
|
||||||
@@ -1287,25 +1289,25 @@ mount_tape () {
|
|||||||
get_mediapolicy ${mediapool_name} ${volume_name}
|
get_mediapolicy ${mediapool_name} ${volume_name}
|
||||||
if [ ${#volume_mediapolicy} -gt 0 ]; then
|
if [ ${#volume_mediapolicy} -gt 0 ]; then
|
||||||
if [ ${volume_mediapolicy} = "append" ] ; then
|
if [ ${volume_mediapolicy} = "append" ] ; then
|
||||||
if [ $verbose -ge 2 ]; then
|
if [ $verbose -ge 2 ]; then
|
||||||
printf "${MAGENTA}Valid tape mediapolicy: ${GREEN}%s${NO_COLOR}\n" \
|
printf "${MAGENTA}Valid tape mediapolicy: ${GREEN}%s${NO_COLOR}\n" \
|
||||||
"${volume_mediapolicy}"
|
"${volume_mediapolicy}"
|
||||||
fi
|
fi
|
||||||
#volume_retensiondate="20180101000000"
|
#volume_retensiondate="20180101000000"
|
||||||
get_retensiondate ${mediapool_name} ${volume_name}
|
get_retensiondate ${mediapool_name} ${volume_name}
|
||||||
date_now=$($date_cmd)
|
date_now=$($date_cmd)
|
||||||
compare_date $date_now $volume_retensiondate
|
compare_date $date_now $volume_retensiondate
|
||||||
RET=$?
|
RET=$?
|
||||||
if [ $RET -eq 2 ]; then
|
if [ $RET -eq 2 ]; then
|
||||||
if [ $verbose -ge 1 ]; then
|
if [ $verbose -ge 1 ]; then
|
||||||
printf "${MAGENTA}RetensionDate has exposed, mount the tape\n"
|
printf "${MAGENTA}RetensionDate has exposed, mount the tape${NO_COLOR}\n"
|
||||||
fi
|
fi
|
||||||
ltfs_mount
|
ltfs_mount
|
||||||
return 0
|
return 0
|
||||||
elif [ $RET -eq 1 ]; then
|
elif [ $RET -eq 1 ]; then
|
||||||
if [ $verbose -ge 1 ]; then
|
if [ $verbose -ge 1 ]; then
|
||||||
printf "${MAGENTA}Tape is bocked via RetensionDate.\n"
|
printf "${MAGENTA}Tape is bocked via RetensionDate.\n"
|
||||||
fi
|
fi
|
||||||
get_poolmember_next "${mediapool_name}"
|
get_poolmember_next "${mediapool_name}"
|
||||||
if test $? -eq 0; then
|
if test $? -eq 0; then
|
||||||
if [ $verbose -ge 2 ]; then
|
if [ $verbose -ge 2 ]; then
|
||||||
@@ -1316,22 +1318,22 @@ mount_tape () {
|
|||||||
mount_tape "${mediapool_name}" "${volume_name_next}"
|
mount_tape "${mediapool_name}" "${volume_name_next}"
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
if [ ${volume_mediapolicy} = "overwrite" ] ; then
|
if [ ${volume_mediapolicy} = "overwrite" ] ; then
|
||||||
volume_retensiondate="20180101000000"
|
volume_retensiondate="20180101000000"
|
||||||
get_retensiondate ${mediapool_name} ${volume_name}
|
get_retensiondate ${mediapool_name} ${volume_name}
|
||||||
date_now=$($date_cmd)
|
date_now=$($date_cmd)
|
||||||
compare_date $date_now $volume_retensiondate
|
compare_date $date_now $volume_retensiondate
|
||||||
if [ $? -eq 2 ]; then
|
if [ $? -eq 2 ]; then
|
||||||
# retensiondate has exposed: wipe given tape
|
# retensiondate has exposed: wipe given tape
|
||||||
ltfs_wipe
|
ltfs_wipe
|
||||||
#ltfs_format ${volume_name} ${volume_serial}
|
ltfs_format ${volume_name} ${volume_serial}
|
||||||
if [ $? -eq 0 ]; then
|
if [ $? -eq 0 ]; then
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
if [ $? -eq 1 ]; then
|
if [ $? -eq 1 ]; then
|
||||||
# respect active retensiondate: unload given tape
|
# respect active retensiondate: unload given tape
|
||||||
mtx_unload
|
mtx_unload
|
||||||
if [ $? -eq 0 ]; then
|
if [ $? -eq 0 ]; then
|
||||||
@@ -1384,9 +1386,9 @@ mtx_getlabel () {
|
|||||||
"${MTX}" "${changer_device}" "${slot_source}"
|
"${MTX}" "${changer_device}" "${slot_source}"
|
||||||
fi
|
fi
|
||||||
volume_name_active=$(perl -ne '
|
volume_name_active=$(perl -ne '
|
||||||
/Data Transfer Element (\d+):Full \(Storage Element (\d+) Loaded\)(:VolumeTag =\s*(.+))?/ && print "$4\n";' ${TMPFILE})
|
/Data Transfer Element (\d+):Full \(Storage Element (\d+) Loaded\)(:VolumeTag =\s*(.+))?/ && print "$4\n";' ${TMPFILE})
|
||||||
volume_name_active=$(echo $volume_name_active | sed -e 's/ *$//g')
|
volume_name_active=$(echo $volume_name_active | sed -e 's/ *$//g')
|
||||||
if [ $verbose -ge 2 ]; then
|
if [ $verbose -ge 2 ] && [ ${#volume_name_active} -gt 0 ]; then
|
||||||
printf "${MAGENTA}Tape in slot ${GREEN}%s${MAGENTA} has Label: ${GREEN}%s${NO_COLOR}\n" \
|
printf "${MAGENTA}Tape in slot ${GREEN}%s${MAGENTA} has Label: ${GREEN}%s${NO_COLOR}\n" \
|
||||||
"${slot_source}" "${volume_name_active}"
|
"${slot_source}" "${volume_name_active}"
|
||||||
fi
|
fi
|
||||||
@@ -1397,8 +1399,8 @@ mtx_getlabel () {
|
|||||||
"${MTX}" "${changer_device}" "${slot_source}"
|
"${MTX}" "${changer_device}" "${slot_source}"
|
||||||
fi
|
fi
|
||||||
volume_name=$(perl -ne '
|
volume_name=$(perl -ne '
|
||||||
/Storage Element ($ENV{"slot_source"}):Full( :VolumeTag=(.+))?/ && print "$3\n";' ${TMPFILE})
|
/Storage Element ($ENV{"slot_source"}):Full( :VolumeTag=(.+))?/ && print "$3\n";' ${TMPFILE})
|
||||||
volume_name=$(echo $volume_name | sed -e 's/ *$//g')
|
volume_name=$(echo $volume_name | sed -e 's/ *$//g')
|
||||||
if [ $verbose -ge 2 ]; then
|
if [ $verbose -ge 2 ]; then
|
||||||
printf "${MAGENTA}Tape in slot ${GREEN}%s${MAGENTA} has Label: ${GREEN}%s${NO_COLOR}\n" \
|
printf "${MAGENTA}Tape in slot ${GREEN}%s${MAGENTA} has Label: ${GREEN}%s${NO_COLOR}\n" \
|
||||||
"${slot_source}" "${volume_name}"
|
"${slot_source}" "${volume_name}"
|
||||||
@@ -2030,7 +2032,7 @@ update_lastwrite () {
|
|||||||
if [ $? -eq 0 ]; then
|
if [ $? -eq 0 ]; then
|
||||||
cmd="jq --monochrome-output --ascii-output '(.MediaPool[] \
|
cmd="jq --monochrome-output --ascii-output '(.MediaPool[] \
|
||||||
| select(.Name == \"$mediapool_name\") \
|
| select(.Name == \"$mediapool_name\") \
|
||||||
| .Member[$tape_index] \
|
| .Member[$tape_index] \
|
||||||
| .LastWrite) \
|
| .LastWrite) \
|
||||||
|= \"$volume_lastwrite\" ' \
|
|= \"$volume_lastwrite\" ' \
|
||||||
${mediapools_json} > $XDG_RUNTIME_DIR/$json_file"
|
${mediapools_json} > $XDG_RUNTIME_DIR/$json_file"
|
||||||
@@ -2082,10 +2084,10 @@ update_mediapool_retensiondays () {
|
|||||||
if [ $? -eq 0 ]; then
|
if [ $? -eq 0 ]; then
|
||||||
cp "$XDG_RUNTIME_DIR/$json_file" "$mediapools_json"
|
cp "$XDG_RUNTIME_DIR/$json_file" "$mediapools_json"
|
||||||
else
|
else
|
||||||
if [ $verbose -ge 1 ]; then
|
if [ $verbose -ge 1 ]; then
|
||||||
printf "${RED}Error:${MAGENTA} Can't update DefaultRetensinDays ${GREEN}'%s'${MAGENTA} in media-pool file ${GREEN}'%s'${NO_COLOR}\n" \
|
printf "${RED}Error:${MAGENTA} Can't update DefaultRetensinDays ${GREEN}'%s'${MAGENTA} in media-pool file ${GREEN}'%s'${NO_COLOR}\n" \
|
||||||
"$mediapool_defaultretensiondays" "$mediapools_json"
|
"$mediapool_defaultretensiondays" "$mediapools_json"
|
||||||
fi
|
fi
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
@@ -2138,7 +2140,7 @@ update_retensiondate () {
|
|||||||
if [ $? -eq 0 ]; then
|
if [ $? -eq 0 ]; then
|
||||||
cmd="jq --monochrome-output --ascii-output '(.MediaPool[] \
|
cmd="jq --monochrome-output --ascii-output '(.MediaPool[] \
|
||||||
| select(.Name == \"$mediapool_name\") \
|
| select(.Name == \"$mediapool_name\") \
|
||||||
| .Member[$tape_index] \
|
| .Member[$tape_index] \
|
||||||
| .RetensionDate) \
|
| .RetensionDate) \
|
||||||
|= \"$volume_retensiondate\" ' \
|
|= \"$volume_retensiondate\" ' \
|
||||||
${mediapools_json} > $XDG_RUNTIME_DIR/$json_file"
|
${mediapools_json} > $XDG_RUNTIME_DIR/$json_file"
|
||||||
@@ -2146,10 +2148,10 @@ update_retensiondate () {
|
|||||||
if [ $? -eq 0 ]; then
|
if [ $? -eq 0 ]; then
|
||||||
cp "$XDG_RUNTIME_DIR/$json_file" "$mediapools_json"
|
cp "$XDG_RUNTIME_DIR/$json_file" "$mediapools_json"
|
||||||
else
|
else
|
||||||
if [ $verbose -ge 1 ]; then
|
if [ $verbose -ge 1 ]; then
|
||||||
printf "${RED}Error:${MAGENTA} Can't update RetensionDate ${GREEN}'%s'${MAGENTA} for Tape ${GREEN}'%s'${NO_COLOR}\n" \
|
printf "${RED}Error:${MAGENTA} Can't update RetensionDate ${GREEN}'%s'${MAGENTA} for Tape ${GREEN}'%s'${NO_COLOR}\n" \
|
||||||
"$volume_retensiondate" "$volume_name"
|
"$volume_retensiondate" "$volume_name"
|
||||||
fi
|
fi
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
@@ -2171,62 +2173,62 @@ Usage: $progname [options]
|
|||||||
|
|
||||||
Options:
|
Options:
|
||||||
--add-retensiondays add RetensionDays to LastWrite attribute for given TapeName in Pool (JSON-File)
|
--add-retensiondays add RetensionDays to LastWrite attribute for given TapeName in Pool (JSON-File)
|
||||||
(input attribute: <mediapool> <volume_name> <days>)
|
(input attribute: <mediapool> <volume_name> <days>)
|
||||||
--color Enable colored output messages
|
--color Enable colored output messages
|
||||||
--get-lastwrite extract LastWrite attribute from given Pool member (JSON-File)
|
--get-lastwrite extract LastWrite attribute from given Pool member (JSON-File)
|
||||||
(input attribute: <mediapool> [<volume_name>])
|
(input attribute: <mediapool> [<volume_name>])
|
||||||
without given volume_name, extract Pool member that was last witten to
|
without given volume_name, extract Pool member that was last witten to
|
||||||
--get-mediapool-name extract MediaPool name for given VolumeName from configuration (JSON-File)
|
--get-mediapool-name extract MediaPool name for given VolumeName from configuration (JSON-File)
|
||||||
(input attribute: <volume_name>)
|
(input attribute: <volume_name>)
|
||||||
--get-mediapools extract MediaPool names from configuration (JSON-File)
|
--get-mediapools extract MediaPool names from configuration (JSON-File)
|
||||||
--get-mediapolicy extract MediaPolicy attribute from Pool configuration (JSON-File)
|
--get-mediapolicy extract MediaPolicy attribute from Pool configuration (JSON-File)
|
||||||
(input attribute: <mediapool> [<volume_name>])
|
(input attribute: <mediapool> [<volume_name>])
|
||||||
--get-poolmember extract VolumeName attribute from Pool configuration (JSON-File)
|
--get-poolmember extract VolumeName attribute from Pool configuration (JSON-File)
|
||||||
(input attribute: <mediapool> [<volume_name>])
|
(input attribute: <mediapool> [<volume_name>])
|
||||||
--get-poolmember-next extract VolumeName for next usable Pool member (JSON-File)
|
--get-poolmember-next extract VolumeName for next usable Pool member (JSON-File)
|
||||||
(input attribute: <mediapool> [volume_name])
|
(input attribute: <mediapool> [volume_name])
|
||||||
--get-retensiondate extract RetensionDate attribute from Pool configuration (JSON-File)
|
--get-retensiondate extract RetensionDate attribute from Pool configuration (JSON-File)
|
||||||
(input attribute: <mediapool> [<volume_name>])
|
(input attribute: <mediapool> [<volume_name>])
|
||||||
--get-retensiondays extract DefaultRetensionDays attribute from Pool configuration (JSON-File)
|
--get-retensiondays extract DefaultRetensionDays attribute from Pool configuration (JSON-File)
|
||||||
(input attribute: <mediapool>)
|
(input attribute: <mediapool>)
|
||||||
--get-slot extract Slot attribute from Pool configuration (JSON-File)
|
--get-slot extract Slot attribute from Pool configuration (JSON-File)
|
||||||
(input attribute: <mediapool> [<volume_name>])
|
(input attribute: <mediapool> [<volume_name>])
|
||||||
--ltfs-getattribute report ltfs extended attribute for mounted tape
|
--ltfs-getattribute report ltfs extended attribute for mounted tape
|
||||||
(input attribute: <ltfs_attribute>)
|
(input attribute: <ltfs_attribute>)
|
||||||
--ltfs-format format tape
|
--ltfs-format format tape
|
||||||
(input attribute: <volume_name> <tape_id>)
|
(input attribute: <volume_name> <tape_id>)
|
||||||
--ltfs-is-mounted returns true, if ltfs tape is already mounted
|
--ltfs-is-mounted returns true, if ltfs tape is already mounted
|
||||||
--ltfs-mount mount a ltfs tape (returns true on success)
|
--ltfs-mount mount a ltfs tape (returns true on success)
|
||||||
--ltfs-reformat reformat mounted tape
|
--ltfs-reformat reformat mounted tape
|
||||||
(input attribute: [<volume_name>])
|
(input attribute: [<volume_name>])
|
||||||
--ltfs-umount unmount a ltfs tape (returns true on success)
|
--ltfs-umount unmount a ltfs tape (returns true on success)
|
||||||
--media-change Update RetensionDate for last written Pool-Tape and und exchange tapes in slots
|
--media-change Update RetensionDate for last written Pool-Tape and und exchange tapes in slots
|
||||||
(input attribute: <mediapool> [<volume_name>])
|
(input attribute: <mediapool> [<volume_name>])
|
||||||
--mtx-exchange exchange tapes in slots
|
--mtx-exchange exchange tapes in slots
|
||||||
(input attribute: <slot_source> <slot_target>)
|
(input attribute: <slot_source> <slot_target>)
|
||||||
--mtx-getlabel report tape label/barcode for tape in drive
|
--mtx-getlabel report tape label/barcode for tape in drive
|
||||||
(input attribute: <slot_source>)
|
(input attribute: <slot_source>)
|
||||||
--mtx-inventory run inquriy task for tape-changer
|
--mtx-inventory run inquriy task for tape-changer
|
||||||
--mtx-load load a tape to target slot
|
--mtx-load load a tape to target slot
|
||||||
(input attribute: <slot_source>)
|
(input attribute: <slot_source>)
|
||||||
--mtx-status list changer slot status
|
--mtx-status list changer slot status
|
||||||
--mtx-transfer transfer a tape to target slot
|
--mtx-transfer transfer a tape to target slot
|
||||||
(input attribute: <slot_source> <slot_target>)
|
(input attribute: <slot_source> <slot_target>)
|
||||||
--mtx-unload unload a tape
|
--mtx-unload unload a tape
|
||||||
(input attribute: slot_source drive)
|
(input attribute: slot_source drive)
|
||||||
--mount make tape accessible for OS
|
--mount make tape accessible for OS
|
||||||
(input attribute: <mediapool_name> [<volume_name>])
|
(input attribute: <mediapool_name> [<volume_name>])
|
||||||
-q, --quiet Be quiet
|
-q, --quiet Be quiet
|
||||||
--update-lastwrite update LastWrite attribute for given TapeName in Pool (JSON-File)
|
--update-lastwrite update LastWrite attribute for given TapeName in Pool (JSON-File)
|
||||||
if no datestring is specified, use "now"
|
if no datestring is specified, use "now"
|
||||||
(input attribute: <mediapool> <volume_name> [<YYYYMMDDHHMMSS> )
|
(input attribute: <mediapool> <volume_name> [<YYYYMMDDHHMMSS> )
|
||||||
--update-retensiondate update RetensionDate attribute for given TapeName in Pool (JSON-File)
|
--update-retensiondate update RetensionDate attribute for given TapeName in Pool (JSON-File)
|
||||||
if no datestring is specified, use "now"
|
if no datestring is specified, use "now"
|
||||||
(input attribute: <mediapool> <volume_name> [<YYYYMMDDHHMMSS> )
|
(input attribute: <mediapool> <volume_name> [<YYYYMMDDHHMMSS> )
|
||||||
--update-retensiondays update DefaultRetensionDays attribute for given Pool (JSON-File)
|
--update-retensiondays update DefaultRetensionDays attribute for given Pool (JSON-File)
|
||||||
(input attribute: <mediapool>)
|
(input attribute: <mediapool>)
|
||||||
--use-mtx use mtx loader handling. If not specified, all mtx commands will use
|
--use-mtx use mtx loader handling. If not specified, all mtx commands will use
|
||||||
default device ($default_changer_device)
|
default device ($default_changer_device)
|
||||||
-v, --verbose Be verbose on what's going on (min: --verbose=1, max: --verbose=3)
|
-v, --verbose Be verbose on what's going on (min: --verbose=1, max: --verbose=3)
|
||||||
--version show program version
|
--version show program version
|
||||||
EOF
|
EOF
|
||||||
@@ -2273,7 +2275,7 @@ case $cmd in
|
|||||||
"${volume_name}" "${volume_date}"
|
"${volume_name}" "${volume_date}"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
get-lastwrite)
|
get-lastwrite)
|
||||||
valid_member=0
|
valid_member=0
|
||||||
get_lastwrite "${mediapool_name}" "${volume_name}"
|
get_lastwrite "${mediapool_name}" "${volume_name}"
|
||||||
@@ -2289,7 +2291,7 @@ case $cmd in
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
get-mediapolicy)
|
get-mediapolicy)
|
||||||
get_mediapolicy "${mediapool_name}" "${volume_name}"
|
get_mediapolicy "${mediapool_name}" "${volume_name}"
|
||||||
if test $? -gt 0; then
|
if test $? -gt 0; then
|
||||||
@@ -2300,7 +2302,7 @@ case $cmd in
|
|||||||
"${volume_name}" "${volume_mediapolicy}"
|
"${volume_name}" "${volume_mediapolicy}"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
get-mediapool-name)
|
get-mediapool-name)
|
||||||
get_mediapool_name "${volume_name}"
|
get_mediapool_name "${volume_name}"
|
||||||
if test $? -gt 0; then
|
if test $? -gt 0; then
|
||||||
@@ -2311,7 +2313,7 @@ case $cmd in
|
|||||||
"${mediapool_name}"
|
"${mediapool_name}"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
get-mediapools)
|
get-mediapools)
|
||||||
get_mediapool_names
|
get_mediapool_names
|
||||||
if test $? -gt 0; then
|
if test $? -gt 0; then
|
||||||
@@ -2322,7 +2324,7 @@ case $cmd in
|
|||||||
"${mediapool_names}"
|
"${mediapool_names}"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
get-poolmember)
|
get-poolmember)
|
||||||
valid_member=0
|
valid_member=0
|
||||||
get_poolmember "${mediapool_name}" "${volume_name}"
|
get_poolmember "${mediapool_name}" "${volume_name}"
|
||||||
@@ -2335,7 +2337,7 @@ case $cmd in
|
|||||||
fi
|
fi
|
||||||
valid_member=1
|
valid_member=1
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
get-poolmember-next)
|
get-poolmember-next)
|
||||||
valid_member=0
|
valid_member=0
|
||||||
get_poolmember_next "${mediapool_name}" "${volume_name}"
|
get_poolmember_next "${mediapool_name}" "${volume_name}"
|
||||||
@@ -2347,7 +2349,7 @@ case $cmd in
|
|||||||
"${mediapool_name}" "${volume_name_next}"
|
"${mediapool_name}" "${volume_name_next}"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
get-mediapool-retensiondays)
|
get-mediapool-retensiondays)
|
||||||
get_mediapool_retensiondays "${mediapool_name}"
|
get_mediapool_retensiondays "${mediapool_name}"
|
||||||
if test $? -gt 0; then
|
if test $? -gt 0; then
|
||||||
@@ -2358,7 +2360,7 @@ case $cmd in
|
|||||||
"${mediapool_name}" "${mediapool_defaultretensiondays}"
|
"${mediapool_name}" "${mediapool_defaultretensiondays}"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
get-retensiondate)
|
get-retensiondate)
|
||||||
get_retensiondate "${mediapool_name}" "${volume_name}"
|
get_retensiondate "${mediapool_name}" "${volume_name}"
|
||||||
if test $? -gt 0; then
|
if test $? -gt 0; then
|
||||||
@@ -2371,7 +2373,7 @@ case $cmd in
|
|||||||
"${volume_name}" "${volume_date}"
|
"${volume_name}" "${volume_date}"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
get-slot)
|
get-slot)
|
||||||
get_slot "${mediapool_name}" "${volume_name}"
|
get_slot "${mediapool_name}" "${volume_name}"
|
||||||
if test $? -eq 0; then
|
if test $? -eq 0; then
|
||||||
@@ -2381,7 +2383,7 @@ case $cmd in
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
exit $?
|
exit $?
|
||||||
;;
|
;;
|
||||||
ltfs-format)
|
ltfs-format)
|
||||||
ltfs_format "${volume_name}" "${tape_id}"
|
ltfs_format "${volume_name}" "${tape_id}"
|
||||||
if test $? -gt 0; then
|
if test $? -gt 0; then
|
||||||
@@ -2405,78 +2407,72 @@ case $cmd in
|
|||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
ltfs-is-mounted)
|
ltfs-is-mounted)
|
||||||
|
if ! $quiet; then
|
||||||
|
printf "${MAGENTA}LTFS tape mount checke\n"
|
||||||
|
fi
|
||||||
ltfs_is_mounted
|
ltfs_is_mounted
|
||||||
if test $? -gt 0; then
|
if test $? -gt 0; then
|
||||||
exit 1
|
exit 1
|
||||||
else
|
|
||||||
if ! $quiet; then
|
|
||||||
printf "${MAGENTA}LTFS Tape is-mounted: ${GREEN}true${NO_COLOR}\n"
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
ltfs-mount)
|
ltfs-mount)
|
||||||
|
if ! $quiet; then
|
||||||
|
printf "${MAGENTA}LTFS mount Tape\n"
|
||||||
|
fi
|
||||||
ltfs_mount
|
ltfs_mount
|
||||||
if test $? -gt 0; then
|
if test $? -gt 0; then
|
||||||
exit 1
|
exit 1
|
||||||
else
|
|
||||||
if ! $quiet; then
|
|
||||||
printf "${MAGENTA}LTFS Tape mount: ${GREEN}true${NO_COLOR}\n"
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
ltfs-reformat)
|
ltfs-reformat)
|
||||||
|
if ! $quiet; then
|
||||||
|
printf "${MAGENTA}LTFS Tape reformat: ${GREEN}%s${NO_COLOR}\n" \
|
||||||
|
"${volume_name}"
|
||||||
|
fi
|
||||||
ltfs_reformat "${volume_name}"
|
ltfs_reformat "${volume_name}"
|
||||||
if test $? -gt 0; then
|
if test $? -gt 0; then
|
||||||
return 1
|
return 1
|
||||||
else
|
|
||||||
if ! $quiet; then
|
|
||||||
printf "${MAGENTA}LTFS Tape reformat: ${GREEN}%s${NO_COLOR}\n" \
|
|
||||||
"${volume_name}"
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
ltfs-umount)
|
ltfs-umount)
|
||||||
|
if ! $quiet; then
|
||||||
|
printf "${MAGENTA}LTFS Tape unmount: ${GREEN}true${NO_COLOR}\n"
|
||||||
|
fi
|
||||||
ltfs_umount
|
ltfs_umount
|
||||||
if test $? -gt 0; then
|
if test $? -gt 0; then
|
||||||
exit 1
|
exit 1
|
||||||
else
|
|
||||||
if ! $quiet; then
|
|
||||||
printf "${MAGENTA}LTFS Tape unmount: ${GREEN}true${NO_COLOR}\n"
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
media-change)
|
media-change)
|
||||||
|
if ! $quiet; then
|
||||||
|
if [ ${#volume_name} -ge 1 ]; then
|
||||||
|
printf "${MAGENTA}Media change in pool: ${GREEN}%s${NO_COLOR} (Volume-Name: ${GREEN}%s${NO_COLOR})\n" \
|
||||||
|
"${mediapool_name}" "${volume_name}"
|
||||||
|
else
|
||||||
|
printf "${MAGENTA}Media change in pool: ${GREEN}%s${NO_COLOR}\n" \
|
||||||
|
"${mediapool_name}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
media_change $mediapool_name $volume_name
|
media_change $mediapool_name $volume_name
|
||||||
if test $? -gt 0; then
|
if test $? -gt 0; then
|
||||||
return 1
|
return 1
|
||||||
else
|
|
||||||
if ! $quiet; then
|
|
||||||
if [ ${#volume_name} -ge 1 ]; then
|
|
||||||
printf "${MAGENTA}Media changed in pool: ${GREEN}%s${NO_COLOR} (Volume-Name: ${GREEN}%s${NO_COLOR})\n" \
|
|
||||||
"${mediapool_name}" "${volume_name}"
|
|
||||||
else
|
|
||||||
printf "${MAGENTA}Media changed in pool: ${GREEN}%s${NO_COLOR}\n" \
|
|
||||||
"${mediapool_name}"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
mount)
|
mount)
|
||||||
mount_tape "${mediapool_name}" "${volume_name}"
|
if ! $quiet; then
|
||||||
if test $? -gt 0; then
|
if test ${#volume_name} -ge 1; then
|
||||||
exit 1
|
printf "${MAGENTA}Mount tape ${GREEN}'%s'${MAGENTA} for ${GREEN}'%s'${NO_COLOR}\n" \
|
||||||
else
|
"${volume_name}" "${mediapool_name}"
|
||||||
if ! $quiet; then
|
else
|
||||||
if test ${#volume_name} -ge 1; then
|
printf "${MAGENTA}Mount next tape for mediapool ${GREEN}'%s'${NO_COLOR}\n" \
|
||||||
printf "${MAGENTA}Tape ${GREEN}'%s'${MAGENTA} for ${GREEN}'%s'${MAGENTA} mounted${NO_COLOR}\n" \
|
"${mediapool_name}"
|
||||||
"${volume_name}" "${mediapool_name}"
|
|
||||||
else
|
|
||||||
printf "${MAGENTA}Next tape for mediapool ${GREEN}'%s'${MAGENTA} mounted${NO_COLOR}\n" \
|
|
||||||
"${mediapool_name}"
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
;;
|
mount_tape "${mediapool_name}" "${volume_name}"
|
||||||
|
if test $? -gt 0; then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
;;
|
||||||
mtx-exchange)
|
mtx-exchange)
|
||||||
mtx_exchange "${slot_source}" "${slot_target}"
|
mtx_exchange "${slot_source}" "${slot_target}"
|
||||||
exit $?
|
exit $?
|
||||||
@@ -2519,7 +2515,7 @@ case $cmd in
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
update-mediapool-retensiondays)
|
update-mediapool-retensiondays)
|
||||||
update_mediapool_retensiondays "${mediapool_name}" "${mediapool_defaultretensiondays}"
|
update_mediapool_retensiondays "${mediapool_name}" "${mediapool_defaultretensiondays}"
|
||||||
if test $? -gt 0; then
|
if test $? -gt 0; then
|
||||||
@@ -2530,7 +2526,7 @@ case $cmd in
|
|||||||
"${mediapool_name}" "${mediapool_defaultretensiondays}"
|
"${mediapool_name}" "${mediapool_defaultretensiondays}"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
update-retensiondate)
|
update-retensiondate)
|
||||||
update_retensiondate "${mediapool_name}" "${volume_name}" "${date_string}"
|
update_retensiondate "${mediapool_name}" "${volume_name}" "${date_string}"
|
||||||
if test $? -gt 0; then
|
if test $? -gt 0; then
|
||||||
@@ -2545,5 +2541,5 @@ case $cmd in
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|||||||
@@ -3,6 +3,13 @@
|
|||||||
|
|
||||||
# dsnap-sync
|
# dsnap-sync
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<span>English</span> |
|
||||||
|
<a href="../..">Englisch</a>
|
||||||
|
<!-- a href="../spanish">Spanisch</a> | -->
|
||||||
|
<a href="lang/german">Deutsch</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
## Über
|
## Über
|
||||||
|
|
||||||
`dsnap-sync` ist konzipiert, um Backups für btrfs formatierte Dateisysteme
|
`dsnap-sync` ist konzipiert, um Backups für btrfs formatierte Dateisysteme
|
||||||
@@ -138,17 +145,17 @@ Folgende Tools werden verwendet:
|
|||||||
erforderlich. Über ein Makefile wird die Installation an den
|
erforderlich. Über ein Makefile wird die Installation an den
|
||||||
richtigen Ziel-Pfad gesteuert.
|
richtigen Ziel-Pfad gesteuert.
|
||||||
|
|
||||||
# make install
|
# make install
|
||||||
|
|
||||||
Sollte Ihr System einen unüblichen Speicherort für die snapper
|
Sollte Ihr System einen unüblichen Speicherort für die snapper
|
||||||
Konfigurationen verwenden, kann der Pfad in einer Umgebungs-Variable
|
Konfigurationen verwenden, kann der Pfad in einer Umgebungs-Variable
|
||||||
für die Installation einbezogen werden (`SNAPPER_CONFIG`).
|
für die Installation einbezogen werden (`SNAPPER_CONFIG`).
|
||||||
|
|
||||||
Arch Linux/Fedora/Gentoo:
|
Arch Linux/Fedora/Gentoo:
|
||||||
# make SNAPPER_CONFIG=/etc/conf.d/snapper install
|
# make SNAPPER_CONFIG=/etc/conf.d/snapper install
|
||||||
|
|
||||||
Debian/Ubuntu:
|
Debian/Ubuntu:
|
||||||
# make SNAPPER_CONFIG=/etc/default/snapper install
|
# make SNAPPER_CONFIG=/etc/default/snapper install
|
||||||
|
|
||||||
Die lokalen `snapper` Konfiguration werden um ein neues Template
|
Die lokalen `snapper` Konfiguration werden um ein neues Template
|
||||||
'dsnap-sync' ergänzt.
|
'dsnap-sync' ergänzt.
|
||||||
@@ -172,41 +179,41 @@ Software Paket Manager.
|
|||||||
|
|
||||||
## Optionen
|
## Optionen
|
||||||
|
|
||||||
Usage: dsnap-sync [options]
|
Usage: dsnap-sync [options]
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
-a, --automount <path> start automount for given path to get a valid target mountpoint.
|
-a, --automount <path> start automount for given path to get a valid target mountpoint.
|
||||||
-b, --backupdir <prefix> backupdir is a relative path that will be appended to target backup-root
|
-b, --backupdir <prefix> backupdir is a relative path that will be appended to target backup-root
|
||||||
--backuptype <type> Specify backup type <archive | child | parent>
|
--backuptype <type> Specify backup type <archive | child | parent>
|
||||||
--batch no user interaction
|
--batch no user interaction
|
||||||
-d, --description <desc> Change the snapper description. Default: "latest incremental backup"
|
-d, --description <desc> Change the snapper description. Default: "latest incremental backup"
|
||||||
--label-finished <desc> snapper description tagging successful jobs. Default: "dsnap-sync backup"
|
--label-finished <desc> snapper description tagging successful jobs. Default: "dsnap-sync backup"
|
||||||
--label-running <desc> snapper description tagging active jobs. Default: "dsnap-sync in progress"
|
--label-running <desc> snapper description tagging active jobs. Default: "dsnap-sync in progress"
|
||||||
--label-synced <desc> snapper description tagging last synced jobs.
|
--label-synced <desc> snapper description tagging last synced jobs.
|
||||||
Default: "dsnap-sync last incremental"
|
Default: "dsnap-sync last incremental"
|
||||||
--color Enable colored output messages
|
--color Enable colored output messages
|
||||||
-c, --config <config> Specify the snapper configuration to use. Otherwise will perform for each snapper
|
-c, --config <config> Specify the snapper configuration to use. Otherwise will perform for each snapper
|
||||||
configuration. You can select multiple configurations
|
configuration. You can select multiple configurations
|
||||||
(e.g. -c "root" -c "home"; --config root --config home)
|
(e.g. -c "root" -c "home"; --config root --config home)
|
||||||
--config-postfix <name> Specify a postfix that will be appended to the destination snapper config name.
|
--config-postfix <name> Specify a postfix that will be appended to the destination snapper config name.
|
||||||
--dry-run perform a trial run (no changes are written).
|
--dry-run perform a trial run (no changes are written).
|
||||||
--mediapool Specify the name of the tape MediaPool
|
--mediapool Specify the name of the tape MediaPool
|
||||||
-n, --noconfirm Do not ask for confirmation for each configuration. Will still prompt for backup
|
-n, --noconfirm Do not ask for confirmation for each configuration. Will still prompt for backup
|
||||||
--nonotify Disable graphical notification (via dbus)
|
--nonotify Disable graphical notification (via dbus)
|
||||||
--nopv Disable graphical progress output (disable pv)
|
--nopv Disable graphical progress output (disable pv)
|
||||||
--noionice Disable setting of I/O class and priority options on target
|
--noionice Disable setting of I/O class and priority options on target
|
||||||
-r, --remote <address> Send the snapshot backup to a remote machine. The snapshot will be sent via ssh
|
-r, --remote <address> Send the snapshot backup to a remote machine. The snapshot will be sent via ssh
|
||||||
You should specify the remote machine's hostname or ip address. The 'root' user
|
You should specify the remote machine's hostname or ip address. The 'root' user
|
||||||
must be permitted to login on the remote machine
|
must be permitted to login on the remote machine
|
||||||
-p, --port <port> The remote port
|
-p, --port <port> The remote port
|
||||||
-s, --subvolid <subvlid> Specify the subvolume id of the mounted BTRFS subvolume to back up to. Defaults to 5.
|
-s, --subvolid <subvlid> Specify the subvolume id of the mounted BTRFS subvolume to back up to. Defaults to 5.
|
||||||
--use-btrfs-quota use btrfs-quota to calculate snapshot size
|
--use-btrfs-quota use btrfs-quota to calculate snapshot size
|
||||||
-u, --uuid <UUID> Specify the UUID of the mounted BTRFS subvolume to back up to. Otherwise will prompt
|
-u, --uuid <UUID> Specify the UUID of the mounted BTRFS subvolume to back up to. Otherwise will prompt
|
||||||
If multiple mount points are found with the same UUID, will prompt for user selection
|
If multiple mount points are found with the same UUID, will prompt for user selection
|
||||||
-t, --target <target> Specify the mountpoint of the backup device
|
-t, --target <target> Specify the mountpoint of the backup device
|
||||||
--volumename Specify the name of the tape volume
|
--volumename Specify the name of the tape volume
|
||||||
-v, --verbose Be verbose on what's going on (min: --verbose=1, max: --verbose=3)
|
-v, --verbose Be verbose on what's going on (min: --verbose=1, max: --verbose=3)
|
||||||
--version show program version
|
--version show program version
|
||||||
|
|
||||||
## Erster Sicherungslauf
|
## Erster Sicherungslauf
|
||||||
|
|
||||||
@@ -264,7 +271,7 @@ sorgen. Folgende Sicherungstypen werden unterschieden:
|
|||||||
* ein Unterverzeichnis des Konfigurations-Namens (`archive-<config-name>`)
|
* ein Unterverzeichnis des Konfigurations-Namens (`archive-<config-name>`)
|
||||||
* ein Unterverzeichnis der Snapshot-ID (`<snapper-id>`)
|
* ein Unterverzeichnis der Snapshot-ID (`<snapper-id>`)
|
||||||
* der aktuelle btrfs Stream wird im Unterverzeichnis abgelegt
|
* der aktuelle btrfs Stream wird im Unterverzeichnis abgelegt
|
||||||
(`<snapper-id>_[full | incremental].btrfs`)
|
(`<snapper-id>_[full | incremental].btrfs`)
|
||||||
* die Metadaten des Prozesses werden in der Datei `info.xml` abgelegt
|
* die Metadaten des Prozesses werden in der Datei `info.xml` abgelegt
|
||||||
|
|
||||||
Steht `ltfs` zur Verfügung, ist ein Backup auf Bänder möglich.
|
Steht `ltfs` zur Verfügung, ist ein Backup auf Bänder möglich.
|
||||||
@@ -357,4 +364,4 @@ Diese Arbeit ist unter der [Creative Common License 4.0][License-CC_BY] lizensie
|
|||||||
![Creative Common Logo][Logo-CC_BY]
|
![Creative Common Logo][Logo-CC_BY]
|
||||||
|
|
||||||
© 2016, 2017 James W. Barnett;
|
© 2016, 2017 James W. Barnett;
|
||||||
© 2017 - 2018 Ralf Zerres
|
© 2017 - 2019 Ralf Zerres
|
||||||
|
|||||||
Reference in New Issue
Block a user