我使用BorgBackup来处理个人计算机的备份。下面是一个bash脚本,它创建我的系统对各种不同目标的备份。我对bash没有什么经验,我希望能得到一些关于最佳实践和可能的安全问题/意外的边缘案例的提示。
一个具体的问题是需要取消环境变量(特别是BORG_PASSPHRASE),就像我所看到的人们所做的(例如这里),根据我的理解,这不应该是必要的,因为环境只是本地的。
理想情况下,我还希望自动确保Borg存储库的完整性。我知道有borg check,我可以时不时地运行,但是我不确定在使用create时这是否是必要的,D3应该已经确保存储库处于健康状态了吗?
关于以下守则的一些说明:
noti是一个非常简单的i3status通知脚本,但是可以用任何其他的脚本来替换。borg create的错误,我无法正确退出,因为我备份/etc,其中一些文件有错误的权限,BorgBackup会抛出错误Bash脚本:
#!/bin/bash
# User data backup script using BorgBackup with options for different target repositories
# usage: backup.sh
# Each target must have a configuration file backup-.conf that provides:
# - pre- and posthook functions
# - $repository - path to a valid borg repository or were one should be created
# - $backup - paths or exclusion paths
# - $pruning - borg pruning scheme
# Additional borg environment variables may be provided and will not be overwritten.
# Output is logged to LOGFILE="$HOME/.local/log/backup/"
# INSTALLATION
# Place script and all target configs in $HOME/.local/scripts
# $HOME/.config/systemd/user/borg-backup.service
# ```
# [Unit]
# Description=Borg User Backup
# [Service]
# Environment=SSH_AUTH_SOCK=/run/user/1000/keyring/ssh
# ExecStart=%h/.local/scripts/backup.sh target1
# Nice=19
# IOSchedulingClass=2
# IOSchedulingPriority=7
# ```
#
# $HOME/.config/systemd/user/borg-backup.timer
# ```
# [Unit]
# Description=Borg User Backup Timer
# [Timer]
# OnCalendar=*-*-* 8:00:00
# Persistent=true
# RandomizedDelaySec=10min
# WakeSystem=false
# [Install]
# WantedBy=timers.target
# ```
# $ systemctl --user import-environment PATH
# reload the daemon
# $ systemctl --user daemon-reload
# start the timer with
# $ systemctl --user start borg-backup.timer
# and confirm that it is running
# $ systemctl --user list-timer
# you can also run the service manually with
# $ systemctl --user start borg-backup
function error () {
RED='\033[0;91m'
NC='\033[0m'
printf "${RED}%s${NC}\n" "${1}"
notify-send -u critical "Borg" "Backup failed: ${1}"
noti rm "BACKUP"
noti add "BACKUP FAILED"
exit 1
}
## Targets
if [ $# -lt 1 ]; then
echo "$0: Missing arguments"
echo "usage: $0 targetname"
exit 1
fi
case "$1" in
"target1"|"target2"|"target3")
target="$1"
;;
*)
error "Unknown target"
;;
esac
# TODO abort if specified target is already running
# exit if borg is already running, maybe previous run didn't finish
#if pidof -x borg >/dev/null; then
# error "Backup already running."
#fi
## Logging and notification
# notify about running backup
noti add "BACKUP"
# write output to logfile
log="$HOME/.local/log/backup/backup-$(date +%Y-%m-%d-%H%M%S).log"
exec > >(tee -i "$log")
exec 2>&1
echo "$target"
## Global Prehook
# create list of installed software
pacman -Qeq > "$HOME/.local/log/package_list.txt"
# create list of non backed up resources
ls -R "$HOME/misc/" > "$HOME/.local/log/resources_list.txt"
# create list of music titles
ls -R "$HOME/music/" > "$HOME/music/music_list.txt"
## Global Config
# set repository passphrase
export BORG_PASSCOMMAND="cat $HOME/passwd.txt"
compression="lz4"
## Target specific Prehook and Config
CONFIGDIR="$HOME/.local/scripts"
source "$CONFIGDIR"/backup-"$target".conf
# TODO make non mandatory and only run if it is defined
prehook || error "prehook failed"
## Borg
# TODO use env variables in configs instead?
# export BORG_REPO=$1
# export BORG_REMOTE_PATH=borg1
# borg create ::'{hostname}-{utcnow:%Y-%m-%dT%H:%M:%S}' $HOME
SECONDS=0
echo "Begin of backup $(date)."
borg create \
--verbose \
--stats \
--progress \
--compression $compression \
"$repository"::"{hostname}-{utcnow:%Y-%m-%d-%H%M%S}" \
$backup
# || error "borg failed"
# use prune subcommand to maintain archives of this machine
borg prune \
--verbose \
--list \
--progress \
"$repository" \
--prefix "{hostname}-" \
$pruning \
|| error "prune failed"
echo "End of backup $(date). Duration: $SECONDS Seconds"
## Cleanup
posthook
noti rm "BACKUP"
echo "Finished"
exit 0示例配置文件:
backup="$HOME
--exclude $HOME/movie
--exclude $HOME/.cache
--exclude $HOME/.local/lib
--exclude $HOME/.thumbnails
--exclude $HOME/.Xauthority
"
pruning="--keep-daily=6 --keep-weekly=6 --keep-monthly=6"
repository="/run/media/username/DRIVE"
prehook() { :; } # e.g. mount drives/network storage
posthook() { :; } # unmount ...发布于 2022-08-20 10:26:53
RED='\033[0;91m' NC='\033[0m' printf "${RED}%s${NC}\n" "${1}"
请不要像那样硬编码终端特定的转义序列。标准输出不一定是终端,也不一定是您所期望的终端。我建议您使用适当的tput setaf命令为实际使用的输出流生成适当的序列。该消息不应该转到错误流,而不是输出流吗?
我建议使用set -u,也可能推荐set -e,以帮助避免由于错误或意外失败的命令而继续使用意外状态的常见错误。
https://codereview.stackexchange.com/questions/251952
复制相似问题