-
Notifications
You must be signed in to change notification settings - Fork 50
/
Copy pathbackup.go
166 lines (138 loc) · 3.7 KB
/
backup.go
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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
package main
import (
"io"
"log"
"os"
"path/filepath"
"time"
"github.com/hoshinonyaruko/palworld-go/config"
)
type BackupTask struct {
Config config.Config
Ticker *time.Ticker
}
func NewBackupTask(config config.Config) *BackupTask {
var ticker *time.Ticker
if config.BackupInterval > 0 {
ticker = time.NewTicker(time.Duration(config.BackupInterval) * time.Second)
}
return &BackupTask{
Config: config,
Ticker: ticker,
}
}
func (task *BackupTask) Schedule() {
if task.Ticker == nil {
// 如果 Ticker 为 nil,不需要进行定时备份
return
}
for range task.Ticker.C {
task.RunBackup()
}
}
func (task *BackupTask) RunBackup() {
// 获取当前日期和时间
currentDate := time.Now().Format("2006-01-02-15-04-05")
// 创建新的备份目录
backupDir := filepath.Join(task.Config.BackupPath, currentDate)
if err := os.MkdirAll(backupDir, 0755); err != nil {
log.Printf("Failed to create backup directory: %v", err)
return
}
// 确定源文件的路径和目标路径
sourcePath := filepath.Join(task.Config.GameSavePath, "SaveGames")
destinationPath := filepath.Join(backupDir, "SaveGames")
// 执行文件复制操作
if err := copyDir(sourcePath, destinationPath); err != nil {
log.Printf("Failed to copy files for backup SaveGames: %v", err)
} else {
log.Printf("Backup completed successfully: %s", destinationPath)
}
// 确定源文件的路径和目标路径
sourcePath = filepath.Join(task.Config.GameSavePath, "Config")
destinationPath = filepath.Join(backupDir, "Config")
// 执行文件复制操作
if err := copyDir(sourcePath, destinationPath); err != nil {
log.Printf("Failed to copy files for backup Config: %v", err)
} else {
log.Printf("Backup completed successfully: %s", destinationPath)
}
// 删除旧备份(如果设置了天数)
if task.Config.SaveDeleteDays > 0 {
task.deleteOldBackups()
}
}
func (task *BackupTask) deleteOldBackups() {
// 读取备份目录
files, err := os.ReadDir(task.Config.BackupPath)
if err != nil {
log.Printf("Failed to list backup directory: %v", err)
return
}
// 删除超过SaveDeleteDays天数的备份
for _, f := range files {
if f.IsDir() {
backupTime, err := time.Parse("2006-01-02-15-04-05", f.Name())
if err != nil {
log.Printf("Failed to parse backup directory name: %s, error: %v", f.Name(), err)
continue
}
if time.Since(backupTime).Hours() > float64(task.Config.SaveDeleteDays*24) {
err := os.RemoveAll(filepath.Join(task.Config.BackupPath, f.Name()))
if err != nil {
log.Printf("Failed to delete old backup: %s, error: %v", f.Name(), err)
} else {
log.Printf("Old backup deleted successfully: %s", f.Name())
}
}
}
}
}
// copyDir 递归复制目录及其内容
func copyDir(src string, dst string) error {
srcInfo, err := os.Stat(src)
if err != nil {
return err
}
if err := os.MkdirAll(dst, srcInfo.Mode()); err != nil {
return err
}
dir, _ := os.Open(src)
defer dir.Close()
entries, _ := dir.Readdir(-1)
for _, entry := range entries {
srcPath := filepath.Join(src, entry.Name())
dstPath := filepath.Join(dst, entry.Name())
if entry.IsDir() {
if err := copyDir(srcPath, dstPath); err != nil {
return err
}
} else {
if err := copyFile(srcPath, dstPath); err != nil {
return err
}
}
}
return nil
}
// copyFile 复制单个文件
func copyFile(src, dst string) error {
srcFile, err := os.Open(src)
if err != nil {
return err
}
defer srcFile.Close()
dstFile, err := os.Create(dst)
if err != nil {
return err
}
defer dstFile.Close()
if _, err = io.Copy(dstFile, srcFile); err != nil {
return err
}
srcInfo, err := os.Stat(src)
if err != nil {
return err
}
return os.Chmod(dst, srcInfo.Mode())
}