Repository navigation
Expand file tree
/
Copy pathbackup-script.go
More file actions
137 lines (115 loc) · 3.83 KB
/
Copy pathbackup-script.go
File metadata and controls
137 lines (115 loc) · 3.83 KB
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
package main
import (
"fmt"
"os"
"path/filepath"
"runtime"
"runtime/debug"
"sort"
"syscall"
"time"
"github.com/mholt/archiver/v3"
)
// Configuration constants - modify these as needed
const (
SOURCE_FOLDER_PATH = `C:\KK_Data\syncthing\obsidian main vault` // Folder you want to back up
BACKUP_FOLDER_PATH = `C:\KK_Data\01_Meta\Backup\obsidian backups` // Folder where backups will be stored
MAX_BACKUPS_TO_KEEP = 3 // Maximum number of backup files to keep
)
func main() {
// Optimize for minimal resource usage
debug.SetGCPercent(20) // More frequent GC to keep memory low
runtime.GOMAXPROCS(1) // Limit to single CPU core
// Set process priority to lowest on Windows
setPriorityLow()
sourceFolder := SOURCE_FOLDER_PATH
backupFolder := BACKUP_FOLDER_PATH
// Ensure the backup folder exists
if err := os.MkdirAll(backupFolder, os.ModePerm); err != nil {
fmt.Println("Error creating backup directory:", err)
return
}
// Create the backup file name based on the current date
dateString := time.Now().Format("2006-01-02_15-04-05")
backupFile := filepath.Join(backupFolder, fmt.Sprintf("backup_%s.zip", dateString))
// Create a custom archiver optimized for minimal resource usage
zip := archiver.Zip{
CompressionLevel: 0, // No compression (fastest, minimal CPU)
MkdirAll: true,
SelectiveCompression: false, // Disable to save CPU
ContinueOnError: true, // Don't stop on minor errors
OverwriteExisting: false,
ImplicitTopLevelFolder: false,
}
fmt.Println("Starting backup (low priority mode)...")
// Create the backup using custom archiver settings
err := zip.Archive([]string{sourceFolder}, backupFile)
if err != nil {
fmt.Println("Error creating backup:", err)
return
}
fmt.Printf("Backup created: %s\n", backupFile)
// Force garbage collection and brief pause to reduce system load
runtime.GC()
time.Sleep(3 * time.Second)
// Manage backups: Keep at most 4 backups (optimized version)
cleanupOldBackups(backupFolder)
fmt.Println("Backup process complete.")
}
// setPriorityLow sets the process priority to lowest on Windows
func setPriorityLow() {
handle, err := syscall.GetCurrentProcess()
if err != nil {
return
}
// Use syscall to set priority to IDLE_PRIORITY_CLASS (0x40)
kernel32 := syscall.NewLazyDLL("kernel32.dll")
proc := kernel32.NewProc("SetPriorityClass")
proc.Call(uintptr(handle), uintptr(0x40)) // IDLE_PRIORITY_CLASS
}
// cleanupOldBackups efficiently manages backup files with minimal resource usage
func cleanupOldBackups(backupFolder string) {
files, err := os.ReadDir(backupFolder)
if err != nil {
fmt.Println("Error reading backup directory:", err)
return
}
// Use a struct to avoid multiple stat calls
type backupInfo struct {
name string
modTime time.Time
}
var backupFiles []backupInfo
for _, file := range files {
if file.IsDir() || filepath.Ext(file.Name()) != ".zip" {
continue
}
info, err := file.Info()
if err != nil {
continue
}
backupFiles = append(backupFiles, backupInfo{
name: file.Name(),
modTime: info.ModTime(),
})
// Small pause between file operations to reduce I/O load
time.Sleep(10 * time.Millisecond)
}
// Sort by modification time (oldest first)
sort.Slice(backupFiles, func(i, j int) bool {
return backupFiles[i].modTime.Before(backupFiles[j].modTime)
})
// Delete excess backups
if len(backupFiles) > MAX_BACKUPS_TO_KEEP {
for i := 0; i < len(backupFiles)-MAX_BACKUPS_TO_KEEP; i++ {
oldestBackup := filepath.Join(backupFolder, backupFiles[i].name)
if err := os.Remove(oldestBackup); err == nil {
fmt.Printf("Deleted oldest backup: %s\n", oldestBackup)
} else {
fmt.Println("Error deleting oldest backup:", err)
}
// Pause between deletions to reduce I/O load
time.Sleep(100 * time.Millisecond)
}
}
}