Skip to content

Commit

Permalink
Alpha to main for v3.0
Browse files Browse the repository at this point in the history
我已经好久都没有给这个储存库打tag了,毕竟以前刚开始学干了很多拆东墙补西墙的事情
现在算是稳定了吧,所以 来合并到主线吧
  • Loading branch information
SourLemonJuice committed Dec 9, 2023
2 parents ff76205 + b5ce4b5 commit 0ae2b03
Show file tree
Hide file tree
Showing 12 changed files with 241 additions and 172 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
/devtest
/.vscode
/src/log
83 changes: 47 additions & 36 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,60 +1,71 @@
# 文件夹备份脚本
# bash 文件夹备份脚本

这算是一个学习用的脚本了,各种地方写得都应该很差,咕咕
这算是一个学习用的脚本了,各种地方写得都应该很差吧,咕咕

## 能干什么

一个(一堆)备份目录到tar文件的脚本\
一个(一堆)备份目录到tar文件,并且能按顺序恢复的脚本\
支持tar的增量备份模式(不会记录删除有什么用呢)

---

## 使用

运行 `src/` 中的 `main.sh`没有默认操作,需要参数\
运行 `src/main.sh`默认显示帮助信息(--help)\
`-h | --help`查看帮助信息

虽然脚本文件很多但主脚本中有检测文件本身路径的逻辑,不用担心不在脚本根目录执行会无法加载其他函数的问题

> 打包和解包前后都有提示信息,不会直接执行的
## 备份格式
### 备份

未来可能有其他的方式吧

### tar
在备份文件夹内会**再有一层文件夹**用来支持增量备份\
使用`-B`会自动检测是否有以前的备份组可用,如果没有(比如第一次使用)就会触发完全备份模式\
使用`--full-backup`参数会强制在新的文件夹里创建一个完整备份

> 完全备份模式也使用了`-g`参数,但放置备份的文件夹是全新的\
> 使用`--one-file-system`参数,不会打包正常根目录里的`dev`这类文件夹
```text
.
├── backup
│ ├── 1699729938_2023-11-12_03-12-18
│ │ ├── 1699729939_2023-11-12_03-12-19_backup.tar
│ │ ├── .log
│ │ ├── .snapshot
│ │ └── .template
│ ├── 1699729941_2023-11-12_03-12-21
│ │ ├── 1699729941_2023-11-12_03-12-21_backup.tar
│ │ ├── 1699730061_2023-11-12_03-14-21_backup.tar
│ │ ├── .log
│ │ ├── .snapshot
│ │ └── .template
│ ├── .log
│ │ └── running.log
│ └── .now_backup
└── test
├── .a
├── a
├── b
├── c
├── dev
└── lost+found
├── 1700956381_2023-11-26_07-53-01
│   ├── 1700956384_2023-11-26_07-53-04_backup.tar
│   ├── .log
│   └── .tar_snapshot
├── 1700956534_2023-11-26_07-55-34
│   ├── 1700956535_2023-11-26_07-55-35_backup.tar
│   ├── 1700956584_2023-11-26_07-56-24_backup.tar
│   ├── .log
│   └── .tar_snapshot
└── .now_backup
```

> 这里的`.log`不是脚本日志,是记录顺序的文件,日志位置和名称写在配置里
```text
-B,--backup <压缩选项> 创建备份
--full-backup <压缩选项> 强制创建新的完全备份
```

### 恢复

从某个备份组按顺序释放文件

```text
-R,--restore <索引方式> 选择备份文件恢复
```

---

## 配置

将需要修改的文件放入`src/config.d`文件夹就能生效(使用bash赋值语法)

> `0a.`开头的是默认配置,最好写一个新的\
> 文件夹内的配置文件会按照 `名称` `顺序` 加载和覆盖
### 强制使用root权限

可以在执行脚本前检查是否为root权限\
可以在执行脚本前检查是否为root权限

```shell
# general
Expand Down Expand Up @@ -86,12 +97,12 @@ Tar_Default_Full_Backup=1

### 日志目录

设置日志存放的目录(目前没什么有用的信息啦)
>不要在最后加 / 我也不知道为什么
设置日志存放的目录

```shell
# log
RunningLogPath=/usr/sys_backup/.log
LogPath=./log
LogName=running.log
```

## 怪问题们
Expand Down
86 changes: 51 additions & 35 deletions src/backup.sh
Original file line number Diff line number Diff line change
@@ -1,48 +1,47 @@

backup(){

case $1 in
full)
# 等待用户最终确认
read -p "tar完整备份模式 [按回车确认]"
logger 'file' "开始tar增量模式备份"
read -p "准备tar完整备份模式 [按回车确认]"
llib_logger 'file' "开始tar增量模式备份"

# 刷新文件所在的组的编号文件
Now_Backup=$(date +%s_%Y-%m-%d_%H-%M-%S)
logger 'both' "设置新编号为 $Now_Backup"
llib_logger 'both' "设置新编号为 $Now_Backup"

# 完整备份都是每组的第一次备份所以要创建组的文件夹
logger 'file' "$(mkdir -v $BackupFolder/$Now_Backup || exit 1)"
llib_logger 'file' "$(mkdir -v $BackupFolder/$Now_Backup || exit 1)"

# 写入当前版本脚本的重要信息用来向后兼容
echo script version:$(cat "$ShellFilePath/version") > $BackupFolder/$Now_Backup/.template
echo file name template:'$(date +%s_%Y-%m-%d_%H-%M-%S)_backup.tar${ZipExtensionName}' >> $BackupFolder/$Now_Backup/.template
# echo script version:$(cat "$ShellFilePath/version") > $BackupFolder/$Now_Backup/.template
# echo file name template:'$(date +%s_%Y-%m-%d_%H-%M-%S)_backup.tar${ZipExtensionName}' >> $BackupFolder/$Now_Backup/.template
;;
add)
# 等待用户最终确认
read -p "tar增量备份模式 [按回车确认]"
logger 'file' "开始tar增量模式备份"
read -p "准备tar增量备份模式 [按回车确认]"
llib_logger 'file' "开始tar增量模式备份"
;;
*)
echo "backup函数 无效参数" && exit 1
llib_logger 'both' "backup函数 无效参数: $1" && exit 1
;;
esac

# 检测是否有设置默认压缩模式
if [[ ! -z $Default_Zip_Mode ]]; then
Tar_Zip_Mode=$Default_Zip_Mode
logger 'file' "强制使用 $Default_Zip_Mode 作为tar压缩参数"
llib_logger 'file' "强制使用 $Default_Zip_Mode 作为tar压缩参数"
else
Tar_Zip_Mode=$2
fi
case $Tar_Zip_Mode in
-z)
logger 'file' "gzip压缩模式"
llib_logger 'file' "gzip压缩模式"
ZipMode="z"
ZipExtensionName=".gz"
;;
*)
logger 'file' "无压缩模式"
llib_logger 'file' "无压缩模式"
ZipMode=""
ZipExtensionName=""
;;
Expand All @@ -53,41 +52,58 @@ backup(){
excludes="--exclude=./lost+found --exclude=.$BackupFolder"

# 等待用户最终确认
separator
echo 源: $RootPath
echo 目标文件夹: $BackupFolder/$Now_Backup
echo 排除参数: $excludes
echo 接收到的备份模式: $1
echo tar压缩参数: $ZipMode
separator
{
read -n 1 -p "[回车继续 其他输入则终止]" Final_Tip
if [[ ! -z $Final_Tip ]];then
logger 'both' "用户已取消操作"
echo "当前时间 $(date +%x-%T)"
rm -ri $BackupFolder/$Now_Backup
logger 'both' "删除未使用的文件夹 $BackupFolder/$Now_Backup"
exit
llib_logger 'file' "----备份详细信息报告----"
llib_separator
llib_logger 'both' "源: $RootPath"
llib_logger 'both' "目标文件夹: $BackupFolder/$Now_Backup"
llib_logger 'both' "排除参数: $excludes"
llib_logger 'both' "接收到的备份模式: $1"
llib_logger 'both' "tar压缩参数: $ZipMode"
llib_separator
llib_logger 'file' "----报告结束----"

# 让用户决定是否继续
read -s -n 1 -p "[按回车立即开始 其他输入则终止]" Final_Tip
# read 的 -p 不带换行,自己加一个
echo
# 如果确定退出就删除刚创建的文件夹
if [[ ! -z $Final_Tip ]];then
# 只有完整备份才需要删除,增量模式在这之前不会改动文件
if [ $1 == "full" ];then
llib_logger 'both' "用户已取消操作 (完整备份模式)"
llib_logger 'file' "当前时间: $(date +%x-%T) 准备删除的目标: $Now_Backup"
# !!! rm 的路径在init函数中均有检测,如果要动请一定要确定不会出现空的函数
# 或者像现在一样尽量使用仅删除文件夹模式
rm -d $BackupFolder/$Now_Backup && llib_logger 'both' "成功删除未使用的空文件夹 $BackupFolder/$Now_Backup"
# 把rm的错误码传递出去
# 正常如果rm没问题会执行日志记录,但如果有问题会停在rm,后面的llib_logger不会覆盖掉rm的"错误码"
exit $?
fi
}
# 其他模式退出可以直接exit
llib_logger 'both' "用户已取消操作"
exit 0
fi

# 这里cd到要工作的目录是因为不这么做生成的tar会先有一个工作目录名称的文件夹再是工作目录里的内容
# 懒得找别的办法了(-:
(
cd $RootPath || exit 1
logger 'file' "开始打包 $RootPath$BackupFolder/$Now_Backup"
tar -g $BackupFolder/$Now_Backup/.snapshot\
llib_logger 'file' "----开始打包"
tar -g $BackupFolder/$Now_Backup/.tar_snapshot\
-"${ZipMode}"cvf $BackupFolder/$Now_Backup/$(date +%s_%Y-%m-%d_%H-%M-%S)_backup.tar${ZipExtensionName}\
--overwrite\
--one-file-system\
${excludes}\
.
.\
2>&1
) | llib_logger 'stdin'

# 写入当前备份的组,如果是增量内容将不变,如果是完全备份将写入新的编号,都是为了最终确认呀啊啊啊
echo -n $Now_Backup > $Now_Backup_FilePath
logger 'file' "更新储存库中的.now_backup文件为 $Now_Backup"
llib_logger 'file' "写入储存库中的.now_backup文件为 > $Now_Backup"

# 写入进打包历史
echo $(date +%s_%Y-%m-%d_%H-%M-%S)_backup.tar${ZipExtensionName} >> $BackupFolder/$Now_Backup/.log
# logggggg
logger 'both' "$(date +%s_%Y-%m-%d_%H-%M-%S)_${FileAppendName}backup.tar${ZipExtensionName} 打包结束"
# 这里读取最后一行.log作为输出,可能并不准确,但不会出现对不上的情况
llib_logger 'both' "$(tail -n 1 $BackupFolder/$Now_Backup/.log) 打包结束" "打包结束 .log的最后一项为 $(tail -n 1 $BackupFolder/$Now_Backup/.log)"
}
7 changes: 3 additions & 4 deletions src/config → src/config.d/0a.config_template.sh
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
# 0 == false
# 1 == true
# "0 == false" "1 == true"

# general
NeedRoot=1
Disable_init_Path_Detection=0
Tar_Default_Full_Backup=1
Default_Zip_Mode=-z

Expand All @@ -12,4 +10,5 @@ BackupFolder=/usr/sys-backup
RootPath=/

# log
RunningLogPath=/usr/sys_backup/.log
LogPath=./log
LogName=running.log
2 changes: 1 addition & 1 deletion src/help_info
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

[操纵备份]
-B,--backup <压缩选项> 创建备份
--backup-full <压缩选项> 强制创建新的完全备份
--full-backup <压缩选项> 强制创建新的完全备份
-R,--restore <索引方式> 选择备份文件恢复

[压缩选项]
Expand Down
23 changes: 3 additions & 20 deletions src/init.sh
Original file line number Diff line number Diff line change
@@ -1,12 +1,5 @@

init(){
# 加载一些小东西
# 日志函数
source $ShellFilePath/logger.sh
# 输出数组内容
source $ShellFilePath/println_array_items.sh
# 打印分割线
source $ShellFilePath/separator.sh

# 检测权限
if [[ $NeedRoot -eq 1 ]] && [[ ! $(id -u) -eq 0 ]]
Expand All @@ -15,15 +8,9 @@ init(){
exit 1
fi

if [[ $Disable_init_Path_Detection -eq 0 ]]; then
# 创建备份文件的文件夹
if [[ ! -d $BackupFolder ]]; then
logger 'file' "$(mkdir -vp $BackupFolder || exit 1)"
fi
# 创建log文件夹
if [[ ! -d $RunningLogPath ]]; then
logger 'file' "$(mkdir -vp $RunningLogPath || exit 1)"
fi
# 创建备份文件的文件夹
if [[ ! -d $BackupFolder ]]; then
llib_logger 'file' "$(mkdir -vp $BackupFolder || exit 1)"
fi

# 设置备份组的编号
Expand All @@ -34,8 +21,4 @@ init(){
Now_Backup=''
fi

LogName=running.log
# 写入日志的第一行日期
> $RunningLogPath/$LogName || exit 1
logger 'file' "$(date +%s_%Y-%m-%d_%T) $0 $@"
}
43 changes: 43 additions & 0 deletions src/lib/logger.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# 写日志咯
llib_logger(){
LogPath=$LogPath
LogName=$LogName

case $1 in
both)
echo $2
if [[ -z $3 ]];then
echo "[$(date +%T)] [$1] $2" >> $LogPath/$LogName
else
# 如果有第三个参数就向文件内写入单独的内容
echo "[$(date +%T)] [$1] $3" >> $LogPath/$LogName
fi
;;
term)
echo $2
;;
file)
echo "[$(date +%T)] [$1] $2" >> $LogPath/$LogName
;;
stdin)
# 管道输入模式
# 执行到这里tee就会开始请求标准输入,有输入后就会将内容附加到后面的文件里实现从管道输入读取命令输出
tee -a $LogPath/$LogName
;;
init)
# 检测并创建log文件夹
if [[ ! -d $LogPath ]]; then
llib_logger 'file' "$(mkdir -vp $LogPath || exit 1)"
fi
# 清空日志
> $LogPath/$LogName || exit 1
# 写入日志
llib_logger 'file' "$(date +%s_%Y-%m-%d_%T) $0"
;;
*)
# 保留缺省情况
echo $@
echo "[$(date +%T)] $@" >> $LogPath/$LogName
;;
esac
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@

# 循环输出数组内的值
println_array_items(){
llib_println_array_items(){
for i in $@; do
echo $i
done
Expand Down
3 changes: 1 addition & 2 deletions src/separator.sh → src/lib/separator.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@

# 分隔线函数
separator(){
llib_separator(){
if [[ -z $1 ]] || [[ ! ${#1} -eq 1 ]]; then
Character='='
else
Expand Down
Loading

0 comments on commit 0ae2b03

Please sign in to comment.