GithubHelp home page GithubHelp logo

better_backup's People

Contributors

alex3236 avatar cranyozen avatar ucketx avatar z0z0r4 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

better_backup's Issues

可能是因为mklink导致无法回档

4bc5b29d8e45eb4b40f7096d530266f0 如题,在回滚时可能系工作目录异常没有找到./world路径

且在回滚失败后没有后续处理手段导致mcdr一直停留在wait for start,只能通过强制杀死进程来重新启动服务器

从 v1.x 迁移到 v2.x SQlite 支持

v1.x 与 v2.x 采用不同的数据结构,互相不兼容,且没有提供降级脚本,属于不可逆更新

如确认需要更新,务必在更新前依照以下过程迁移数据或直接删除 better_backup 文件夹以清空备份数据

  1. 确保已安装 pydal pip install pydal 以完成迁移,同时这也是 v2.x 的一必须前置
  2. 下载 migrate.py 并放入你的 MCDR 所在根目录
    """
    用于从 v1.x 迁移到 v2.x
    如非默认,请将 better_backup 数据所在写入 BACKUP_DATA_PATH
    并将此文件放于所在 MCDR 的根目录下运行
    """
    import os
    from shutil import rmtree
    import json
    from pydal import DAL, Field
    import datetime
    database: DAL = None
    BACKUP_DATA_PATH = "better_backup"
    if os.path.exists(BACKUP_DATA_PATH):
    print(f"已找到 {BACKUP_DATA_PATH}")
    else:
    print(f"未找到 {BACKUP_DATA_PATH},请确认better_backup 数据所在")
    exit(1)
    def load_database():
    global database
    os.makedirs(BACKUP_DATA_PATH, exist_ok=True)
    database = DAL("sqlite://storage.db", folder=BACKUP_DATA_PATH)
    if "files" not in database.tables:
    database.define_table(
    "files",
    Field("backup_uuid"),
    Field("name"),
    Field("hash"),
    Field("hash_type"),
    Field("path"),
    )
    if "backups" not in database.tables:
    database.define_table(
    "backups",
    Field("uuid"),
    Field("time", type="integer"),
    Field("size", type="integer"),
    Field("message"),
    )
    def get_all_backup_info(metadata_dir: str) -> list:
    all_backup_info = []
    for backup in os.listdir(metadata_dir):
    if (
    not backup == "cache_index.json"
    and os.path.isfile(os.path.join(metadata_dir, backup))
    and backup[-5:] == ".json"
    ):
    backup_path = os.path.join(metadata_dir, backup)
    with open(backup_path, encoding="UTF-8") as f:
    all_backup_info.append(json.load(f))
    return all_backup_info
    def scan_backup_info(backup_uuid: str, backup_info: dict, root_path: str = ""):
    for info in backup_info:
    if backup_info[info]["type"] == "file":
    database.files.insert(
    backup_uuid=backup_uuid,
    name=info,
    path=root_path,
    hash=backup_info[info]["md5"],
    hash_type="md5",
    )
    elif backup_info[info]["type"] == "dir":
    scan_backup_info(
    backup_uuid,
    backup_info[info]["files"],
    root_path=os.path.join(root_path, info),
    )
    if __name__ == "__main__":
    load_database()
    all_info = get_all_backup_info(os.path.join(BACKUP_DATA_PATH, "metadata"))
    for backup_info in all_info:
    database.backups.insert(
    uuid=backup_info["backup_uuid"],
    time=int(
    datetime.datetime.strptime(
    backup_info["backup_time"], "%Y-%m-%d %H:%M:%S"
    ).timestamp()
    ),
    size=backup_info["backup_size"],
    message=backup_info["backup_message"],
    )
    scan_backup_info(
    backup_uuid=backup_info["backup_uuid"],
    backup_info=backup_info["backup_files"],
    )
    print(f'已迁移 {backup_info["backup_uuid"]}')
    database.commit()
    rmtree(os.path.join(BACKUP_DATA_PATH, "metadata"))
    # print(f"已完成,请在备份后手动删除 {BACKUP_DATA_PATH}/metadata 文件夹")
  3. 确认你的备份数据所在,如未修改过则默认 better_backup 无需理会
  4. 运行 migrate.py 开始迁移 python migrate.py
  5. 如输出为 已完成,请更新至 v2.x,v1.x 不再兼容 则为成功,请安装 v2.x 的 better_backup 插件

无法 reset

> !!bb reset
[MCDR] [11:04:53] [better_backup:reset_cache/INFO]: [Better Backup] 准备重置备份数据
Exception in thread better_backup:reset_cache:
Traceback (most recent call last):
  File "D:\Python\Python311\Lib\threading.py", line 1038, in _bootstrap_inner
    self.run()
  File "D:\Python\Python311\Lib\threading.py", line 975, in run
    self._target(*self._args, **self._kwargs)
  File "D:\Python\Python311\Lib\site-packages\mcdreforged\api\decorator\new_thread.py", line 29, in wrapped_target
    raise e from None
  File "D:\Python\Python311\Lib\site-packages\mcdreforged\api\decorator\new_thread.py", line 26, in wrapped_target
    self.__return_value = target(*args_, **kwargs_)
                          ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\projects\mcdr\plugins\better_backup\better_backup\utils.py", line 154, in wrap
    func(source, *args, **kwargs)
  File "D:\projects\mcdr\plugins\better_backup\better_backup\operations.py", line 340, in reset_cache
    raise e #! TODO: handle database.close
    ^^^^^^^
  File "D:\projects\mcdr\plugins\better_backup\better_backup\operations.py", line 338, in reset_cache
    database.close()
  File "D:\Python\Python311\Lib\site-packages\pydal\base.py", line 809, in close
    if self._db_uid in THREAD_LOCAL._pydal_db_instances_:
                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: '_thread._local' object has no attribute '_pydal_db_instances_'

基准测试

渲染不同大小的地图后,获取得首次备份、第二次备份耗时,以及 QucikBackupM 的耗时进行对比

  • SSD PC SN520 NVMe WDC 512GB
  • CPU Intel(R) Core(TM) i5-9300H CPU @ 2.40GHz

结论

  • 首次备份时无论如何 Better_Backup 都会慢于 QucikBackupM,原因在于逻辑不同
  • 在存档较小时 QucikBackupM 速率占优,但此时耗时基本上都很小,区别不大
  • 在存档较大,如 10G 左右,QucikBackupM 与 Better_Backup 速率基本持平,耗时 30s 左右
  • 在存档更大后,Better_Backup 备份速度明显快于 QucikBackupM,在 16G 时将近只需要一半的时间
  • 然而速率总体基本持平的事实立足于占用空间原小于 QucikBackupM 的基础上,所以推荐使用 Better_Backup

详细测试结果如下,使用 Chunky 插件渲染地图

2000 Radius
image

> !!qb make
[MCDR] [16:00:39] [QBM - create/INFO]: [QBM] 备份中...请稍等
[Server] [16:00:39 INFO]: Automatic saving is now disabled
[Server] [16:00:39 INFO]: Saving the game (this may take a moment!)
[Server] [16:00:39 INFO]: ThreadedAnvilChunkStorage (world): All chunks are saved
[Server] [16:00:39 INFO]: ThreadedAnvilChunkStorage (DIM-1): All chunks are saved
[Server] [16:00:39 INFO]: ThreadedAnvilChunkStorage (DIM1): All chunks are saved
[Server] [16:00:39 INFO]: ThreadedAnvilChunkStorage: All dimensions are saved
[Server] [16:00:39 INFO]: Saved the game
[MCDR] [16:00:39] [QBM - create/INFO] [quick_backup_multi]: Slot 1 (None) is deleted to provide spaces for the incoming backup
[MCDR] [16:00:39] [QBM - create/INFO] [quick_backup_multi]: copying ./server\world -> ./qb_multi\slot1\world
[MCDR] [16:00:40] [QBM - create/INFO]: [QBM] 备份完成,耗时0.9秒
[MCDR] [16:00:40] [QBM - create/INFO]: [QBM] 日期: 2023-08-11 16:00:40; 注释: 空
[Server] [16:00:40 INFO]: Automatic saving is now enabled
> !!bb make
[MCDR] [16:00:46] [BB - create/INFO]: [Better Backup] 备份中...请稍等
[Server] [16:00:46 INFO]: Automatic saving is now disabled
[Server] [16:00:46 INFO]: Saving the game (this may take a moment!)
[Server] [16:00:46 INFO]: ThreadedAnvilChunkStorage (world): All chunks are saved
[Server] [16:00:46 INFO]: ThreadedAnvilChunkStorage (DIM-1): All chunks are saved
[Server] [16:00:46 INFO]: ThreadedAnvilChunkStorage (DIM1): All chunks are saved
[Server] [16:00:46 INFO]: ThreadedAnvilChunkStorage: All dimensions are saved
[Server] [16:00:46 INFO]: Saved the game
[MCDR] [16:00:50] [BB - create/INFO]: [Better Backup] 备份 78ab22 完成,耗时3.9秒 * 737.58 MB * None
[MCDR] [16:00:50] [BB - create/INFO]: [Better Backup] 检测到新增的备份,重置定时器
[MCDR] [16:00:50] [BB - create/INFO]: [Better Backup] 下次自动备份时间: 2023/08/11 16:01:05
[Server] [16:00:50 INFO]: Automatic saving is now enabled
> !!bb make
[MCDR] [16:00:54] [BB - create/INFO]: [Better Backup] 备份中...请稍等
[Server] [16:00:54 INFO]: Automatic saving is now disabled
[Server] [16:00:54 INFO]: Saving the game (this may take a moment!)
[Server] [16:00:54 INFO]: ThreadedAnvilChunkStorage (world): All chunks are saved
[Server] [16:00:54 INFO]: ThreadedAnvilChunkStorage (DIM-1): All chunks are saved
[Server] [16:00:54 INFO]: ThreadedAnvilChunkStorage (DIM1): All chunks are saved
[Server] [16:00:54 INFO]: ThreadedAnvilChunkStorage: All dimensions are saved
[Server] [16:00:54 INFO]: Saved the game
[MCDR] [16:00:55] [BB - create/INFO]: [Better Backup] 备份 3c20a8 完成,耗时1.7秒 * 737.58 MB * None
[MCDR] [16:00:55] [BB - create/INFO]: [Better Backup] 检测到新增的备份,重置定时器
[MCDR] [16:00:55] [BB - create/INFO]: [Better Backup] 下次自动备份时间: 2023/08/11 16:01:10
[Server] [16:00:55 INFO]: Automatic saving is now enabled

自动清除旧备份时会删除所有备份

版本: 2.1.5

[MCDR] [19:59:22] [better_backup:timer/INFO]: [Better Backup] 每 30.0 分钟一次的定时备份触发
[MCDR] [19:59:22] [better_backup:timer/INFO]: [Better Backup] 备份中...请稍等
[Server] [19:59:22] [Server thread/INFO]: Automatic saving is now disabled
[Server] [19:59:22] [Server thread/INFO]: Saving the game (this may take a moment!)
[Server] [19:59:22] [Server thread/INFO]: ThreadedAnvilChunkStorage (world): All chunks are saved
[Server] [19:59:22] [Server thread/INFO]: ThreadedAnvilChunkStorage (DIM1): All chunks are saved
[Server] [19:59:22] [Server thread/INFO]: ThreadedAnvilChunkStorage (DIM-1): All chunks are saved
[Server] [19:59:22] [Server thread/INFO]: ThreadedAnvilChunkStorage: All dimensions are saved
[Server] [19:59:22] [Server thread/INFO]: Saved the game
[MCDR] [19:59:39] [better_backup:timer/INFO]: [Better Backup] 备份 0e598d 完成,耗时 17.4 秒 * 1.05 GB * timer 定时备份
[MCDR] [19:59:39] [better_backup:timer/INFO]: [Better Backup] 检测到新增的备份,重置定时器
[MCDR] [19:59:39] [better_backup:timer/INFO]: [Better Backup] 下次自动备份时间: 2023/08/29 20:29:39
[MCDR] [20:00:36] [better_backup:timer/INFO]: [Better Backup] 已自动删除备份点 6cc83e * 394f74 * b800b2 * eaa515 * 8cb688 * e45d0a * da8f4a * dd5ec2 * 92d627 * 39c0cc * 3a863b * f38a0f * 89eb3b * 47cd1a * afa747 * 57e1bb * 9b493c * c08a93 * 60b7b0 * ec9c62 * 69ebb6 * 0f1af1 * 4a047b * b310b9 * 512cef * d966a4 * 3b8d44 * 35719a * c53a0a * 767b79 * f12465 * 5eb324 * ff5cc9 * 6f6bdb * 751091 * 30f175 * 64367d * 81263e * cb4563 * f59bbb * fe6ab4 * 8abb88 * 13b4d9 * 5342bc * fe2f63 * 4bc183 * de9a8c * 72cd82 * f1590f * ad02c1
[MCDR] [20:00:36] [better_backup:timer/INFO]: [Better Backup] 定时备份成功
[Server] [20:00:36] [Server thread/INFO]: Automatic saving is now enabled
> !!bb list
[MCDR] [20:03:34] [TaskExecutor/INFO]: [备份点信息]
[MCDR] [20:03:34] [TaskExecutor/INFO]: [01] [0e598d] 23-08-29 19:59 * 1.05 GB   * timer 定时备份
[MCDR] [20:03:34] [TaskExecutor/INFO]: [<<] 1/1 [>>]
[MCDR] [20:03:34] [TaskExecutor/INFO]: 共 1 个备份点,占用空间 1.05 GB

配置文件:

{
    "size_display": true,
    "turn_off_auto_save": true,
    "ignored_files": [
        "session.lock"
    ],
    "ignored_folders": [],
    "ignored_extensions": [
        ".lock"
    ],
    "world_names": [
        "world"
    ],
    "save_command": {
        "save-off": "save-off",
        "save-all flush": "save-all flush",
        "save-on": "save-on"
    },
    "saved_output": [
        "Saved the game",
        "Saved the world"
    ],
    "backup_data_path": "./better_backup",
    "server_path": "./server",
    "overwrite_backup_folder": "overwrite",
    "backup_compress_level": 3,
    "export_backup_folder": "./export_backup",
    "export_backup_format": "tar_gz",
    "export_backup_compress_level": 1,
    "auto_remove": true,
    "backup_count_limit": 50,
    "minimum_permission_level": {
        "make": 1,
        "restore": 2,
        "remove": 2,
        "confirm": 1,
        "abort": 1,
        "reload": 2,
        "list": 0,
        "reset": 2,
        "timer": 2,
        "export": 4
    },
    "timer_enabled": true,
    "timer_interval": 30.0
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.