重要前提:gitlab 数据挂载盘必须能够正常读取,且
/var/opt/gitlab/git-data/repositories
目录下的数据可以完整拷贝。
当 gitlab 服务器意外宕机且没有备份时,项目代码的恢复变得尤为关键。以下是经过优化的恢复流程,相比传统方法更为简洁高效。
一、数据拷贝与准备
挂载数据盘将宕机服务器的数据盘挂载到其他正常运行的主机或服务器上。确保
/var/opt/gitlab/git-data
目录下的所有内容能够完整拷贝到新的主机或服务器中。sudo mount /dev/sdx /mnt/data # 示例挂载命令,需根据实际情况调整
拷贝数据将
/var/opt/gitlab/git-data
目录下的所有内容完整拷贝到新主机的指定目录,例如/mnt/recovery
。sudo cp -r /mnt/data/var/opt/gitlab/git-data /mnt/recovery/
二、识别项目数据
gitlab 的项目数据存储在 /var/opt/gitlab/git-data/repositories/@hashed
目录下,文件夹名称经过哈希处理,无法直接识别项目信息。但每个项目文件夹(如 xxxxx.git
)下的 config
文件中存储了项目相关的部分信息,可以提取仓库所有者及仓库名称。
注意:
xxx.wiki.git
和xxx.design.git
文件夹通常可以忽略,因为它们不包含重要代码数据,且其config
文件中也不包含仓库所有者及仓库名称。
三、简化恢复方法
传统的恢复方法通常需要搭建新的 gitlab 服务器并进行数据镜像,但这种方法存在以下问题:
- 需要确保新旧服务器的 gitlab 版本完全一致,否则可能导致数据无法正确镜像。
- 操作步骤繁琐,耗时且容易出错。
事实上,我们可以采用更简单的方法直接恢复代码,无需搭建新服务器。
以项目文件夹 73/47/73475cb40a568e8da8a045ced110137e159f890ac4da883b6b17dc651b3a8049.git
为例,以下是具体步骤:
设置安全目录由于 gitlab 的项目目录可能被识别为不安全目录,需要通过以下命令将其标记为安全目录:
git config --global --add safe.directory /mnt/recovery/repositories/@hashed/73/47/73475cb40a568e8da8a045ced110137e159f890ac4da883b6b17dc651b3a8049.git
克隆项目在上文中提到,
config
文件中存储了完整的仓库所有者和仓库名称(例如author/project_name
)。我们可以通过克隆操作将项目恢复到本地目录。假设目标项目路径是your_clone_dir/author/project_name
,那么可以执行以下命令来完成克隆:git clone /mnt/recovery/repositories/@hashed/73/47/73475cb40a568e8da8a045ced110137e159f890ac4da883b6b17dc651b3a8049.git your_clone_dir/author/project_name
四、自动化恢复脚本
为了进一步简化操作,以下是一个 python 脚本,可以快速执行上述操作,只需提供哈希化仓库的源目录和克隆仓库的目标目录。
#!/usr/bin/env python # -*-coding:utf-8 -*- # ============================================================================== # copyright (c) 2025 laugh12321 authors. all rights reserved. # # licensed under the gnu general public license v3.0 (the "license"); # you may not use this file except in compliance with the license. # you may obtain a copy of the license at # # https://www.gnu.org/licenses/gpl-3.0.html # # unless required by applicable law or agreed to in writing, software # distributed under the license is distributed on an "as is" basis, # without warranties or conditions of any kind, either express or implied. # see the license for the specific language governing permissions and # limitations under the license. # ============================================================================== # file : hashed_repo_cloner.py # version : 1.0 # author : laugh12321 # contact : laugh12321@vip.qq.com # date : 2025/03/31 14:51:38 # desc : none # ============================================================================== from pathlib import path import configparser import subprocess import argparse from typing import optional from rich.progress import track import sys def extract_repo_name_from_config(config_path: path) -> str: """ 从git配置文件中提取仓库完整路径 :param config_path: git配置文件路径 :return: 仓库完整路径 :raises valueerror: 如果配置缺少gitlab段或fullpath键 :raises filenotfounderror: 如果配置文件不存在 """ if not config_path.is_file(): raise filenotfounderror(f"git config file not found: {config_path}") config = configparser.configparser() config.read(config_path) if 'gitlab' not in config or 'fullpath' not in config['gitlab']: raise valueerror(f"config file missing required gitlab section or fullpath key: {config_path}") return config.get('gitlab', 'fullpath') def add_safe_directory(git_dir: path) -> none: """ 将git目录添加到安全目录列表 :param git_dir: git仓库路径 """ subprocess.run( ["git", "config", "--global", "--add", "safe.directory", str(git_dir)], check=true, stdout=subprocess.devnull, # 将标准输出重定向到 /dev/null stderr=subprocess.devnull # 将标准错误重定向到 /dev/null ) def clone_repository(source_dir: path, target_dir: path, repo_name: str) -> none: """ 克隆仓库到目标目录 :param source_dir: 源git仓库路径 :param target_dir: 目标目录路径 :param repo_name: 仓库名称 """ target_path = target_dir / repo_name subprocess.run( ["git", "clone", str(source_dir), str(target_path)], check=true, stdout=subprocess.devnull, # 将标准输出重定向到 /dev/null stderr=subprocess.devnull # 将标准错误重定向到 /dev/null ) def process_git_repositories(hashed_repos_dir: path, output_dir: path) -> none: """ 处理所有哈希化的git仓库并将其克隆到输出目录 :param hashed_repos_dir: 包含哈希化仓库的目录 :param output_dir: 输出目录 """ # 预过滤.git目录,排除wiki和design仓库 git_folders = [ folder for folder in hashed_repos_dir.rglob("*.git") if not folder.name.endswith((".wiki.git", ".design.git")) ] if not git_folders: print("no valid git repositories found to process.") return for git_folder in track(git_folders, description="processing repositories"): config_path = git_folder / "config" try: repo_name = extract_repo_name_from_config(config_path) add_safe_directory(git_folder) clone_repository(git_folder, output_dir, repo_name) except exception as e: print(f"error processing {git_folder.name}: {e}") sys.exit() # 终止程序 def validate_directory(path: optional[str]) -> path: """ 验证并将路径字符串转换为path对象 :param path: 路径字符串 :return: path对象 :raises valueerror: 如果路径不存在或不是目录 """ if path is none: raise valueerror("path cannot be none") path_obj = path(path) if not path_obj.exists(): raise valueerror(f"path does not exist: {path}") if not path_obj.is_dir(): raise valueerror(f"path is not a directory: {path}") return path_obj def parse_arguments(): """ 解析命令行参数 :return: 包含参数的命名空间 """ parser = argparse.argumentparser( description="将gitlab哈希化仓库克隆到目标目录", formatter_class=argparse.argumentdefaultshelpformatter ) parser.add_argument( "--source", type=str, required=true, help="包含哈希化仓库的源目录(必须)" ) parser.add_argument( "--output", type=str, required=true, help="克隆仓库的目标目录(必须)" ) return parser.parse_args() def main(): args = parse_arguments() try: source_dir = validate_directory(args.source) output_dir = path(args.output) process_git_repositories(source_dir, output_dir) except valueerror as e: print(f"argument error: {e}") return 1 return 0 if __name__ == "__main__": exit(main())
使用方法
运行以下命令即可启动脚本:
python hashed_repo_cloner.py --source gitlab_hashed_dir --output project_out_dir
五、后续操作
验证恢复结果进入克隆后的项目目录,检查代码完整性,确保所有分支和提交记录都已正确恢复。
cd project_out_dir/author/project_name git log # 查看提交记录 git branch -a # 查看所有分支
重新托管到 gitlab 或其他平台如果需要将恢复的代码重新托管到 gitlab 或其他代码托管平台,可以按照以下步骤操作:
- 在目标平台创建新的仓库。
- 将本地克隆的项目推送到新仓库:
git remote add origin <新仓库的url> git push -u origin --all git push -u origin --tags
通过上述方法,我们无需搭建新服务器,也无需担心版本兼容问题,能够快速高效地恢复 gitlab 项目代码。
到此这篇关于gitlab 服务器宕机时的项目代码恢复方法的文章就介绍到这了,更多相关gitlab 服务器宕机内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论