confmirror 1.0.0__tar.gz

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.
Files changed (38) hide show
  1. confmirror-1.0.0/LICENSE +21 -0
  2. confmirror-1.0.0/PKG-INFO +381 -0
  3. confmirror-1.0.0/README.md +359 -0
  4. confmirror-1.0.0/pyproject.toml +63 -0
  5. confmirror-1.0.0/setup.cfg +4 -0
  6. confmirror-1.0.0/src/confmirror/__init__.py +43 -0
  7. confmirror-1.0.0/src/confmirror/backup.py +334 -0
  8. confmirror-1.0.0/src/confmirror/cli.py +643 -0
  9. confmirror-1.0.0/src/confmirror/config.py +309 -0
  10. confmirror-1.0.0/src/confmirror/diff/__init__.py +215 -0
  11. confmirror-1.0.0/src/confmirror/diff/core.py +301 -0
  12. confmirror-1.0.0/src/confmirror/diff/display.py +94 -0
  13. confmirror-1.0.0/src/confmirror/gitops.py +107 -0
  14. confmirror-1.0.0/src/confmirror/global_config.py +83 -0
  15. confmirror-1.0.0/src/confmirror/list.py +101 -0
  16. confmirror-1.0.0/src/confmirror/logger.py +142 -0
  17. confmirror-1.0.0/src/confmirror/meta.py +78 -0
  18. confmirror-1.0.0/src/confmirror/output.py +53 -0
  19. confmirror-1.0.0/src/confmirror/perms.py +191 -0
  20. confmirror-1.0.0/src/confmirror/restore.py +246 -0
  21. confmirror-1.0.0/src/confmirror/system_install.py +125 -0
  22. confmirror-1.0.0/src/confmirror/utils.py +251 -0
  23. confmirror-1.0.0/src/confmirror.egg-info/PKG-INFO +381 -0
  24. confmirror-1.0.0/src/confmirror.egg-info/SOURCES.txt +36 -0
  25. confmirror-1.0.0/src/confmirror.egg-info/dependency_links.txt +1 -0
  26. confmirror-1.0.0/src/confmirror.egg-info/entry_points.txt +2 -0
  27. confmirror-1.0.0/src/confmirror.egg-info/requires.txt +10 -0
  28. confmirror-1.0.0/src/confmirror.egg-info/top_level.txt +1 -0
  29. confmirror-1.0.0/tests/test_backup_restore.py +356 -0
  30. confmirror-1.0.0/tests/test_cli.py +182 -0
  31. confmirror-1.0.0/tests/test_cli_agent.py +185 -0
  32. confmirror-1.0.0/tests/test_config.py +86 -0
  33. confmirror-1.0.0/tests/test_diff_core.py +293 -0
  34. confmirror-1.0.0/tests/test_infrastructure.py +244 -0
  35. confmirror-1.0.0/tests/test_meta.py +47 -0
  36. confmirror-1.0.0/tests/test_perms_list.py +97 -0
  37. confmirror-1.0.0/tests/test_system_install.py +163 -0
  38. confmirror-1.0.0/tests/test_utils.py +99 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 yoing945
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,381 @@
1
+ Metadata-Version: 2.4
2
+ Name: confmirror
3
+ Version: 1.0.0
4
+ Summary: 系统配置备份与还原工具
5
+ Author-email: yoing945 <yoing945@qq.com>
6
+ License-Expression: MIT
7
+ Classifier: Programming Language :: Python :: 3
8
+ Classifier: Operating System :: OS Independent
9
+ Requires-Python: >=3.9
10
+ Description-Content-Type: text/markdown
11
+ License-File: LICENSE
12
+ Requires-Dist: PyYAML>=6.0
13
+ Requires-Dist: click>=8.0
14
+ Requires-Dist: pathspec>=0.10
15
+ Provides-Extra: dev
16
+ Requires-Dist: pytest>=7.0; extra == "dev"
17
+ Requires-Dist: build; extra == "dev"
18
+ Requires-Dist: black; extra == "dev"
19
+ Requires-Dist: isort; extra == "dev"
20
+ Requires-Dist: pyright>=1.1; extra == "dev"
21
+ Dynamic: license-file
22
+
23
+ # ConfMirror
24
+
25
+ **ConfMirror** 是一个声明式系统配置镜像与还原工具,旨在安全可靠地备份和还原系统配置文件。
26
+
27
+ ## 🚀 功能特性
28
+
29
+ - **安全可靠**:完整保留文件权限、属主、类型,支持精确还原
30
+ - **声明式管理**:通过 YAML 配置文件定义备份规则,可版本化、可复用
31
+ - **轻量无侵入**:不修改原系统目录,仅在独立数据仓库中维护镜像
32
+ - **生产就绪**:支持交互确认、分级日志、错误还原,避免误操作
33
+ - **Git 集成**:可与 Git 结合使用,实现历史追溯、差异对比、远程同步
34
+ - **智能补全**:支持命令和模块名称的自动补全功能
35
+ - **🤖 Agent 友好**:支持 `--format json` 结构化输出、`--dry-run` 预览、`--yes` 非交互模式,便于 AI Agent 集成。项目内置 `.agents/skills/confmirror/SKILL.md`,可直接作为 AI Skill 加载
36
+
37
+ ## 📦 安装
38
+
39
+ ### 通过 uv 安装(推荐)
40
+
41
+ ```bash
42
+ uv tool install confmirror
43
+ ```
44
+
45
+ ### 通过 pip 安装
46
+
47
+ ```bash
48
+ pip install confmirror
49
+ ```
50
+
51
+ ## 🛠️ 快速开始
52
+
53
+ ### 1. 创建配置文件
54
+
55
+ 首先,在工作目录中创建 `confmirror.yaml` 配置文件:
56
+
57
+ ```yaml
58
+ settings:
59
+ name: "my-config"
60
+ backup_root: "./mirror" # 镜像根目录
61
+ script_hooks_dir: "./script-hooks" # 脚本钩子目录
62
+ log_dir: "./logs" # 日志目录
63
+ git_auto_commit: true # 是否自动提交到 Git
64
+ git_auto_push: false # 是否自动推送到远程
65
+
66
+ modules:
67
+ - name: "sshd"
68
+ paths:
69
+ - "/etc/ssh/sshd_config"
70
+
71
+ - name: "nginx"
72
+ base_path: "/etc/nginx"
73
+ paths:
74
+ - "nginx.conf"
75
+ - "sites-available/default"
76
+
77
+ - name: "ufw"
78
+ hook: "ufw/script.sh" # 相对于 script-hooks/ 的脚本路径
79
+ ```
80
+
81
+ ### 2. 执行备份
82
+
83
+ ```bash
84
+ # 全量备份
85
+ confmirror backup
86
+
87
+ # 备份指定模块
88
+ confmirror backup --module sshd
89
+
90
+ # 备份指定路径
91
+ confmirror backup /etc/ssh/sshd_config
92
+ ```
93
+
94
+ ### 3. 执行还原
95
+
96
+ ```bash
97
+ # 还原指定模块
98
+ sudo confmirror restore --module sshd
99
+
100
+ # 还原指定路径
101
+ sudo confmirror restore /etc/ssh/sshd_config
102
+
103
+ # 全量还原
104
+ sudo confmirror restore
105
+ ```
106
+
107
+ ## 🤖 AI Agent 快速开始
108
+
109
+ ConfMirror 对 AI Agent 友好,支持结构化 JSON 输出和非交互执行。
110
+
111
+ ### Agent 调用示例
112
+
113
+ ```bash
114
+ # 结构化输出(JSON)
115
+ confmirror backup --module nginx --format json
116
+
117
+ # 预览操作(不实际执行)
118
+ confmirror backup --module nginx --dry-run --format json
119
+
120
+ # 非交互模式(跳过所有确认提示)
121
+ confmirror backup --yes
122
+ confmirror restore --yes
123
+
124
+ # 组合使用:Agent 安全调用
125
+ confmirror backup --module nginx --dry-run --format json
126
+ # → 评估影响后,去掉 --dry-run 实际执行
127
+ confmirror backup --module nginx --format json
128
+ ```
129
+
130
+ ### JSON 输出示例
131
+
132
+ ```bash
133
+ $ confmirror diff --module nginx --format json
134
+ {
135
+ "status": "success",
136
+ "command": "diff",
137
+ "module": "nginx",
138
+ "added": [],
139
+ "deleted": [],
140
+ "changed": [
141
+ {
142
+ "source": "/etc/nginx/nginx.conf",
143
+ "backup": "mirror/etc/nginx/nginx.conf",
144
+ "content_same": false,
145
+ "meta_same": true,
146
+ "unified_diff": ["--- backup: nginx.conf", "+++ source: nginx.conf", "@@ -1 +1 @@", "-old", "+new"]
147
+ }
148
+ ],
149
+ "unchanged": []
150
+ }
151
+ ```
152
+
153
+ > 💡 **提示**:`--format json` 会自动抑制终端日志输出,确保 stdout 为纯净的 JSON,便于 Agent 解析。
154
+
155
+ ## 🔧 配置详解
156
+
157
+ ### 配置文件结构
158
+
159
+ `confmirror.yaml` 文件包含两个主要部分:
160
+
161
+ - `settings`:全局设置
162
+ - `modules`:备份模块列表
163
+
164
+ ### Settings 选项
165
+
166
+ | 选项 | 描述 | 默认值 |
167
+ |------|------|--------|
168
+ | `name` | 配置集名称 | 当前目录名 |
169
+ | `backup_root` | 镜像根目录 | `"./mirror"` |
170
+ | `script_hooks_dir` | 脚本钩子目录 | `"./script-hooks"` |
171
+ | `log_dir` | 日志目录 | `"./logs"` |
172
+ | `log_max_lines` | 日志最大保留行数 | `1000` |
173
+ | `git_auto_commit` | 是否自动提交到 Git | `false` |
174
+ | `git_auto_push` | 是否自动推送到远程 | `false` |
175
+ | `mirror_file_mode` | 备份文件在 mirror 中的权限(八进制字符串),确保 Git 可读写 | `"0o644"` |
176
+ | `mirror_dir_mode` | 备份目录在 mirror 中的权限(八进制字符串),确保 Git 可读写 | `"0o755"` |
177
+
178
+ ### Modules 选项
179
+
180
+ 每个模块可以包含以下字段:
181
+
182
+ | 字段 | 描述 | 必需 |
183
+ |------|------|------|
184
+ | `name` | 模块名称 | 是 |
185
+ | `paths` | 要备份的路径列表 | 否* |
186
+ | `base_path` | 拼接到 `paths` 前的父路径 | 否 |
187
+ | `exclude_paths` | 要排除的路径模式 | 否 |
188
+ | `hook` | 相对于 `script_hooks_dir` 的脚本路径 | 否* |
189
+ | `hook_lang` | 脚本解释器语言,默认 `bash` | 否 |
190
+
191
+ > * `paths` 和 `hook` 二者选其一;同时存在时 `hook` 优先
192
+
193
+ ### 模块配置示例
194
+
195
+ ```yaml
196
+ modules:
197
+ # 1. 路径备份模块
198
+ - name: "ssh-config"
199
+ paths:
200
+ - "/etc/ssh/sshd_config"
201
+ - "/etc/ssh/ssh_config.d/"
202
+ exclude_paths:
203
+ - "*.bak" # 排除所有 .bak 文件
204
+ - "*.tmp" # 排除所有 .tmp 文件
205
+ - "config.bak" # 排除特定文件
206
+ - "temp/" # 排除目录
207
+ - "*/temp/*" # 排除所有层级的 temp 目录中的文件
208
+ - "**/logs/" # 排除任意深度的 logs 目录
209
+ - "!important.log" # 例外:不排除 important.log 文件(即使它匹配了 *.log 模式)
210
+
211
+ # 2. 脚本备份模块
212
+ - name: "ufw-rules"
213
+ hook: "ufw/export-rules.sh"
214
+
215
+ # 3. 带父路径的模块
216
+ - name: "docker-apps"
217
+ base_path: "/data/dockerapps/"
218
+ paths:
219
+ - "traefik/docker-compose.yml"
220
+ - "traefik/traefik.yml"
221
+ - "traefik/dynamic/"
222
+ exclude_paths:
223
+ - "*.log" # 排除所有 .log 文件
224
+ - "**/cache/" # 排除任意深度的 cache 目录
225
+ - "temp*" # 排除以 temp 开头的文件或目录
226
+ ```
227
+
228
+ ### 排除模式
229
+
230
+ `exclude_paths` 使用 Git 风格的模式匹配(`.gitignore` 语法):
231
+
232
+ | 模式 | 含义 |
233
+ |------|------|
234
+ | `*.log` | 所有 `.log` 文件 |
235
+ | `temp/` | 名为 `temp` 的目录 |
236
+ | `*/cache/*` | 任意一级 `cache` 目录下的文件 |
237
+ | `**/logs/` | 任意深度的 `logs` 目录 |
238
+ | `!important.log` | 例外:不排除该文件 |
239
+
240
+ ## 📋 命令参考
241
+
242
+ ### 命令速查
243
+
244
+ | 命令 | 说明 |
245
+ |------|------|
246
+ | `confmirror backup` | 全量备份(交互确认) |
247
+ | `confmirror backup -m <module>` | 备份指定模块 |
248
+ | `confmirror backup -m <module> --force` | 强制覆盖备份 |
249
+ | `confmirror backup <path>` | 备份指定路径 |
250
+ | `sudo confmirror restore` | 全量还原(建议 root) |
251
+ | `sudo confmirror restore -m <module>` | 还原指定模块 |
252
+ | `confmirror diff -m <module>` | 对比模块差异 |
253
+ | `confmirror perms -m <module>` | 查看权限信息 |
254
+ | `confmirror ls` | 列出所有模块 |
255
+ | `confmirror sync` | 手动同步到 Git 远程 |
256
+ | `confmirror install-system` | 创建系统级入口(解决 `sudo` PATH 问题) |
257
+ | `confmirror global-config-path set <path>` | 设置全局默认配置路径 |
258
+ | `confmirror global-config-path show` | 显示全局配置路径 |
259
+
260
+ ### 全局选项
261
+
262
+ | 选项 | 说明 |
263
+ |------|------|
264
+ | `--format {human,json}` | 输出格式,默认 `human` |
265
+ | `--dry-run` | 预览模式,不实际执行 |
266
+ | `--yes` | 非交互模式,跳过所有确认 |
267
+ | `--config <path>` | 指定配置文件路径 |
268
+ | `--version` | 显示版本 |
269
+ | `--help` | 显示帮助 |
270
+
271
+ ## ⚡ 自动补全
272
+
273
+ ConfMirror 支持命令和模块名称的自动补全功能。您可以使用以下方式安装自动补全:
274
+
275
+ ```bash
276
+ # 对于 Bash 用户
277
+ eval "$(_CONFMIRROR_COMPLETE=bash_source confmirror)"
278
+
279
+ # 对于 Zsh 用户
280
+ eval "$(_CONFMIRROR_COMPLETE=zsh_source confmirror)"
281
+
282
+ # 对于 Fish 用户
283
+ eval "$(_CONFMIRROR_COMPLETE=fish_source confmirror)"
284
+ ```
285
+
286
+ 要永久激活自动补全,请将相应的命令添加到您的 shell 配置文件中(如 `.bashrc`、`.zshrc`)。
287
+
288
+
289
+ ## 📁 目录结构
290
+
291
+ 执行备份后,目录结构如下:
292
+
293
+ ```
294
+ your-project/
295
+ ├── confmirror.yaml # 配置文件
296
+ ├── mirror/ # 配置镜像目录
297
+ │ └── etc/
298
+ │ └── ssh/
299
+ │ ├── sshd_config
300
+ │ └── sshd_config.meta # 元数据文件
301
+ ├── script-hooks/ # 脚本钩子目录
302
+ │ └── ufw/
303
+ │ └── script.sh
304
+ └── logs/ # 日志目录
305
+ └── my-config.log
306
+ ```
307
+
308
+ ## 🔄 与 Git 结合使用
309
+
310
+ 虽然 ConfMirror 本身不依赖 Git,但您可以将其与 Git 结合使用,以获得更好的版本控制体验:
311
+
312
+ ### 初始化 Git 仓库
313
+
314
+ ```bash
315
+ # 初始化 Git 仓库
316
+ git init
317
+
318
+ # 添加配置文件
319
+ git add confmirror.yaml
320
+
321
+ # 配置 .gitignore(logs/ 为运行时日志,建议忽略)
322
+ echo "logs/" >> .gitignore
323
+ ```
324
+
325
+ ### 启用自动提交
326
+
327
+ 在 `confmirror.yaml` 中启用自动提交:
328
+
329
+ ```yaml
330
+ settings:
331
+ git_auto_commit: false # 是否自动提交到 Git(默认 false)
332
+ git_auto_push: false # 是否自动推送到远程(默认 false,需先设置 git_auto_commit)
333
+ ```
334
+
335
+ 启用后,每次执行 `confmirror backup` 命令后,如果启用了 `git_auto_commit`,工具会自动将更改提交到 Git 仓库。
336
+
337
+ ### 手动提交
338
+
339
+ ```bash
340
+ confmirror backup
341
+ git add mirror/ confmirror.yaml
342
+ git commit -m "Backup configuration: $(date +%Y-%m-%d)"
343
+ ```
344
+
345
+ ## 多机管理
346
+
347
+ 多服务器场景的管理策略详见 [docs/MULTI_SERVER.md](docs/MULTI_SERVER.md)。
348
+
349
+
350
+ ## 退出码
351
+
352
+ ConfMirror 使用标准化退出码,便于脚本和 Agent 判断执行结果:
353
+
354
+ | 退出码 | 含义 | 场景 |
355
+ |--------|------|------|
356
+ | `0` | 成功 | 命令正常完成 |
357
+ | `1` | 配置错误 | 配置文件加载失败、参数错误 |
358
+ | `2` | 权限错误 | restore 非 root 运行 |
359
+ | `3` | 部分失败 | 某些文件备份/还原失败,但其他成功 |
360
+
361
+ ## 常见问题
362
+
363
+ ### 权限问题
364
+
365
+ 在某些情况下,备份或还原操作可能需要更高的权限。如果遇到权限错误,可以使用以下方式提权:
366
+
367
+ ```bash
368
+ # 推荐:创建系统级入口(一次配置,永久可用)
369
+ sudo confmirror install-system
370
+ # 之后直接使用:
371
+ sudo confmirror restore
372
+
373
+ # 备选:显式传递 PATH
374
+ sudo env "PATH=$PATH" confmirror backup
375
+
376
+ # 备选:进入 root shell
377
+ sudo -i
378
+ confmirror backup
379
+ ```
380
+
381
+ > `install-system` 会在 `/usr/local/bin/confmirror` 创建一个 wrapper 脚本,内部 hardcode 原始 confmirror 的完整路径,从而绕过 `sudo` 重置 PATH 的问题。卸载时执行 `sudo confmirror uninstall-system`。