私服 nexus 之间迁移 npm 仓库

本文介绍如何将一个 Nexus 特定仓库中的 npm 包内容迁移到另一个 Nexus 特定仓库。此过程适用于需要重构仓库结构或合并仓库的场景。

迁移脚本

以下是完整的迁移脚本,它会自动完成以下操作:

  1. 从源仓库获取所有 npm 包列表
  2. 下载每个包的 .tgz 文件
  3. 解压并重新发布到目标仓库
bash 复制代码
#!/bin/bash

# === 配置区域 ===
NEXUS_URL="https://nexus.test.com"
USERNAME="test"
PASSWORD="123456"

SOURCE_REPO="npm-a"
TARGET_REPO="npm-b"

SOURCE_REGISTRY="$NEXUS_URL/repository/$SOURCE_REPO/"
TARGET_REGISTRY="$NEXUS_URL/repository/$TARGET_REPO/"

TMP_DIR="/tmp/npm-migrate"
mkdir -p "$TMP_DIR"
cd "$TMP_DIR" || exit 1
# =================

# ✅ 日志处理:同时输出到终端和日志文件
LOG_FILE="$TMP_DIR/npm-migrate.log"
exec > >(tee -a "$LOG_FILE") 2>&1

log() {
  echo "[$(date '+%F %T')] $*"
}

log "🚀 启动 npm 仓库迁移脚本"

# 遇到错误不中断脚本
set +e

TOKEN=""

while true; do
    log "📥 获取包列表,continuationToken=$TOKEN"

    RESPONSE=$(curl -s -u "$USERNAME:$PASSWORD" \
      "$NEXUS_URL/service/rest/v1/components?repository=$SOURCE_REPO${TOKEN:+&continuationToken=$TOKEN}")

    ITEM_COUNT=$(echo "$RESPONSE" | jq '.items | length')
    log "📦 本页包含 $ITEM_COUNT 个包"

    echo "$RESPONSE" | jq -c '.items[]' | while read -r item; do
        name=$(echo "$item" | jq -r '.assets[0].path' | cut -d/ -f1)
        version=$(echo "$item" | jq -r '.version')

        log "➡️ 处理 $name@$version"

        tarball_url="${SOURCE_REGISTRY}${name}/-/${name}-${version}.tgz"
        tarball_file="${name}-${version}.tgz"

        log "🌐 下载包: $tarball_url"
        curl -s -u "$USERNAME:$PASSWORD" -O "$tarball_url"

        if [[ -f "$tarball_file" ]]; then
            tar -xzf "$tarball_file"
            pkg_dir="package"

            # 可选:检查是否已存在(加快速度)
            EXISTS=$(curl -s -u "$USERNAME:$PASSWORD" "$TARGET_REGISTRY$name" | grep "\"$version\"")
            if [[ -n "$EXISTS" ]]; then
                log "✅ $name@$version 已存在于目标仓库,跳过发布"
            else
                log "🚀 发布 $name@$version 到 $TARGET_REPO"
                npm publish "$pkg_dir" --registry "$TARGET_REGISTRY" --force
                if [[ $? -ne 0 ]]; then
                    log "❌ 发布失败:$name@$version"
                else
                    log "✅ 发布成功:$name@$version"
                fi
            fi

            rm -rf "$tarball_file" "$pkg_dir"
        else
            log "❌ 下载失败:$tarball_url"
        fi
    done

    # 分页处理
    TOKEN=$(echo "$RESPONSE" | jq -r '.continuationToken')
    if [[ "$TOKEN" == "null" || -z "$TOKEN" ]]; then
        log "✅ 所有包处理完成,无更多分页"
        break
    else
        log "➡️ 获取下一页 continuationToken=$TOKEN"
    fi
done

log "🏁 所有迁移已完成"

~/.npmrc 中配置目标仓库的 auth 认证信息,因为发布包要使用,内容如下示例:

bash 复制代码
registry=https://nexus.test.com/repository/npm-b/
//nexus.test.com/repository/npm-b/:_auth=c45h2312asmh3dsfYW3fassaawRAxMde=
//nexus.test.com/repository/npm-b/:always-auth=true

其中 _auth 后面的内容是对 "账号:密码" 进行base64之后的字符串,注意账号密码使用英文冒号分隔拼接在一起后统一 base64。

使用说明

  • 确保已安装 curl, jq, npmtar 工具

  • 确保有源仓库和目标仓库的访问权限

执行脚本:

bash 复制代码
chmod +x migrate.sh
./migrate.sh

注意事项

  • 此脚本仅处理源仓库中的第一页数据(默认100条记录),如需处理更多数据,需要添加分页逻辑

  • 迁移过程中会保留原始包的版本信息

  • 使用 --force 参数强制发布,可能会覆盖目标仓库中已存在的同名包

  • 脚本执行完毕后会自动清理临时文件


(END)

相关推荐
源去_云走4 小时前
自建 Iconfy API 服务:解决国内访问不稳定问题
前端·容器·npm·node.js
lee57610 小时前
鄙人的 Vue 3.0 商业级开源甘特图已经发布到 npm
前端·vue.js·npm·开源·甘特图
小信丶1 天前
解决 pnpm dev 报错:系统禁止运行脚本的问题
前端·vue.js·windows·npm
小邋遢2.01 天前
vscod 执行npm build报错:Error: Cannot find module ‘vite‘
前端·npm·node.js
孟陬1 天前
2025-12-11 之后前端 npm 如何发包 How to Publish NPM Package in Year 2025
npm·node.js·bun
吴敬悦2 天前
私有的 GitHub Package 怎么拉取?
npm·github
前端郭德纲2 天前
React 19.2 已发布,现已上线 npm!
前端·react.js·npm
LYFlied2 天前
【一句话概括】前端项目包管理器怎么选?
前端·npm·pnpm·yarn
LisEcho3 天前
yoyoj-rn — RN 的脚手架工具可以不是 @react-native-community/cli
前端·react native·npm
醉风塘3 天前
NPM:从“模块之痛”到“生态之基”的演化史
前端·npm·node.js