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

nohup启动的Python脚本在time.sleep()处挂起的原因排查

排查Python脚本在time.sleep()处挂起的可能原因

根据你描述的情况——脚本运行两天后卡在time.sleep(60),日志最后停留在DEBUG Starting Sleep,且进程未终止,已经排除内存泄漏、I/O挂起和连接超时,下面是几个可能的原因及排查方向:

1. 系统信号导致进程被暂停

如果系统向进程发送了SIGSTOP信号(比如误操作执行kill -STOP <pid>,或是某些监控工具的自动行为),进程会进入暂停状态,既不会继续执行代码,也不会终止,看起来就像是"挂起"了。

  • 排查方法:
    • 用ps -o stat <pid>查看进程状态,若状态为T(stopped),说明进程确实被暂停。
    • 尝试发送SIGCONT信号(kill -CONT <pid>),观察进程是否恢复运行。
    • 检查系统日志(如/var/log/syslog或/var/log/messages),排查是否有相关信号的发送记录。

2. 系统时钟回拨导致sleep时长异常

Python的time.sleep()依赖系统时钟计算等待时长,如果系统时钟被手动回拨、或是NTP服务同步时向后调整了大量时间,sleep的实际等待时间会被异常延长。比如调用time.sleep(60)后,时钟回拨了2天,进程会实际等待2天+60秒,看起来就像是挂起。

  • 排查方法:
    • 查看系统时钟同步记录(如timedatectl status查看NTP状态,或检查/var/log/ntp.log),确认是否有大规模时钟回拨操作。
    • 在脚本中添加sleep前后的时间戳日志,方便后续定位:
      logging.debug(f"Starting sleep at {datetime.datetime.now()}")
      time.sleep(60)
      logging.debug(f"Finished sleep at {datetime.datetime.now()}")
      

3. 未捕获的BaseException导致执行中断

你的脚本中except Exception仅能捕获继承自Exception的异常,但KeyboardInterrupt、SystemExit等属于BaseException层级,不会被捕获。如果进程收到SIGINT等信号,可能在time.sleep()处触发未捕获的异常,导致进程停止执行但未终止(这种情况多与第三方库修改信号处理逻辑有关)。

  • 排查方法:
    • 扩大异常捕获范围,改为捕获BaseException,看是否能捕获到相关异常:
      try:
          logging.debug("Started loop.")
          do_some_stuff()
          logging.debug("Stuff was done.")
      except BaseException as e:
          logging.exception("Unhandled exception occurred")
      
    • 检查do_some_stuff()中是否有修改信号处理的代码(如signal.signal()调用)。

4. 系统资源限制触发隐性限制

虽然你排查了内存泄漏,但仍可能存在其他资源限制:

  • 文件描述符耗尽:如果do_some_stuff()中频繁打开文件却未关闭,可能导致进程打开的文件描述符达到系统上限(ulimit -n),虽然sleep本身不依赖文件描述符,但可能影响后续日志写入,让你误以为卡在sleep阶段。

  • CPU时间限制:若系统设置了进程CPU时间上限(ulimit -t),当进程累计CPU时间达标时,系统会发送SIGXCPU信号,若进程忽略该信号,可能进入异常暂停状态。

  • 排查方法:

    • 用ulimit -a查看当前资源限制,确认是否有严格的阈值。
    • 用lsof -p <pid>查看进程打开的文件描述符数量,判断是否接近上限。
    • 检查系统日志中是否有资源限制相关的警告信息。

5. 第三方库的隐性异常

如果do_some_stuff()依赖第三方库,某些库可能存在线程死锁、资源未正确释放的问题——虽然表面上do_some_stuff()执行完成,但库内部的异常状态可能影响后续的time.sleep()正常执行。

  • 排查方法:
    • 逐步简化do_some_stuff()的逻辑,注释掉部分功能后运行脚本,定位是否由某段代码引发问题。
    • 检查第三方库的版本,查看是否有已知的类似bug记录。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 04:14:17