Last active
February 1, 2023 10:04
-
-
Save fumiyas/fa608bc3e7d0b3b4927c86cab4ab0ce4 to your computer and use it in GitHub Desktop.
雑な要件を聞いて実装した雑なリモートバックアップスクリプト
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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