You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让指定脚本在Packer构建成功或失败时均执行?

解决方案:确保scriptC.sh始终执行(无论Packer构建成败)

要实现不管前面的脚本(scriptA.sh、scriptB.sh)是否执行失败,scriptC.sh都能运行,你有几个可靠的方法,下面按推荐程度排序:

方法1:使用Packer的cleanup_provisioners(最推荐)

Packer原生支持清理阶段的provisioner,这些provisioner会在构建结束时自动执行——不管主provisioner是成功还是失败(刚好匹配你当前使用的packer build -on-error=cleanup参数)。

在你的template.json里,单独配置cleanup_provisioners字段,把scriptC.sh放在这里:

{
  "builders": [
    // 你的builder配置
  ],
  "provisioners": [
    {
      "type": "shell",
      "script": "scriptA.sh"
    },
    {
      "type": "shell",
      "script": "scriptB.sh"
    }
  ],
  "cleanup_provisioners": [
    {
      "type": "shell",
      "script": "scriptC.sh"
    }
  ]
}

这个方法完全符合Packer的设计规范,逻辑清晰,不需要修改脚本内容,也不会掩盖前面脚本的错误状态,是最优解。

方法2:用Shell的trap捕获退出信号

如果不想拆分provisioner,可以把所有逻辑放到一个inline shell provisioner里,用trap命令注册EXIT信号的处理函数,确保scriptC.sh在shell会话结束时(不管正常退出还是异常退出)都会执行:

{
  "provisioners": [
    {
      "type": "shell",
      "inline": [
        // 注册退出时执行scriptC.sh
        "trap './scriptC.sh' EXIT",
        // 执行你的主脚本
        "./scriptA.sh",
        "./scriptB.sh"
      ]
    }
  ]
}

注意替换脚本路径为实际相对/绝对路径即可,这个方法适合脚本之间有依赖、需要放在同一个会话中的场景。

方法3:强制执行脚本(简单但不推荐)

如果你只是想让scriptC.sh无条件执行,可以直接用Shell的分号分隔命令,忽略前面命令的错误状态:

{
  "provisioners": [
    {
      "type": "shell",
      "inline": [
        "./scriptA.sh; ./scriptB.sh; ./scriptC.sh"
      ]
    }
  ]
}

⚠️ 注意:这个方法的问题是,Packer会把整个inline命令的退出码设为最后一个命令(scriptC.sh)的退出码,这会掩盖scriptA.sh或scriptB.sh的错误——即使它们执行失败,Packer也会认为provisioner成功。所以除非你不在意前面脚本的错误状态,否则不建议用这个方法。


内容的提问来源于stack exchange,提问作者bigbaeng

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 09:54:29