首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用BorgBackup进行用户备份的Bash脚本

使用BorgBackup进行用户备份的Bash脚本
EN

Code Review用户
提问于 2020-11-11 16:49:09
回答 1查看 633关注 0票数 6

我使用BorgBackup来处理个人计算机的备份。下面是一个bash脚本,它创建我的系统对各种不同目标的备份。我对bash没有什么经验,我希望能得到一些关于最佳实践和可能的安全问题/意外的边缘案例的提示。

一个具体的问题是需要取消环境变量(特别是BORG_PASSPHRASE),就像我所看到的人们所做的(例如这里),根据我的理解,这不应该是必要的,因为环境只是本地的。

理想情况下,我还希望自动确保Borg存储库的完整性。我知道有borg check,我可以时不时地运行,但是我不确定在使用create时这是否是必要的,D3应该已经确保存储库处于健康状态了吗?

关于以下守则的一些说明:

  • noti是一个非常简单的i3status通知脚本,但是可以用任何其他的脚本来替换。
  • 一些路径和名称被替换为假名。
  • 对于borg create的错误,我无法正确退出,因为我备份/etc,其中一些文件有错误的权限,BorgBackup会抛出错误
  • 代码中的TODO注释是我在某个时候可能想要研究的东西,但是代码现在起作用了。

Bash脚本:

代码语言:javascript
复制
#!/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

示例配置文件:

代码语言:javascript
复制
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 ...
EN

回答 1

Code Review用户

发布于 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,以帮助避免由于错误或意外失败的命令而继续使用意外状态的常见错误。

票数 2
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/251952

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档