• 设为首页
  • 收藏本站
  • 积分充值
  • VIP赞助
  • 手机版
  • 微博
  • 微信
    微信公众号 添加方式:
    1:搜索微信号(888888
    2:扫描左侧二维码
  • 快捷导航
    福建二哥 门户 查看主题

    GitLab 服务器宕机时的项目代码恢复方法

    发布者: 晋3555 | 发布时间: 2025-8-16 11:33| 查看数: 13| 评论数: 0|帖子模式

    1. <strong>重要前提</strong>:GitLab 数据挂载盘必须能够正常读取,且 [code]/var/opt/gitlab/git-data/repositories
    复制代码
    目录下的数据可以完整拷贝。[/code]当 GitLab 服务器意外宕机且没有备份时,项目代码的恢复变得尤为关键。以下是经过优化的恢复流程,相比传统方法更为简洁高效。

    一、数据拷贝与准备


    • 挂载数据盘将宕机服务器的数据盘挂载到其他正常运行的主机或服务器上。确保
      1. /var/opt/gitlab/git-data
      复制代码
      目录下的所有内容能够完整拷贝到新的主机或服务器中。
      1. sudo mount /dev/sdX /mnt/data  # 示例挂载命令,需根据实际情况调整
      复制代码
    • 拷贝数据
      1. /var/opt/gitlab/git-data
      复制代码
      目录下的所有内容完整拷贝到新主机的指定目录,例如
      1. /mnt/recovery
      复制代码
      1. sudo cp -r /mnt/data/var/opt/gitlab/git-data /mnt/recovery/
      复制代码

    二、识别项目数据

    GitLab 的项目数据存储在
    1. /var/opt/gitlab/git-data/repositories/@hashed
    复制代码
    目录下,文件夹名称经过哈希处理,无法直接识别项目信息。但每个项目文件夹(如
    1. xxxxx.git
    复制代码
    )下的
    1. config
    复制代码
    文件中存储了项目相关的部分信息,可以提取仓库所有者及仓库名称。
    1. <strong>注意</strong>:[code]xxx.wiki.git
    复制代码
    1. xxx.design.git
    复制代码
    文件夹通常可以忽略,因为它们不包含重要代码数据,且其
    1. config
    复制代码
    文件中也不包含仓库所有者及仓库名称。[/code]
    三、简化恢复方法

    传统的恢复方法通常需要搭建新的 GitLab 服务器并进行数据镜像,但这种方法存在以下问题:

    • 需要确保新旧服务器的 GitLab 版本完全一致,否则可能导致数据无法正确镜像。
    • 操作步骤繁琐,耗时且容易出错。
    事实上,我们可以采用更简单的方法直接恢复代码,无需搭建新服务器。
    以项目文件夹
    1. 73/47/73475cb40a568e8da8a045ced110137e159f890ac4da883b6b17dc651b3a8049.git
    复制代码
    为例,以下是具体步骤:

    • 设置安全目录由于 GitLab 的项目目录可能被识别为不安全目录,需要通过以下命令将其标记为安全目录:
      1. git config --global --add safe.directory /mnt/recovery/repositories/@hashed/73/47/73475cb40a568e8da8a045ced110137e159f890ac4da883b6b17dc651b3a8049.git
      复制代码
    • 克隆项目在上文中提到,
      1. config
      复制代码
      文件中存储了完整的仓库所有者和仓库名称(例如
      1. author/project_name
      复制代码
      )。我们可以通过克隆操作将项目恢复到本地目录。假设目标项目路径是
      1. your_clone_dir/author/project_name
      复制代码
      ,那么可以执行以下命令来完成克隆:
      1. git clone /mnt/recovery/repositories/@hashed/73/47/73475cb40a568e8da8a045ced110137e159f890ac4da883b6b17dc651b3a8049.git your_clone_dir/author/project_name
      复制代码

    四、自动化恢复脚本

    为了进一步简化操作,以下是一个 Python 脚本,可以快速执行上述操作,只需提供哈希化仓库的源目录和克隆仓库的目标目录。
    1. #!/usr/bin/env python
    2. # -*-coding:utf-8 -*-
    3. # ==============================================================================
    4. # Copyright (c) 2025 laugh12321 Authors. All Rights Reserved.
    5. #
    6. # Licensed under the GNU General Public License v3.0 (the "License");
    7. # you may not use this file except in compliance with the License.
    8. # You may obtain a copy of the License at
    9. #
    10. #     https://www.gnu.org/licenses/gpl-3.0.html  
    11. #
    12. # Unless required by applicable law or agreed to in writing, software
    13. # distributed under the License is distributed on an "AS IS" BASIS,
    14. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    15. # See the License for the specific language governing permissions and
    16. # limitations under the License.
    17. # ==============================================================================
    18. # File    :   hashed_repo_cloner.py
    19. # Version :   1.0
    20. # Author  :   laugh12321
    21. # Contact :   laugh12321@vip.qq.com
    22. # Date    :   2025/03/31 14:51:38
    23. # Desc    :   None
    24. # ==============================================================================
    25. from pathlib import Path
    26. import configparser
    27. import subprocess
    28. import argparse
    29. from typing import Optional
    30. from rich.progress import track
    31. import sys
    32. def extract_repo_name_from_config(config_path: Path) -> str:
    33.     """
    34.     从Git配置文件中提取仓库完整路径
    35.     :param config_path: Git配置文件路径
    36.     :return: 仓库完整路径
    37.     :raises ValueError: 如果配置缺少gitlab段或fullpath键
    38.     :raises FileNotFoundError: 如果配置文件不存在
    39.     """
    40.     if not config_path.is_file():
    41.         raise FileNotFoundError(f"Git config file not found: {config_path}")
    42.     config = configparser.ConfigParser()
    43.     config.read(config_path)
    44.     if 'gitlab' not in config or 'fullpath' not in config['gitlab']:
    45.         raise ValueError(f"Config file missing required gitlab section or fullpath key: {config_path}")
    46.     return config.get('gitlab', 'fullpath')
    47. def add_safe_directory(git_dir: Path) -> None:
    48.     """
    49.     将Git目录添加到安全目录列表
    50.     :param git_dir: Git仓库路径
    51.     """
    52.     subprocess.run(
    53.         ["git", "config", "--global", "--add", "safe.directory", str(git_dir)],
    54.         check=True,
    55.         stdout=subprocess.DEVNULL,  # 将标准输出重定向到 /dev/null
    56.         stderr=subprocess.DEVNULL   # 将标准错误重定向到 /dev/null
    57.     )
    58. def clone_repository(source_dir: Path, target_dir: Path, repo_name: str) -> None:
    59.     """
    60.     克隆仓库到目标目录
    61.     :param source_dir: 源Git仓库路径
    62.     :param target_dir: 目标目录路径
    63.     :param repo_name: 仓库名称
    64.     """
    65.     target_path = target_dir / repo_name
    66.     subprocess.run(
    67.         ["git", "clone", str(source_dir), str(target_path)],
    68.         check=True,
    69.         stdout=subprocess.DEVNULL,  # 将标准输出重定向到 /dev/null
    70.         stderr=subprocess.DEVNULL   # 将标准错误重定向到 /dev/null
    71.     )
    72. def process_git_repositories(hashed_repos_dir: Path, output_dir: Path) -> None:
    73.     """
    74.     处理所有哈希化的Git仓库并将其克隆到输出目录
    75.     :param hashed_repos_dir: 包含哈希化仓库的目录
    76.     :param output_dir: 输出目录
    77.     """
    78.     # 预过滤.git目录,排除wiki和design仓库
    79.     git_folders = [
    80.         folder for folder in hashed_repos_dir.rglob("*.git")
    81.         if not folder.name.endswith((".wiki.git", ".design.git"))
    82.     ]
    83.     if not git_folders:
    84.         print("No valid Git repositories found to process.")
    85.         return
    86.     for git_folder in track(git_folders, description="Processing repositories"):
    87.         config_path = git_folder / "config"
    88.         try:
    89.             repo_name = extract_repo_name_from_config(config_path)
    90.             add_safe_directory(git_folder)
    91.             clone_repository(git_folder, output_dir, repo_name)
    92.         except Exception as e:
    93.             print(f"Error processing {git_folder.name}: {e}")
    94.             sys.exit()  # 终止程序
    95. def validate_directory(path: Optional[str]) -> Path:
    96.     """
    97.     验证并将路径字符串转换为Path对象
    98.     :param path: 路径字符串
    99.     :return: Path对象
    100.     :raises ValueError: 如果路径不存在或不是目录
    101.     """
    102.     if path is None:
    103.         raise ValueError("Path cannot be None")
    104.     path_obj = Path(path)
    105.     if not path_obj.exists():
    106.         raise ValueError(f"Path does not exist: {path}")
    107.     if not path_obj.is_dir():
    108.         raise ValueError(f"Path is not a directory: {path}")
    109.     return path_obj
    110. def parse_arguments():
    111.     """
    112.     解析命令行参数
    113.     :return: 包含参数的命名空间
    114.     """
    115.     parser = argparse.ArgumentParser(
    116.         description="将GitLab哈希化仓库克隆到目标目录",
    117.         formatter_class=argparse.ArgumentDefaultsHelpFormatter
    118.     )
    119.     parser.add_argument(
    120.         "--source",
    121.         type=str,
    122.         required=True,
    123.         help="包含哈希化仓库的源目录(必须)"
    124.     )
    125.     parser.add_argument(
    126.         "--output",
    127.         type=str,
    128.         required=True,
    129.         help="克隆仓库的目标目录(必须)"
    130.     )
    131.     return parser.parse_args()
    132. def main():
    133.     args = parse_arguments()
    134.     try:
    135.         source_dir = validate_directory(args.source)
    136.         output_dir = Path(args.output)
    137.         process_git_repositories(source_dir, output_dir)
    138.     except ValueError as e:
    139.         print(f"Argument error: {e}")
    140.         return 1
    141.     return 0
    142. if __name__ == "__main__":
    143.     exit(main())
    复制代码
    使用方法

    运行以下命令即可启动脚本:
    1. python hashed_repo_cloner.py --source gitlab_hashed_dir --output project_out_dir
    复制代码
    五、后续操作


    • 验证恢复结果进入克隆后的项目目录,检查代码完整性,确保所有分支和提交记录都已正确恢复。
      1. cd project_out_dir/author/project_name
      2. git log  # 查看提交记录
      3. git branch -a  # 查看所有分支
      复制代码
    • 重新托管到 GitLab 或其他平台如果需要将恢复的代码重新托管到 GitLab 或其他代码托管平台,可以按照以下步骤操作:

      • 在目标平台创建新的仓库。
      • 将本地克隆的项目推送到新仓库:
        1. git remote add origin <新仓库的URL>
        2. git push -u origin --all
        3. git push -u origin --tags
        复制代码

    通过上述方法,我们无需搭建新服务器,也无需担心版本兼容问题,能够快速高效地恢复 GitLab 项目代码。
    到此这篇关于GitLab 服务器宕机时的项目代码恢复方法的文章就介绍到这了,更多相关GitLab 服务器宕机内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

    来源:互联网
    免责声明:如果侵犯了您的权益,请联系站长(1277306191@qq.com),我们会及时删除侵权内容,谢谢合作!

    最新评论

    浏览过的版块

    QQ Archiver 手机版 小黑屋 福建二哥 ( 闽ICP备2022004717号|闽公网安备35052402000345号 )

    Powered by Discuz! X3.5 © 2001-2023

    快速回复 返回顶部 返回列表