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

如何禁用Heroku一次性Dyno对崩溃应用的自动重启(或实现优雅停机)

解决Heroku Scheduler调度one-off任务时的崩溃重启问题

我来帮你拆解下这个问题——其实你碰到的是Heroku对dyno类型和任务调度的一个常见认知偏差,咱们一步步来搞定它:

核心问题根源

Heroku的one-off dyno(比如用heroku run手动启动的)确实是一次性任务,跑完就停;但Heroku Scheduler本质上是帮你创建重复运行的worker dyno,而不是手动的one-off dyno。如果你的任务被识别为web dyno,或者进程退出不符合预期,Heroku就会判定为崩溃并尝试重启。

具体解决方案

1. 把任务部署为worker dyno,而非web dyno

Heroku对web dyno有特殊要求:它期望进程持续监听某个端口(默认5000),如果进程退出或者没有监听端口,就会直接标记为崩溃。这也是你哪怕跑个简单print脚本都会崩溃的原因——如果默认用了web dyno类型,Heroku在脚本结束后发现没有进程监听端口,就判定为异常。

解决方法:

  • 在项目根目录创建Procfile文件,内容指定为worker进程:
    worker: python your_script.py
    
  • 部署后,在Heroku Scheduler的任务配置里,选择worker作为dyno类型(不要选默认的web)。

2. 确保脚本以退出码0正常结束

不管是让脚本自然执行完毕,还是主动退出,都要保证最终的退出状态码是0(正常结束的标志):

  • 主动退出时用sys.exit(0),而不是不带参数的sys.exit()或者quit()(不带参数可能返回非0码)。
  • 本地测试时,运行脚本后执行echo $?(Linux/macOS)或echo %errorlevel%(Windows),确认返回值是0。

举个极简测试脚本:

print("测试任务完成")
import sys
sys.exit(0)

3. 手动验证worker任务的运行状态

配置好Procfile后,先手动运行worker任务验证:

heroku run worker

运行结束后,查看日志:

heroku logs --tail

如果日志里显示Exit status 0,说明任务正常结束,Heroku不会标记为崩溃,Scheduler调度时也会正常执行后停止。

4. 检查日志排查异常

如果还是出现崩溃,一定要看Heroku日志的详细信息:

  • 日志里会明确显示进程的退出码、是否有未捕获的异常、或者Heroku的健康检查报错。
  • 比如如果日志里出现Error R10 (Boot timeout) -> Web process failed to bind to $PORT within 60 seconds of launch,那说明你还是用了web dyno类型,赶紧切换成worker。

总结

你之前的操作失误大概率是用了web dyno类型来运行一次性任务,导致Heroku误判进程异常。只要把任务配置为worker dyno,确保脚本以退出码0正常结束,Scheduler调度的任务就会执行完毕后自动停止,不会触发崩溃重启。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 11:24:11