Bash脚本偶发‘Integer expression expected’错误排查求助
排查Bash脚本内存阈值判断的错误问题
你这个脚本的核心问题出在提取内存使用率的逻辑不够严谨,当系统中存在多个带"worker"关键字的进程时,你的命令会返回多行结果,导致memory_usage变量里包含多个数值,最终在整数比较时触发错误。
先来看你的原始脚本:
#!/bin/bash memory_usage=`ps -eo size,pid,user,command --sort -size | awk '{ hr=$1/1024 ; printf("%13.2f Mb ",hr) } { for ( x=4 ; x<=NF ; x++ ) { printf("%s ",$x) } print "" }' |cut -d "" -f2 | cut -d "-" -f1 | grep worker | cut -d M -f 1` echo "Memory usage is ${memory_usage}" int_memory_usage=${memory_usage%.*} echo "Int Memory usage is ${int_memory_usage}" if [ "${int_memory_usage}" -gt 16000 ]; then echo "Memory for worker ${memory_usage} above threshold" pkill -f "worker" fi
错误原因分析
从报错信息Memory usage is 4261.01 0.34可以看出,memory_usage变量里有两个数值,这说明你的ps+grep worker命令匹配到了多个进程——比如一个真正的worker进程,还有可能包含脚本自身的grep worker进程,或者其他带worker关键字的进程。
当变量里有多个值时,int_memory_usage=${memory_usage%.*}只会去掉最后一个值的小数部分,导致int_memory_usage变成4261.01 0,后续的[ "${int_memory_usage}" -gt 16000 ]自然无法处理非单一整数的情况,抛出integer expression expected错误。
另外,你的cut -d "" -f2是无效的——cut的分隔符不能是空字符串,这部分其实是多余的,反而会干扰结果提取。
修复方案
我们需要优化进程筛选和内存提取逻辑,确保只获取目标worker进程的内存值,并且处理多进程场景:
方案1:只监控内存占用最高的worker进程
如果你的需求是只要有worker进程内存超过阈值就杀掉所有worker,那么可以只提取内存最高的那个worker进程的数值:
#!/bin/bash # 提取内存最高的worker进程的内存值(只取第一行,排除awk/grep自身进程) memory_usage=$(ps -eo size,pid,user,command --sort -size | awk '/worker/ && !/awk/ && !/grep/ { hr=$1/1024; printf("%.2f", hr); exit }') # 处理没有worker进程的边界情况 if [ -z "$memory_usage" ]; then echo "No worker processes found." exit 0 fi echo "Memory usage is ${memory_usage}" # 用awk转整数比字符串截取更可靠 int_memory_usage=$(awk -v mem="$memory_usage" 'BEGIN{print int(mem)}') echo "Int Memory usage is ${int_memory_usage}" if [ "$int_memory_usage" -gt 16000 ]; then echo "Memory for worker ${memory_usage} above threshold" pkill -f "worker" fi
方案2:逐个检查每个worker进程的内存
如果需要精准杀掉单个超阈值的进程(而非一刀切),可以遍历所有worker进程逐个判断:
#!/bin/bash # 遍历所有worker进程,获取PID和内存值,逐个判断并处理 ps -eo size,pid,command --sort -size | awk '/worker/ && !/awk/ && !/grep/ { hr=$1/1024 mem_int=int(hr) printf("Worker PID %d: %.2f Mb\n", $2, hr) if (mem_int > 16000) { printf("Killing worker PID %d (memory exceeds threshold)\n", $2) system("kill " $2) } }'
关键优化点
- 用
awk直接过滤进程,排除awk和grep自身的进程,避免误匹配 - 用
awk的int()函数转换整数,比字符串截取更可靠,不会受多值干扰 - 增加了无worker进程的边界处理,避免空值导致的错误
- 方案2可以精准控制单个进程,减少不必要的进程终止
内容的提问来源于stack exchange,提问作者tusharmakkar08
相关产品推荐
相关产品推荐

