根据你提供的 Modelfile 内容,模型的核心权重文件路径已经明确:
/root/.ollama/models/blobs/sha256-dec52a44569a2a25341c4e3fee25846eed4f6f0b936278e3a3c900bb99d37c

注意:在文件系统中,这个文件的实际文件名通常是 sha256-dec52a...(将冒号 : 替换为连字符 -,或者本身就是文件名)。

下面是一个完整的 打包脚本 和对应的 部署脚本。

1. 源服务器打包脚本 (package_ollama_model.sh)

在当前服务器(有模型的机器)上创建此脚本并运行。它会自动提取 Modelfile 中指定的 blob 文件,并将它们与 Modelfile 一起打包。

#!/bin/bash

# 配置变量
MODEL_NAME="qwen3.5:9b"
MODelfile_NAME="qwen3.5.9b.Modelfile"
OUTPUT_TAR="ollama-qwen3.5-9b-offline-package.tar.gz"
WORK_DIR="./offline_package_temp"
BLOB_DIR="$HOME/.ollama/models/blobs"

echo ">>> 开始打包模型: $MODEL_NAME"

# 1. 清理临时目录
rm -rf "$WORK_DIR"
mkdir -p "$WORK_DIR/blobs"

# 2. 复制 Modelfile
if [ ! -f "$MODelfile_NAME" ]; then
    echo "错误: 找不到文件 $MODelfile_NAME,请先运行 'ollama show $MODEL_NAME --modelfile > $MODelfile_NAME'"
    exit 1
fi
cp "$MODelfile_NAME" "$WORK_DIR/Modelfile"
echo "已复制 Modelfile"

# 3. 从 Modelfile 中提取 Blob 哈希值
# 查找以 FROM 开头且路径包含 blobs 的行
BLOB_PATH=$(grep "^FROM " "$WORK_DIR/Modelfile" | awk '{print $2}')

if [ -z "$BLOB_PATH" ]; then
    echo "错误: 无法从 Modelfile 中解析出 Blob 路径"
    exit 1
fi

# 提取文件名 (例如: sha256-dec52...)
BLOB_FILENAME=$(basename "$BLOB_PATH")

echo "检测到依赖的 Blob 文件: $BLOB_FILENAME"

# 4. 复制 Blob 文件
if [ ! -f "$BLOB_DIR/$BLOB_FILENAME" ]; then
    # 尝试另一种命名格式 (有时候是 sha256:xxx 变成 sha256-xxx)
    # Ollama 内部通常存储为 sha256-<hash>
    echo "警告: 直接路径未找到,尝试查找匹配的文件..."
    BLOB_FILENAME=$(ls "$BLOB_DIR" | grep -E "^sha256-[a-f0-9]{64}$" | head -n 1)
    if [ -z "$BLOB_FILENAME" ]; then
        echo "错误: 在 $BLOB_DIR 中找不到对应的权重文件。"
        exit 1
    fi
fi

cp "$BLOB_DIR/$BLOB_FILENAME" "$WORK_DIR/blobs/"
echo "已复制权重文件 ($(du -h "$WORK_DIR/blobs/$BLOB_FILENAME" | cut -f1))"

# 5. 打包
tar -czvf "$OUTPUT_TAR" -C "$WORK_DIR" .

echo ">>> 打包完成!"
echo "输出文件: $(pwd)/$OUTPUT_TAR"
echo "文件大小: $(du -h "$OUTPUT_TAR" | cut -f1)"
echo ""
echo "请将此文件和 ollama 二进制程序传输到离线服务器。"

# 清理临时目录
rm -rf "$WORK_DIR"

使用方法:

  1. 保存为 package_ollama_model.sh。
  2. 赋予执行权限:chmod +x package_ollama_model.sh。
  3. 运行:./package_ollama_model.sh。
  4. 生成的 ollama-qwen3.5-9b-offline-package.tar.gz 即为所需包。

2. 目标离线服务器部署脚本 (deploy_ollama_model.sh)

将上述生成的 .tar.gz 包以及 ollama 二进制程序(确保版本兼容,建议也是 0.18.1)传到离线服务器后,运行此脚本。

前提条件:

  • 已安装 ollama 命令(即使还没运行过)。
  • 已将 ollama-qwen3.5-9b-offline-package.tar.gz 上传到当前目录。
#!/bin/bash

# 配置变量
PACKAGE_FILE="ollama-qwen3.5-9b-offline-package.tar.gz"
MODEL_NAME="qwen3.5:9b"
OLLAMA_DATA_DIR="$HOME/.ollama"
BLOB_DIR="$OLLAMA_DATA_DIR/models/blobs"
MANIFEST_DIR="$OLLAMA_DATA_DIR/models/manifests/registry.ollama.ai/library/qwen3.5"
TEMP_EXTRACT_DIR="./ollama_deploy_temp"

echo ">>> 开始部署离线模型: $MODEL_NAME"

# 1. 检查包是否存在
if [ ! -f "$PACKAGE_FILE" ]; then
    echo "错误: 找不到安装包 $PACKAGE_FILE"
    exit 1
fi

# 2. 确保 Ollama 目录结构存在
# 如果 ollama 从未运行过,目录可能不存在。先尝试运行一下再停止,或者手动创建
if [ ! -d "$BLOB_DIR" ]; then
    echo "正在初始化 Ollama 目录结构..."
    mkdir -p "$BLOB_DIR"
    mkdir -p "$MANIFEST_DIR"
fi

# 3. 解压包
rm -rf "$TEMP_EXTRACT_DIR"
mkdir -p "$TEMP_EXTRACT_DIR"
tar -xzvf "$PACKAGE_FILE" -C "$TEMP_EXTRACT_DIR"
echo "包已解压"

# 4. 复制 Blob 文件
echo "正在复制权重文件..."
# 包里应该有 blobs/ 目录
if [ -d "$TEMP_EXTRACT_DIR/blobs" ]; then
    cp -r "$TEMP_EXTRACT_DIR/blobs/"* "$BLOB_DIR/"
    echo "权重文件复制完成"
else
    echo "错误: 包中未找到 blobs 目录"
    exit 1
fi

# 5. 重建模型注册 (关键步骤)
# 我们不能直接复制 manifests,因为路径可能因用户而异,最稳妥是用 ollama create 重新引用本地 blob
echo "正在注册模型..."

# 检查 Modelfile 中的 FROM 路径是否需要调整
# 在源机器上,FROM 指向的是绝对路径 /root/.ollama/models/blobs/...
# 在目标机器上,如果用户名不同或路径不同,直接 run create 可能会报错找不到文件
# 所以我们需要修改临时 Modelfile 中的 FROM 路径,使其指向刚才复制进去的文件名

TEMP_MODelfile="$TEMP_EXTRACT_DIR/Modelfile"
BLOB_FILENAME=$(ls "$BLOB_DIR" | grep -E "^sha256-[a-f0-9]{64}$" | head -n 1)

if [ -z "$BLOB_FILENAME" ]; then
    echo "错误: 目标目录中未找到复制过来的 blob 文件"
    exit 1
fi

# 构造新的 FROM 行,直接指向文件名 (ollama create 会自动在默认 blob 目录找)
# 或者更稳妥:修改 Modelfile 内容为相对路径或直接使用哈希引用
# Ollama create 支持 FROM <filename> 如果文件在当前目录,但这里文件在系统目录
# 最佳实践:修改 Modelfile 中的 FROM 为绝对路径 (目标机器的路径)

TARGET_BLOB_PATH="$BLOB_DIR/$BLOB_FILENAME"

# 备份原 Modelfile
cp "$TEMP_MODelfile" "$TEMP_MODelfile.bak"

# 替换 FROM 行
sed -i "s|^FROM .*|FROM $TARGET_BLOB_PATH|" "$TEMP_MODelfile"

echo "更新后的 Modelfile 内容预览:"
head -n 5 "$TEMP_MODelfile"

# 执行 create
# 注意:此时需要 ollama serve 正在运行
# 检查是否运行
if ! pgrep -x "ollama" > /dev/null; then
    echo "Ollama 服务未运行,正在后台启动..."
    ollama serve &
    sleep 3 # 等待启动
    STARTED_SERVICE=true
fi

# 创建模型
ollama create "$MODEL_NAME" -f "$TEMP_MODelfile"

if [ $? -eq 0 ]; then
    echo ">>> 模型注册成功!"
    ollama list | grep "$MODEL_NAME"
else
    echo ">>> 模型注册失败,请检查错误信息"
    exit 1
fi

# 如果是我们启动的服务,可以选择停止,或者保留
if [ "$STARTED_SERVICE" = true ]; then
    echo "提示: 脚本启动了 ollama 服务。如需停止,请运行 'pkill ollama' 或使用 systemctl"
fi

# 清理
rm -rf "$TEMP_EXTRACT_DIR"

echo ">>> 部署完成。你可以运行: ollama run $MODEL_NAME"

操作流程总结

  1. 在有网机器上:

    • 生成 Modelfile: ollama show qwen3.5:9b --modelfile > qwen3.5.9b.Modelfile
    • 运行 打包脚本。
    • 得到 ollama-qwen3.5-9b-offline-package.tar.gz。
    • 下载对应版本的 ollama-linux-amd64 二进制文件(或安装包)。
  2. 传输:

    • 将 .tar.gz 包和 ollama 二进制文件拷贝到离线服务器。
  3. 在离线服务器上:

    • 安装/放置 ollama 二进制文件到 /usr/bin/ollama (或其他路径)。
    • 运行 部署脚本。
    • 脚本会自动:
      1. 解压包。
      2. 将大文件放入 ~/.ollama/models/blobs。
      3. 修正 Modelfile 中的路径指向新位置。
      4. 调用 ollama create 重新注册模型。
  4. 验证:

    • ollama list
    • ollama run qwen3.5:9b "测试"

注意事项

  • 用户一致性:如果源机器是 root,目标机器也是 root,上述脚本默认路径 $HOME 即为 /root,完全适用。如果目标机器是非 root 用户,请确保该用户有权限读取 .ollama 目录,或者在运行部署脚本前 export HOME=/home/youruser。
  • 服务管理:如果离线服务器使用 systemctl 管理 ollama (systemctl start ollama),部署脚本中的 ollama serve & 可能会冲突。在这种情况下,请确保 systemctl start ollama 已执行,并注释掉脚本中自动启动服务的部分。
  • 显存/驱动:再次提醒,离线服务器必须安装好 NVIDIA 驱动,否则模型会回退到 CPU 模式,推理速度极慢。

更多推荐