前言

前两天写过一篇《使用绿联NAS备份服务器数据》的文章。

但是想备份服务器的其他内容,只能原封不动的搬运过来,不能做到压缩备份,这时候就得需要一个可以自动打包数据并压缩的Shell任务了。

打包完成之后,我们再在NAS使用远程下载文件的定时任务去拉取这个压缩备份,就能做到备份自定义文件了,非常灵活通用,比如:想备份Minecraft服务器的数据,直接把存档文件夹压缩保存在某个指定目录,NAS直接远程拉取这个目录就能达到备份Minecraft存档的功能了。

理论可行,实践开始。

开始

其实只需要一个Shell脚本,然后在1Panel中配置计划任务就行了,非常简单,这里就只需要给出Shell脚本,以及脚本功能、如何使用就行了。

Shell脚本

脚本内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#!/bin/bash

#######################################
# 用户配置区域 #
#######################################

# 备份目标目录
TARGET_DIR="/opt/backup/left4dead2"

# 要备份的源目录列表
SOURCE_DIRS=(
"/opt/game/steam/Left4Dead2/left4dead2/addons" # 插件目录
"/opt/game/steam/Left4Dead2/left4dead2/cfg" # 配置目录
"/opt/game/steam/Left4Dead2/start.sh" # 启动脚本
"/opt/game/steam/Left4Dead2/left4dead2/motd.txt" # 每日消息
"/opt/game/steam/Left4Dead2/left4dead2/host.txt" # 主机logo
)

# --- 新增:过滤配置 ---

# 排除项 (支持通配符,相对于源目录的相对路径)
# 例如:排除所有 .log 文件和 tmp 文件夹
EXCLUDE_LIST=(
# "*.log"
# "sourcemod/logs/*"
# "workshop/*"
"地图-*.vpk"
)

# 白名单 (优先级最高,即使在排除项中也会被包含)
# 例如:即使排除所有 .log,但要保留重要的一条
WHITELIST=(
# "important_plugin.log"
# "workshop/indispensable_mod.vpk"
"地图-测试地图-老.vpk"
)

# --- 结束:过滤配置 ---

# 压缩包名称前缀
ARCHIVE_PREFIX="left4dead2"
# 临时目录前缀
TEMP_DIR_PREFIX="backup_temp"
# 保留的备份数量
KEEP_COUNT=1

#######################################
# 脚本主体部分 #
#######################################

# 检查依赖
if ! command -v rsync &> /dev/null; then
echo "错误: 未找到 rsync,请先安装 (yum/apt install rsync)"
exit 1
fi

# 检查并创建目标目录
if [ ! -d "$TARGET_DIR" ]; then
echo "提示: 目标目录不存在,正在创建: $TARGET_DIR"
mkdir -p "$TARGET_DIR" || exit 1
fi

# 创建临时目录
temp_dir=$(mktemp -d -p "$TARGET_DIR" "${TEMP_DIR_PREFIX}_XXXXXX")
[ $? -ne 0 ] && { echo "错误: 无法创建临时目录"; exit 1; }

echo "开始备份操作..."
echo "--------------------------------"

# 构建 rsync 过滤参数
# 注意:白名单必须在排除项之前
filter_args=()
for item in "${WHITELIST[@]}"; do
filter_args+=("--include=$item")
done
for item in "${EXCLUDE_LIST[@]}"; do
filter_args+=("--exclude=$item")
done

# 复制源目录到临时目录
for src in "${SOURCE_DIRS[@]}"; do
[[ "$src" =~ ^[[:space:]]*# ]] && continue
[[ -z "$src" ]] && continue

if [ ! -e "$src" ]; then
echo "警告: '$src' 不存在,跳过"
continue
fi

echo "正在同步 (含过滤): $src"

# 使用 rsync 进行过滤备份
# -R 使用相对路径以防同名文件夹覆盖,但为了保持你原脚本逻辑,
# 我们同步到临时目录的子目录下
base_name=$(basename "$src")

if [ -d "$src" ]; then
# 如果是目录,同步内容到临时文件夹下的同名目录
mkdir -p "$temp_dir/$base_name"
rsync -avz --quiet "${filter_args[@]}" "$src/" "$temp_dir/$base_name/"
else
# 如果是文件,直接复制
cp -p "$src" "$temp_dir/"
fi

if [ $? -ne 0 ]; then
echo "错误: 同步 '$src' 失败"
rm -rf "$temp_dir"
exit 1
fi
done

# 创建压缩包
timestamp=$(date +%Y%m%d_%H%M%S)
archive_name="${ARCHIVE_PREFIX}_${timestamp}.tar.gz"
echo "--------------------------------"
echo "正在创建压缩包: $archive_name"
tar -czf "$TARGET_DIR/$archive_name" -C "$temp_dir" .

# 清理临时目录
echo "清理临时文件..."
rm -rf "$temp_dir"

echo "--------------------------------"
echo "备份完成! 压缩包: $TARGET_DIR/$archive_name"

# 清理旧备份
if [ $KEEP_COUNT -gt 0 ]; then
backup_files=($(ls -tr "$TARGET_DIR/${ARCHIVE_PREFIX}"_*.tar.gz 2>/dev/null))
total_files=${#backup_files[@]}
if [ $total_files -gt $KEEP_COUNT ]; then
files_to_delete=$((total_files - KEEP_COUNT))
for ((i=0; i<files_to_delete; i++)); do
echo "删除旧备份: ${backup_files[$i]}"
rm -f "${backup_files[$i]}"
done
fi
fi

echo "--------------------------------"
echo "所有操作已完成!"

功能说明

将指定的一个或多个文件夹/文件,打包到tar.gz包中,源文件不受任何影响。

tar.gz压缩包的名称会带上时间,可指定保存压缩包的个数,超出则删除最旧的压缩包。

参数说明

  • TARGET_DIR:压缩包保存的文件夹路径
  • SOURCE_DIRS:需要被压缩的内容,可以是多个,可以是文件夹或文件
  • ARCHIVE_PREFIX:压缩包的前缀,最终压缩包的名称会带上时间后缀
  • TEMP_DIR_PREFIX:临时目录的前缀,最终临时目录会带上随机后缀,打包完成后自动删除
  • KEEP_COUNT:保存的压缩包个数,多次执行脚本时,会自动清理多余的压缩包,删除最旧的
  • EXCLUDE_LIST:排除项,排除目标文件夹的部分内容, 相对路径(相对每个目标文件夹的路径)
  • WHITELIST:白名单,使排除项中的部分内容无效, 相对路径(相对每个目标文件夹的路径)

1Panel计划任务

其实只需要能够定时执行脚本就行了,没了解过其他能定时执行脚本的工具,由于服务器是由1Panel管理的,这里直接就使用1Panel的计划任务了,按照以下步骤配置即可,非常简单。

进入计划任务菜单,点击创建计划任务

  • 任务类型:Shell脚本
  • 任务名称:任意
  • 执行周期:根据需求,我这里是游戏存档,设置成了一天一次,凌晨执行
  • 脚本内容:录入上面的脚本,根据配置说明修改
  • 保留份数:默认7天足够了

点击确认,计划任务就已经弄好了,想要使用NAS远程备份,就直接备份脚本中TARGET_DIR配置的文件夹路径就行了。