Skip to content

Instantly share code, notes, and snippets.

@fumiyas
Last active February 1, 2023 10:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fumiyas/fa608bc3e7d0b3b4927c86cab4ab0ce4 to your computer and use it in GitHub Desktop.
Save fumiyas/fa608bc3e7d0b3b4927c86cab4ab0ce4 to your computer and use it in GitHub Desktop.
雑な要件を聞いて実装した雑なリモートバックアップスクリプト
#!/bin/bash
##
## ファイルバックアップ over SSH (雑)
## Copyright (c) 2023 SATOH Fumiyasu @ OSSTech Crop., Japan
##
## License: GNU General Public License version 3
##
## NOTE: SSH 経由で任意のコマンドを実行可能。過剰なアクセス権と言える。
## 本来ならセキュリティを考慮して制限すべき。流用はお勧めしない。
## https://github.com/fumiyas/adhoc-backup など
## (osstech-support パッケージにも入っている) でローカルバックアップして、
## そのバックアップディレクトリを rsync over SSH すればよいのでは?
## それなら authorized_keys(5) で rsync サーバーのみ実行に限定できるし、
## rsyncd.conf(5) で書き込み先限定かつ読み出し不可にできる。
##
set -u
set -o pipefail || exit $? ## bash 3.0+
perr() {
echo "$0: ERROR: $1" 1>&2
}
pdie() {
perr "$1"
exit "${2-1}"
}
## ======================================================================
[[ -n ${BACKUP_DEBUG-} ]] && set -x
timestamp=$(date +%Y%m%d)
## バックアップ元 (バックアップ対象)
src_host=$(uname -n |sed 's/\..*//') || pdie "Failed to examine hostname: $?" $?
src_user="${BACKUP_SRC_USER:-backup}"
## バックアップ先 (SSH 経由のリモートホスト)
dst_host="${BACKUP_DST_HOST:-backup}"
dst_port="${BACKUP_DST_PORT:-22}"
dst_user="${BACKUP_DST_USER:-backup}"
dst_dir="${BACKUP_DST_DIR:-/var/backup/$src_host}"
dst_compress="${BACKUP_DST_COMPRESS:-gzip}"
dst_prefix="${BACKUP_DST_PREFIX:-}"
dst_suffix="${BACKUP_DST_SUFFIX:-.tar.gz}"
dst_umask="${BACKUP_DST_UMASK:-0077}"
dst_age="${BACKUP_DST_AGE:-30}"
## ----------------------------------------------------------------------
if [[ $# -eq 0 ]]; then
echo "Usage: $0 BACKUP_SOURCE_DIR [...]"
exit 1
fi
src_dirs=("$@")
## ======================================================================
src_dirs_filtered=()
for src_dir in "${src_dirs[@]}"; do
src_dirs_filtered+=("${src_dir#/}")
done
ssh_args=(
setpriv
--reuid "$src_user"
--regid "$src_user"
--init-groups
ssh
-p "$dst_port"
-o 'BatchMode yes'
-o 'GSSAPIAuthentication no'
-o 'TCPKeepAlive yes'
-o 'ServerAliveInterval 59'
"$dst_user@$dst_host"
)
## ----------------------------------------------------------------------
cd / || pdie "Failed to change working directory: $?" $?
dst_bash_script=$(
[[ $- == *x* ]] && echo 'set -x'
cat <<'EOF'
set -u
set -e
IFS= read -r dst_dir
IFS= read -r dst_basename
IFS= read -r dst_suffix
IFS= read -r dst_umask
IFS= read -r dst_age
umask "$dst_umask"
tmp_suffix=".tmp"
dst_file="$dst_dir/$dst_basename$dst_suffix"
dst_tmpfile="$dst_file.$$$tmp_suffix"
## 前回実行時の一時ファイルが残っていたら削除
find "$dst_dir" -mindepth 1 -maxdepth 1 -name "*$tmp_suffix" -type f -mtime +1 -delete
cat >"$dst_tmpfile"
mv "$dst_tmpfile" "$dst_file"
## 古いバックアップを削除
find "$dst_dir" -mindepth 1 -maxdepth 1 -name "*$dst_suffix" -type f -mtime "$dst_age" -delete
EOF
)
(
echo "$dst_dir"
echo "$dst_prefix$timestamp"
echo "$dst_suffix"
echo "$dst_umask"
echo "$((dst_age + 1))"
tar -c -f - "${src_dirs_filtered[@]}" |"$dst_compress"
) \
|"${ssh_args[@]}" "$dst_bash_script" \
|| pdie "Failed to backup: $?" $?
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment