golang-migrate如何在DB版本高于本地脚本时跳过迁移执行?
问题根因
- 变量赋值异常的核心原因是golang-migrate的版本号输出和业务日志分别输出到不同的IO流,命令替换默认仅捕获标准输出(stdout),导致你拿到的是日志内容而非版本号
- 你之前用
wc -l统计迁移脚本数量作为最高版本的逻辑存在缺陷:迁移版本号允许不连续,统计数量不等于实际最高版本号
解决方案1:正确捕获迁移版本,手动判断执行
修正后的脚本如下:
#!/bin/bash set -euo pipefail # 正确获取本地迁移脚本的最高版本(兼容版本号不连续场景) MAX_LOCAL_VERSION=$(ls /app/config/db/migrations/*.up.sql | sed 's/.*\/\([0-9]*\)_.*/\1/' | sort -n | tail -n 1) echo "MAX_LOCAL_VERSION: $MAX_LOCAL_VERSION" # 合并标准输出和错误流,过滤出纯数字的当前数据库版本 CURRENT_VERSION=$(/app/migrate -source=file:///app/config/db/migrations/ -database=<connection_string> version 2>&1 | grep -E '^[0-9]+$') # 处理无迁移记录的场景,默认版本为0 CURRENT_VERSION=${CURRENT_VERSION:-0} echo "CURRENT_VERSION: $CURRENT_VERSION" if [ "$MAX_LOCAL_VERSION" -gt "$CURRENT_VERSION" ]; then /app/migrate \ -source=file:///app/config/db/migrations/ \ -database=<connection_string> \ up fi /app/my-app
逻辑说明:
- 用sed提取所有迁移脚本前缀的版本号,排序后取最大值作为本地最高版本,避免跳号场景下的逻辑错误
- 执行version命令时添加
2>&1合并标准输出和错误流,再通过grep过滤纯数字行,确保拿到的是数值类型的版本号 - 新增无迁移记录时的默认值处理,避免空值判断报错
解决方案2:直接捕获迁移错误,忽略版本过高的场景
如果你不想手动处理版本号逻辑,可以直接对migrate up的错误做过滤,只有非"缺失迁移脚本"的错误才中断流程:
#!/bin/bash set -euo pipefail # 执行迁移,输出日志同时保存到临时文件 /app/migrate -source=file:///app/config/db/migrations/ -database=<connection_string> up 2>&1 | tee /tmp/migrate_log EXIT_CODE=${PIPESTATUS[0]} if [ $EXIT_CODE -ne 0 ]; then # 检查错误是否为数据库版本过高导致的迁移脚本缺失 if grep -q "no migration found for version" /tmp/migrate_log; then echo "当前数据库版本高于本地迁移脚本最高版本,跳过迁移步骤" else echo "迁移执行失败,错误日志如下:" cat /tmp/migrate_log exit $EXIT_CODE fi fi /app/my-app
这个方案不需要依赖版本号解析逻辑,兼容性更强。
内容的提问来源于stack exchange,提问作者PersonThatCodes
相关产品推荐
相关产品推荐

