大模型之ollama离线模型迁移
·
根据你提供的 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"
使用方法:
- 保存为
package_ollama_model.sh。 - 赋予执行权限:
chmod +x package_ollama_model.sh。 - 运行:
./package_ollama_model.sh。 - 生成的
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"
操作流程总结
-
在有网机器上:
- 生成 Modelfile:
ollama show qwen3.5:9b --modelfile > qwen3.5.9b.Modelfile - 运行 打包脚本。
- 得到
ollama-qwen3.5-9b-offline-package.tar.gz。 - 下载对应版本的
ollama-linux-amd64二进制文件(或安装包)。
- 生成 Modelfile:
-
传输:
- 将
.tar.gz包和ollama二进制文件拷贝到离线服务器。
- 将
-
在离线服务器上:
- 安装/放置
ollama二进制文件到/usr/bin/ollama(或其他路径)。 - 运行 部署脚本。
- 脚本会自动:
- 解压包。
- 将大文件放入
~/.ollama/models/blobs。 - 修正
Modelfile中的路径指向新位置。 - 调用
ollama create重新注册模型。
- 安装/放置
-
验证:
ollama listollama 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 模式,推理速度极慢。
更多推荐

所有评论(0)