DEBUG.WIKI
V.PS:让项目靠近用户,亚太、欧洲、北美 KVM VPS
IPPeak:从目标地区访问网页,住宅代理、SEO 监测、广告验证
ZgoCloud:多地区部署,按需选节点;日本、美国、香港、德国

GitHub Actions 取消 Terraform plan 后状态仍锁定:检查信号链

对照取消入口、CLI退出与后端锁状态,检查wrapper输出依赖,确认失效锁归属后再恢复。

取消正在运行的 terraform plan 后,工作流显示 canceled,下一次运行却报状态锁已被占用。先保留锁信息和取消前后的日志:Actions 停止任务、Terraform 退出、后端释放锁是三个需要分别确认的状态。

取消信号先送到步骤入口

GitHub Runner 对需要取消的步骤,先向入口进程发送 SIGINT;7.5 秒内未退出,再发 SIGTERM,等待 2.5 秒后仍未退出则终止进程树。这些时间不同于服务器侧五分钟的取消超时,不能理解成 Terraform 一定有五分钟保存状态。

run 步骤外面可能还有 shell;使用 setup-terraform 时,还可能经过 Node wrapper。信号到达外层进程,不代表里面的 Terraform 已接收并完成退出。

按 setup-terraform 3.1.2 和 4.0.1 的 wrapper 源码,它调用 @actions/exec 启动 CLI,并捕获输出;wrapper 文件本身没有显式注册取消信号转发。实际结果还取决于 runner、shell、子进程和后端,不能只凭这个静态检查认定每次残留锁都由 wrapper 造成。

查看日志是否出现 Interrupt received 和正常停止提示。如果又出现 Two interrupts received. Exiting immediately,需要进一步核对状态保存结果;看到第一次 graceful shutdown 提示,仍不能确认整个退出已经完成。

改调用方式前,检查是否依赖 wrapper 输出

保留当前 action 与 CLI 版本、shell、完整调用命令和工作目录。项目确实不依赖 wrapper 时,可以在原 setup-terraform 步骤的 with 中评估这一项:

terraform_wrapper: false

这是输入片段,不是完整工作流。保留原来的版本、认证和审批设置;关闭 wrapper 后,其提供的 stdout、stderr、exitcode 步骤输出也会失去原有来源,下游评论或条件判断需要一起检查。

去掉这一层 wrapper 仍不能保证信号通过剩余 shell 正确传播,更不能延长强制终止时间。先在独立测试后端和不影响正式资源的运行中检查取消过程,观察 CLI 退出、锁释放和状态一致性,再决定是否用于生产。不要把取消逻辑的试验放进真实 apply。

先确认持锁操作已经停止

对照报错中的 Lock ID、持有者、操作时间,以及准确的 backend、workspace 和状态路径。确认没有仍运行的本地进程、远程 Terraform 任务或其他 runner 正在操作同一状态;页面上的 canceled 不能代替这些检查。

只有确认是自己的失效锁、自动解锁失败且持锁操作已经停止,并得到相应操作授权,才考虑在原配置目录执行:

terraform force-unlock LOCK_ID

LOCK_ID 必须使用已核对的实际值。保留交互确认,不把该命令放进无条件的取消清理步骤,也不要删除 .tflock 或设置 -lock=false 绕过其他操作的锁。

解锁不会回滚基础设施,也不会补写遗漏的状态。尤其取消的是 apply 时,后续仍要对照状态与真实资源;先保存恢复所需记录,再按后端和项目的恢复流程处理。复查没有并发写入、状态与资源一致后,才能恢复正常运行。不要把“下一次命令能启动”当成完整恢复。