Linux Bash脚本检查Java进程异常:until语句错误咨询
你的until语句逻辑搞反啦,而且还有个潜在的语法坑,咱们一步步拆解:
核心逻辑错误
until的运行规则是:只要条件为假,就重复执行循环体;当条件为真时,立刻退出循环。
看你的代码:
until [ ` pgrep java ` ]; do echo Java still running... sleep 1 done
当Java进程正在运行时,pgrep java会返回一个或多个进程ID,此时[ 进程ID ]这个表达式的结果是真(非空字符串在test命令里会被判定为真)。这就导致until直接认为条件满足,跳过循环体,直接执行后面的echo Java is done...——这就是为什么你不管Java是否在运行,都只会看到这个输出。
反过来,如果Java进程已经结束,pgrep java没有输出,[ ]的结果是假,until才会执行循环体,但这时候你其实希望脚本退出,完全和你的预期背道而驰了。
额外的潜在问题
如果有多个Java进程在运行,pgrep java会输出多行PID,这时候[ pgrep java ]会变成[ pid1 pid2 ],这会触发test命令的语法错误,因为它没法处理多个参数。
修复方案
有两种更可靠的写法,推荐用第一种:
方案1:修正until的条件(检查退出状态)
直接利用pgrep的退出状态判断,而不是它的输出。pgrep找到进程时返回0(成功),没找到返回非0(失败)。我们用!取反,让until在进程存在时持续循环:
#!/bin/bash until ! pgrep java > /dev/null; do echo Java still running... sleep 1 done echo Java is done...
这里> /dev/null是为了屏蔽pgrep的输出,避免干扰脚本的正常打印内容。
方案2:改用while循环(更符合直觉)
如果你觉得until的逻辑容易搞混,换成while循环会更直观——只要进程存在,就持续打印提示:
#!/bin/bash while pgrep java > /dev/null; do echo Java still running... sleep 1 done echo Java is done...
这个逻辑更直接:当pgrep java返回成功(进程存在),就执行循环体;进程结束后,pgrep返回失败,退出循环,打印完成信息。
内容的提问来源于stack exchange,提问作者Mark Estrada

