Refine backup script

This commit is contained in:
2026-02-01 23:27:21 +08:00
parent 33df613807
commit 7b805a1795
12 changed files with 283 additions and 247 deletions

View File

@@ -1,35 +0,0 @@
#!/bin/sh
DOCKER_DIR="/lvm1/docker"
CONTAINER_NAME="adguardhome"
CONTAINER_DIR="$DOCKER_DIR/$CONTAINER_NAME"
SAVE_PATH="/media/backup/backup_docker/$CONTAINER_NAME/files"
NOW_DATETIME="$(date +'%Y%m%d_%H%M%S')"
BACKUP_FILENAME="backup_${CONTAINER_NAME}_$NOW_DATETIME.tar"
BACKUP_FILE_PATH="$SAVE_PATH/$BACKUP_FILENAME"
BACKUP_CMD="sudo tar cvf $BACKUP_FILENAME $CONTAINER_NAME"
echo "DOCKER_DIR: $DOCKER_DIR"
echo "CONTAINER_DIR: $CONTAINER_DIR"
echo "SAVE_PATH: $SAVE_PATH"
echo "NOW_DATETIME: $NOW_DATETIME"
echo "BACKUP_FILENAME: $BACKUP_FILENAME"
echo "BACKUP_FILE_PATH: $BACKUP_FILE_PATH"
echo "BACKUP_CMD: $BACKUP_CMD"
echo "$(date +'%F %R:%S'): Backup start. BACKUP_CMD = $BACKUP_CMD"
mkdir -p $SAVE_PATH
sudo docker compose -f ${CONTAINER_DIR}/docker-compose.yml down
cd $DOCKER_DIR
$BACKUP_CMD
sudo docker compose -f ${CONTAINER_DIR}/docker-compose.yml up -d
## Move BACKUP_FILENAME to BACKUP_FILE_PATH
echo "rsync -ah --progress $BACKUP_FILENAME $SAVE_PATH"
rsync -ah --progress $BACKUP_FILENAME $SAVE_PATH
## Delete local backup file
echo "rm $BACKUP_FILENAME"
rm -f $BACKUP_FILENAME
echo "$(date +'%F %R:%S'): Backup finished."

74
backup_docker.sh Executable file
View File

@@ -0,0 +1,74 @@
#!/bin/sh
# Check if container name is provided
if [ -z "$1" ]; then
echo "Usage: $0 <container_name> [--exclude=<DIR_NAME>]"
echo "Example: $0 immich"
echo "Example: $0 immich --exclude=immich/nasphoto"
exit 1
fi
DOCKER_DIR="/DATA01/dockers"
CONTAINER_NAME="$1"
CONTAINER_DIR="$DOCKER_DIR/$CONTAINER_NAME"
EXCLUDE_OPTION=""
# Parse exclude option if provided
if [ -n "$2" ]; then
case "$2" in
--exclude=*)
EXCLUDE_DIR="${2#--exclude=}"
EXCLUDE_OPTION="--exclude $EXCLUDE_DIR"
;;
*)
echo "錯誤: 無效的參數: $2"
echo "Usage: $0 <container_name> [--exclude=<DIR_NAME>]"
exit 1
;;
esac
fi
# Check if container directory exists
if [ ! -d "$CONTAINER_DIR" ]; then
echo "錯誤: 容器目錄不存在: $CONTAINER_DIR"
echo "無法備份一個目錄不存在的 docker"
exit 1
fi
echo "$(date +'%F %R:%S'): Backup start."
SAVE_PATH="/nas/Backup/backup_docker/$CONTAINER_NAME/files"
NOW_DATETIME="$(date +'%Y%m%d_%H%M%S')"
BACKUP_FILENAME="backup_${CONTAINER_NAME}_$NOW_DATETIME.tar"
BACKUP_FILE_PATH="$SAVE_PATH/$BACKUP_FILENAME"
BACKUP_CMD="sudo tar -cv $EXCLUDE_OPTION -f $BACKUP_FILENAME $CONTAINER_NAME"
echo "DOCKER_DIR: $DOCKER_DIR"
echo "CONTAINER_DIR: $CONTAINER_DIR"
echo "SAVE_PATH: $SAVE_PATH"
echo "NOW_DATETIME: $NOW_DATETIME"
echo "BACKUP_FILENAME: $BACKUP_FILENAME"
echo "BACKUP_FILE_PATH: $BACKUP_FILE_PATH"
echo "BACKUP_CMD: $BACKUP_CMD"
echo "$(date +'%F %R:%S'): Backup start. BACKUP_CMD = $BACKUP_CMD"
echo pwd=$(pwd)
mkdir -p $SAVE_PATH
## Clean up old backups before creating new one, keep only the newest 4 files
echo "$(date +'%F %R:%S'): Cleaning up old backups before backup..."
/home/awin/scripts/newestN.sh -d="$SAVE_PATH" -n=4 --confirm=0
sudo docker compose -f ${CONTAINER_DIR}/docker-compose.yml down
cd $DOCKER_DIR
$BACKUP_CMD
sudo docker compose -f ${CONTAINER_DIR}/docker-compose.yml up -d
## Move BACKUP_FILENAME to BACKUP_FILE_PATH
echo "rsync -avh --progress $BACKUP_FILENAME $SAVE_PATH"
rsync -ah --progress $BACKUP_FILENAME $SAVE_PATH
## Delete local backup file
echo "rm $BACKUP_FILENAME"
rm -f $BACKUP_FILENAME
echo "$(date +'%F %R:%S'): Backup finished."

View File

@@ -1,18 +0,0 @@
#!/bin/bash
BACKUP_FOLDER=/media/backup/backup_awin-pc2/dotfiles/
BACKUP_ITEMS=(
'/home/awin/.bashrc'
'/home/awin/.config'
'/home/awin/.ssh'
'/home/awin/.vimrc'
)
for item in "${BACKUP_ITEMS[@]}"
do
cp -r -p $item $BACKUP_FOLDER
done

View File

@@ -1,35 +0,0 @@
#!/bin/sh
DOCKER_DIR="/lvm1/docker"
CONTAINER_NAME="filebrowser"
CONTAINER_DIR="$DOCKER_DIR/$CONTAINER_NAME"
SAVE_PATH="/media/backup/backup_docker/$CONTAINER_NAME/files"
NOW_DATETIME="$(date +'%Y%m%d_%H%M%S')"
BACKUP_FILENAME="backup_${CONTAINER_NAME}_$NOW_DATETIME.tar"
BACKUP_FILE_PATH="$SAVE_PATH/$BACKUP_FILENAME"
BACKUP_CMD="sudo tar cvf $BACKUP_FILENAME $CONTAINER_NAME"
echo "DOCKER_DIR: $DOCKER_DIR"
echo "CONTAINER_DIR: $CONTAINER_DIR"
echo "SAVE_PATH: $SAVE_PATH"
echo "NOW_DATETIME: $NOW_DATETIME"
echo "BACKUP_FILENAME: $BACKUP_FILENAME"
echo "BACKUP_FILE_PATH: $BACKUP_FILE_PATH"
echo "BACKUP_CMD: $BACKUP_CMD"
echo "$(date +'%F %R:%S'): Backup start. BACKUP_CMD = $BACKUP_CMD"
mkdir -p $SAVE_PATH
sudo docker compose -f ${CONTAINER_DIR}/docker-compose.yml down
cd $DOCKER_DIR
$BACKUP_CMD
sudo docker compose -f ${CONTAINER_DIR}/docker-compose.yml up -d
## Move BACKUP_FILENAME to BACKUP_FILE_PATH
echo "rsync -ah --progress $BACKUP_FILENAME $SAVE_PATH"
rsync -ah --progress $BACKUP_FILENAME $SAVE_PATH
## Delete local backup file
echo "rm $BACKUP_FILENAME"
rm -f $BACKUP_FILENAME
echo "$(date +'%F %R:%S'): Backup finished."

View File

@@ -1,35 +0,0 @@
#!/bin/sh
DOCKER_DIR="/lvm1/docker"
CONTAINER_NAME="freshrss"
CONTAINER_DIR="$DOCKER_DIR/$CONTAINER_NAME"
SAVE_PATH="/media/backup/backup_docker/$CONTAINER_NAME/files"
NOW_DATETIME="$(date +'%Y%m%d_%H%M%S')"
BACKUP_FILENAME="backup_${CONTAINER_NAME}_$NOW_DATETIME.tar"
BACKUP_FILE_PATH="$SAVE_PATH/$BACKUP_FILENAME"
BACKUP_CMD="sudo tar cvf $BACKUP_FILENAME $CONTAINER_NAME"
echo "DOCKER_DIR: $DOCKER_DIR"
echo "CONTAINER_DIR: $CONTAINER_DIR"
echo "SAVE_PATH: $SAVE_PATH"
echo "NOW_DATETIME: $NOW_DATETIME"
echo "BACKUP_FILENAME: $BACKUP_FILENAME"
echo "BACKUP_FILE_PATH: $BACKUP_FILE_PATH"
echo "BACKUP_CMD: $BACKUP_CMD"
echo "$(date +'%F %R:%S'): Backup start. BACKUP_CMD = $BACKUP_CMD"
mkdir -p $SAVE_PATH
sudo docker compose -f ${CONTAINER_DIR}/docker-compose.yml down
cd $DOCKER_DIR
$BACKUP_CMD
sudo docker compose -f ${CONTAINER_DIR}/docker-compose.yml up -d
## Move BACKUP_FILENAME to BACKUP_FILE_PATH
echo "rsync -ah --progress $BACKUP_FILENAME $SAVE_PATH"
rsync -ah --progress $BACKUP_FILENAME $SAVE_PATH
## Delete local backup file
echo "rm $BACKUP_FILENAME"
rm -f $BACKUP_FILENAME
echo "$(date +'%F %R:%S'): Backup finished."

View File

@@ -1,35 +0,0 @@
#!/bin/sh
DOCKER_DIR="/lvm1/docker"
CONTAINER_NAME="gitea"
CONTAINER_DIR="$DOCKER_DIR/$CONTAINER_NAME"
SAVE_PATH="/media/backup/backup_docker/$CONTAINER_NAME/files"
NOW_DATETIME="$(date +'%Y%m%d_%H%M%S')"
BACKUP_FILENAME="backup_${CONTAINER_NAME}_$NOW_DATETIME.tar"
BACKUP_FILE_PATH="$SAVE_PATH/$BACKUP_FILENAME"
BACKUP_CMD="sudo tar cvf $BACKUP_FILENAME $CONTAINER_NAME"
echo "DOCKER_DIR: $DOCKER_DIR"
echo "CONTAINER_DIR: $CONTAINER_DIR"
echo "SAVE_PATH: $SAVE_PATH"
echo "NOW_DATETIME: $NOW_DATETIME"
echo "BACKUP_FILENAME: $BACKUP_FILENAME"
echo "BACKUP_FILE_PATH: $BACKUP_FILE_PATH"
echo "BACKUP_CMD: $BACKUP_CMD"
echo "$(date +'%F %R:%S'): Backup start. BACKUP_CMD = $BACKUP_CMD"
mkdir -p $SAVE_PATH
sudo docker compose -f ${CONTAINER_DIR}/docker-compose.yml down
cd $DOCKER_DIR
$BACKUP_CMD
sudo docker compose -f ${CONTAINER_DIR}/docker-compose.yml up -d
## Move BACKUP_FILENAME to BACKUP_FILE_PATH
echo "rsync -ah --progress $BACKUP_FILENAME $SAVE_PATH"
rsync -ah --progress $BACKUP_FILENAME $SAVE_PATH
## Delete local backup file
echo "rm $BACKUP_FILENAME"
rm -f $BACKUP_FILENAME
echo "$(date +'%F %R:%S'): Backup finished."

View File

@@ -1,38 +0,0 @@
#!/bin/sh
echo "$(date +'%F %R:%S'): Backup start."
DOCKER_DIR="/lvm1/docker"
CONTAINER_NAME="immich"
CONTAINER_DIR="$DOCKER_DIR/$CONTAINER_NAME"
SAVE_PATH="/media/backup/backup_docker/$CONTAINER_NAME/files"
NOW_DATETIME="$(date +'%Y%m%d_%H%M%S')"
BACKUP_FILENAME="backup_${CONTAINER_NAME}_$NOW_DATETIME.tar"
BACKUP_FILE_PATH="$SAVE_PATH/$BACKUP_FILENAME"
BACKUP_CMD="sudo tar -cv --exclude immich/nasphoto -f $BACKUP_FILENAME $CONTAINER_NAME"
echo "DOCKER_DIR: $DOCKER_DIR"
echo "CONTAINER_DIR: $CONTAINER_DIR"
echo "SAVE_PATH: $SAVE_PATH"
echo "NOW_DATETIME: $NOW_DATETIME"
echo "BACKUP_FILENAME: $BACKUP_FILENAME"
echo "BACKUP_FILE_PATH: $BACKUP_FILE_PATH"
echo "BACKUP_CMD: $BACKUP_CMD"
echo "$(date +'%F %R:%S'): Backup start. BACKUP_CMD = $BACKUP_CMD"
echo pwd=$(pwd)
mkdir -p $SAVE_PATH
sudo docker compose -f ${CONTAINER_DIR}/docker-compose.yml down
cd $DOCKER_DIR
$BACKUP_CMD
sudo docker compose -f ${CONTAINER_DIR}/docker-compose.yml up -d
## Move BACKUP_FILENAME to BACKUP_FILE_PATH
echo "rsync -avh --progress $BACKUP_FILENAME $SAVE_PATH"
rsync -ah --progress $BACKUP_FILENAME $SAVE_PATH
## Delete local backup file
echo "rm $BACKUP_FILENAME"
rm -f $BACKUP_FILENAME
echo "$(date +'%F %R:%S'): Backup finished."

View File

@@ -1,35 +0,0 @@
#!/bin/sh
DOCKER_DIR="/lvm1/docker"
CONTAINER_NAME="nextcloud"
CONTAINER_DIR="$DOCKER_DIR/$CONTAINER_NAME"
SAVE_PATH="/media/backup/backup_docker/$CONTAINER_NAME/files"
NOW_DATETIME="$(date +'%Y%m%d_%H%M%S')"
BACKUP_FILENAME="backup_${CONTAINER_NAME}_$NOW_DATETIME.tar"
BACKUP_FILE_PATH="$SAVE_PATH/$BACKUP_FILENAME"
BACKUP_CMD="sudo tar cvf $BACKUP_FILENAME $CONTAINER_NAME"
echo "DOCKER_DIR: $DOCKER_DIR"
echo "CONTAINER_DIR: $CONTAINER_DIR"
echo "SAVE_PATH: $SAVE_PATH"
echo "NOW_DATETIME: $NOW_DATETIME"
echo "BACKUP_FILENAME: $BACKUP_FILENAME"
echo "BACKUP_FILE_PATH: $BACKUP_FILE_PATH"
echo "BACKUP_CMD: $BACKUP_CMD"
echo "$(date +'%F %R:%S'): Backup start. BACKUP_CMD = $BACKUP_CMD"
mkdir -p $SAVE_PATH
sudo docker compose -f ${CONTAINER_DIR}/docker-compose.yml down
cd $DOCKER_DIR
$BACKUP_CMD
sudo docker compose -f ${CONTAINER_DIR}/docker-compose.yml up -d
## Move BACKUP_FILENAME to BACKUP_FILE_PATH
echo "rsync -ah --progress $BACKUP_FILENAME $SAVE_PATH"
rsync -ah --progress $BACKUP_FILENAME $SAVE_PATH
## Delete local backup file
echo "rm $BACKUP_FILENAME"
rm -f $BACKUP_FILENAME
echo "$(date +'%F %R:%S'): Backup finished."

View File

@@ -1,13 +0,0 @@
#!/bin/sh
NOW_DATETIME="$(date +'%Y%m%d_%H%M%S')"
SAVE_FOLDER="/media/upload/pi_backup"
SAVE_FILENAME="pi4_$NOW_DATETIME.img"
CMD="sudo /home/awin/bin/image-utils/image-backup -i $SAVE_FOLDER/$SAVE_FILENAME"
LOG_FILE="/home/awin/log/backup_pi4.log"
mkdir -p $SAVE_FOLDER
echo "$(date +'%F %R:%S'): Backup start. CMD = $CMD" > $LOG_FILE
$CMD
echo "$(date +'%F %R:%S'): Backup finished." >> $LOG_FILE

54
check_nas_dir.sh Executable file
View File

@@ -0,0 +1,54 @@
#!/bin/bash
# 定義幫助訊息函數
usage() {
echo "用法: sudo $0 <掛載路徑> <日誌檔案路徑>"
echo "範例: sudo $0 /nas/Backup /var/log/nas_check.log"
exit 1
}
# 檢查參數數量,如果少於 2 個則顯示 help
if [ "$#" -ne 2 ]; then
usage
fi
MOUNT_PATH=$1
LOG_FILE=$2
# 確保 log 檔案的目錄存在
LOG_DIR=$(dirname "$LOG_FILE")
if [ ! -d "$LOG_DIR" ]; then
mkdir -p "$LOG_DIR"
fi
# 取得目前時間
TIMESTAMP=$(date "+%Y-%m-%d %H:%M:%S")
# --- 核心檢查邏輯 ---
# 1. 檢查目錄是否為掛載點
# 2. 檢查目錄是否可正常存取 (ls),避免 Stale File Handle 或連線僵死
if mountpoint -q "$MOUNT_PATH" && ls "$MOUNT_PATH" > /dev/null 2>&1; then
# 狀態正常
exit 0
else
# 狀態異常,開始修復
echo "[$TIMESTAMP] 偵測到 $MOUNT_PATH 掛載異常,準備修復..." >> "$LOG_FILE"
# 嘗試強制卸載 (Lazy unmount)
# 使用 -l 可以即刻解除目錄占用,解決 "Device or resource busy"
umount -l "$MOUNT_PATH" > /dev/null 2>&1
# 重新掛載 (讀取 /etc/fstab 設定)
mount "$MOUNT_PATH" >> "$LOG_FILE" 2>&1
# 最終驗證
if mountpoint -q "$MOUNT_PATH" && ls "$MOUNT_PATH" > /dev/null 2>&1; then
echo "[$TIMESTAMP] $MOUNT_PATH 修復成功。" >> "$LOG_FILE"
# 這裡可以加入重啟 Docker 的通用邏輯 (選用)
# systemctl restart docker
else
echo "[$TIMESTAMP] 錯誤: 無法掛載 $MOUNT_PATH,請檢查網路或 NAS 狀態。" >> "$LOG_FILE"
fi
fi

152
newestN.sh Executable file
View File

@@ -0,0 +1,152 @@
#!/bin/bash
# 列出目錄內的所有檔案只保留最新的n個檔案
# 使用方法: newestN.sh -d=<目錄路徑> [-n=<保留數量>] [--confirm=<0|1>]
# 預設值
DIR=""
KEEP_NUM=2
CONFIRM=0
# 顯示幫助訊息
show_help() {
echo "用法: $0 -d=<目錄路徑> [-n=<保留數量>] [--confirm=<0|1>]"
echo ""
echo "參數說明:"
echo " -d=<目錄路徑> 指定要處理的目錄 (必需)"
echo " -n=<保留數量> 保留最新的檔案數量 (預設: 2)"
echo " --confirm=<0|1> 是否需要使用者確認 (預設: 0)"
echo " 0 = 不須確認,直接刪除"
echo " 1 = 需要使用者確認"
echo ""
echo "範例:"
echo " $0 -d=/backup/logs -n=5"
echo " $0 -d=/backup/logs -n=3 --confirm=1"
exit 1
}
# 解析參數
for arg in "$@"; do
case $arg in
-d=*)
DIR="${arg#*=}"
;;
-n=*)
KEEP_NUM="${arg#*=}"
;;
--confirm=*)
CONFIRM="${arg#*=}"
;;
-h|--help)
show_help
;;
*)
echo "錯誤: 未知的參數 '$arg'"
show_help
;;
esac
done
# 檢查目錄參數是否提供
if [ -z "$DIR" ]; then
echo "錯誤: 必須提供目錄路徑"
echo ""
show_help
fi
# 檢查目錄是否存在
if [ ! -e "$DIR" ]; then
echo "錯誤: 路徑 '$DIR' 不存在"
echo ""
show_help
fi
# 檢查是否為目錄
if [ ! -d "$DIR" ]; then
echo "錯誤: '$DIR' 不是一個目錄"
echo ""
show_help
fi
# 檢查保留數量是否為正整數
if ! [[ "$KEEP_NUM" =~ ^[0-9]+$ ]] || [ "$KEEP_NUM" -lt 1 ]; then
echo "錯誤: 保留數量必須是正整數"
exit 1
fi
# 檢查 confirm 參數是否有效
if [ "$CONFIRM" != "0" ] && [ "$CONFIRM" != "1" ]; then
echo "錯誤: --confirm 參數必須是 0 或 1"
exit 1
fi
echo "處理目錄: $DIR"
echo "保留最新 $KEEP_NUM 個檔案"
echo ""
# 取得目錄中的所有檔案(不含子目錄),按修改時間排序(最新的在前)
FILES=($(find "$DIR" -maxdepth 1 -type f -printf '%T@ %p\n' | sort -rn | cut -d' ' -f2-))
# 檔案總數
TOTAL=${#FILES[@]}
if [ $TOTAL -eq 0 ]; then
echo "目錄中沒有檔案"
exit 0
fi
echo "目錄中共有 $TOTAL 個檔案"
echo ""
# 如果檔案數量小於或等於保留數量,不需要刪除
if [ $TOTAL -le $KEEP_NUM ]; then
echo "檔案數量 ($TOTAL) 未超過保留數量 ($KEEP_NUM),無需刪除"
exit 0
fi
# 計算要刪除的檔案數量
DELETE_COUNT=$((TOTAL - KEEP_NUM))
echo "即將刪除 $DELETE_COUNT 個舊檔案:"
echo "----------------------------------------"
# 列出即將被刪除的檔案
TO_DELETE=("${FILES[@]:$KEEP_NUM}")
for file in "${TO_DELETE[@]}"; do
# 顯示檔案名稱和修改時間
MOD_TIME=$(stat -c '%y' "$file" | cut -d'.' -f1)
echo " $file (修改時間: $MOD_TIME)"
done
echo "----------------------------------------"
echo ""
# 如果需要確認
if [ $CONFIRM -eq 1 ]; then
read -p "確定要刪除以上檔案嗎? (y/N): " response
case "$response" in
[yY][eE][sS]|[yY])
echo "開始刪除檔案..."
;;
*)
echo "取消刪除操作"
exit 0
;;
esac
else
echo "開始刪除檔案..."
fi
# 刪除舊檔案
DELETED=0
for file in "${TO_DELETE[@]}"; do
if rm "$file" 2>/dev/null; then
echo "已刪除: $file"
DELETED=$((DELETED + 1))
else
echo "刪除失敗: $file"
fi
done
echo ""
echo "完成! 共刪除 $DELETED 個檔案"

View File

@@ -1,7 +1,7 @@
#!/bin/sh
echo "$(date +'%F %R:%S'): Sync /media/nasphoto/ /lvm1/docker/immich/nasphoto start."
echo "$(date +'%F %R:%S'): Sync /nas/photo/ /DATA01/dockers/immich/nasphoto start."
rsync -avP --delete /media/nasphoto/ /lvm1/docker/immich/nasphoto
rsync -avP --delete /nas/photo/ /DATA01/dockers/immich/nasphoto
echo "$(date +'%F %R:%S'): Sync /media/nasphoto/ /lvm1/docker/immich/nasphoto finished."
echo "$(date +'%F %R:%S'): Sync /nas/photo/ /DATA01/dockers/immich/nasphoto finished."