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

Ubuntu 20.04 cron执行shell脚本ps进程计数与手动执行结果不符

cron执行脚本时ps进程计数与手动执行不一致问题排查

核心原因

差异本质是ps -efa | grep -v grep | grep import -c的匹配逻辑存在缺陷:该命令会对全量进程的完整命令行做模糊匹配,只要命令行中包含import字符串就会被统计,grep -v grep仅能排除grep命令自身的进程,无法排除其他路径、参数中带import的关联进程;而cron调度的执行环境和交互式手动执行的环境中,这类附带的带import关键字的进程数量不一致,最终导致计数差。

两种场景下的计数构成

  • 手动执行脚本场景
    交互式终端下执行脚本时,除目标Java进程外,几乎没有其他命令行带import的进程:
    • Java进程存活时:仅匹配到1个目标Java服务进程,val=1
    • Java进程停止时:无匹配进程,val=0
      和观测到的现象完全一致。
  • cron自动调度场景
    cron执行定时任务时,会生成一整条任务调度链路的进程,这些进程的命令行中都包含脚本路径/software/deployment/service/import2/restart_import.sh,路径本身带有import字符串,会被grep命中,这部分进程固定占3个匹配项:
    1. cron服务fork出的执行定时任务的shell父进程
    2. 执行ps命令、管道命令时生成的子shell进程
    3. 脚本执行过程中产生的其他关联临时子进程
      在此基础上叠加目标Java进程的计数:
    • Java进程存活时:3个固定关联进程 + 1个Java进程 = 4,val=4
    • Java进程停止时:仅剩余3个固定关联进程,val=3

修复方案

原逻辑写死判断val -eq 4可靠性极差,只要cron执行链路的进程数随系统配置、版本变化发生变动,判断就会失效,建议替换为精确匹配目标Java进程特征的判断逻辑,两种常用实现如下:

  1. 用pgrep精确匹配进程特征(推荐)
    替换原有的进程计数行:
# 仅匹配启动了指定war包的Java进程,自动排除脚本、cron链路进程干扰
val=$(pgrep -f "java.*import-web-1.0-SNAPSHOT.war" -c)

同时将判断逻辑修改为:

if [[ ${val} -ge 1 ]]; then
  echo "Import Up" >> /tmp/output.log
else
  # 原有拉起逻辑保持不变
fi

该写法在手动执行、cron执行环境下计数一致,Java进程存活时val=1,停止时val=0,不会出现误判。
2. 优化原有grep匹配规则
如果不想依赖pgrep,可以收窄grep的匹配范围,同时排除脚本自身进程:

val=$(ps -efa | grep -v grep | grep -v restart_import.sh | grep "java.*import-web-1.0-SNAPSHOT.war" -c)

该写法通过额外的grep -v restart_import.sh排除脚本自身进程,同时将匹配关键字从宽泛的import替换为Java进程独有的war包名称,避免匹配到无关进程。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 03:51:21