#!/bin/bash # 参数检查 if [ $# -ne 1 ]; then echo "用法:$0 <进程名关键词>" exit 1 fi PROCESS_NAME="$1" LOG_FILE="group_mem.log" # 主循环 while true; do TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S') LOG_ENTRY="[$TIMESTAMP]" # 动态获取所有匹配进程的PID PIDS=$(pgrep -f "$PROCESS_NAME" | tr '\n' ' ') if [ -z "$PIDS" ]; then echo "[$TIMESTAMP] 未找到匹配进程" >> $LOG_FILE sleep 10 continue fi # 遍历每个PID for PID in $PIDS; do MEM_KB=$(grep VmRSS /proc/$PID/status 2>/dev/null | awk '{print $2}') MEM_MB=$(echo "scale=2; $MEM_KB / 1024" | bc 2>/dev/null || echo "N/A") LOG_ENTRY+=" PID${PID}:${MEM_MB}MB;" done echo "$LOG_ENTRY" >> $LOG_FILE sleep 10 done上述脚本增添每10s的进程所有内存求和记录
时间: 2025-07-07 09:46:35 浏览: 6
<think>好的,我需要帮助用户修改他们的Bash脚本,以添加每10秒记录所有进程内存总和的功能。让我先仔细看看用户提供的脚本。
首先,用户当前的脚本会无限循环,每隔10秒检查一次指定进程名的所有进程,记录每个进程的内存使用情况到日志文件中。现在用户希望增加一个功能:除了记录每个进程的内存使用外,还要记录所有进程的内存总和,同样每10秒一次。
我需要分析现有脚本的结构,找到在哪里添加求和的功能。主循环中,脚本遍历每个PID,计算单个进程的内存使用,并累加到LOG_ENTRY变量中。此时,可以在遍历每个PID的同时,将这些内存值累加到一个总和中。不过需要注意的是,内存值的单位是MB,且可能带有小数。因此,在累加时需要处理浮点数运算,这在Bash中可能有些挑战。
另外,用户可能希望总和以MB为单位,保留两位小数。现有的单个进程内存计算已经使用了`bc`命令来处理小数除法,可能可以利用同样的方法来处理总和。但是,如果某个进程的内存值为"N/A",如何处理?可能需要跳过这些无效值,或者在日志中明确标记总和包含无效数据。
接下来,考虑如何在日志条目中添加总和的信息。当前的LOG_ENTRY变量是一个字符串,每次循环追加每个PID的内存信息。可以在遍历所有PID并计算总和后,将总和添加到LOG_ENTRY中,例如在末尾添加类似“总计:XX.XXMB”的部分。
现在,具体步骤可能是:
1. 初始化一个变量来保存内存总和,比如TOTAL_MEM=0。
2. 在遍历每个PID的循环中,检查MEM_MB是否为数字,如果是,则累加到TOTAL_MEM中;如果为"N/A",可能需要记录错误或忽略。
3. 使用`bc`命令进行浮点数累加,注意处理可能的错误。
4. 遍历完成后,将总和格式化为两位小数,并追加到LOG_ENTRY中。
5. 修改日志条目格式,确保总和被正确记录。
另外需要考虑的是,当所有进程的内存值都是"N/A"时,总和应该如何处理?可能需要将总和也标记为"N/A",或者在日志中说明这种情况。此外,如果部分进程返回有效值,部分无效,可能只累加有效部分,或者在日志中注明部分数据无效。
例如,在遍历每个PID时:
- 如果MEM_MB是数字,则TOTAL_MEM=$(echo "$TOTAL_MEM + $MEM_MB" | bc)
- 否则,可能设置一个标志,表示存在无效数据,最终总和显示为"N/A"。
或者,选择忽略无效数据,只累加有效值,即使有部分无效数据,总和仍然显示为有效数值的总和。这取决于用户的需求,但通常在监控脚本中,可能希望尽可能记录有效数据,并在存在问题时进行标记。
因此,可能需要引入一个变量,如HAS_INVALID=0,当遇到MEM_MB为"N/A"时,HAS_INVALID=1。在计算总和后,如果HAS_INVALID为1,则在总和后面添加“(包含无效数据)”或直接将总和显示为"N/A"。
不过,根据用户提供的原脚本,当无法获取内存时,MEM_MB被设置为"N/A"。因此,在计算总和时,如果任何进程的MEM_MB是"N/A",可能需要将总和也标记为"N/A",或者在日志中明确说明。例如,在日志条目中添加“总计:N/A”或类似信息。
不过,用户可能更希望即使有部分进程无法获取内存,仍然计算其他有效进程的总和,并在日志中记录总和的同时注明有部分数据无效。或者,如果所有进程都无法获取内存,则总和为0或N/A。
需要明确如何处理这些情况,但根据原脚本的逻辑,当无法获取内存时,MEM_MB设为"N/A",但在日志中仍然记录该PID的内存为N/A。因此,可能希望在总和计算中,跳过这些N/A的值,只累加有效的数值,并在总和后面注明是否有无效数据。
例如:
- 初始化TOTAL_MEM=0和INVALID_COUNT=0
- 对于每个PID的MEM_MB:
- 如果是数字,则TOTAL_MEM加上该值
- 否则,INVALID_COUNT加1
- 遍历完成后,如果INVALID_COUNT > 0,则在总和后添加注释,如“(部分数据无效)”
- 如果所有MEM_MB都是N/A,则总和显示为N/A
不过,这样的处理可能稍微复杂,需要更多的代码逻辑。或者,可以简单地将所有有效的MEM_MB相加,忽略无效的,并在总和记录时,如果有无效数据,则标记总和为N/A,或者仍然显示总和但加注释。
根据用户的需求,可能更倾向于在总和计算中只考虑有效值,并记录总和。如果所有值都无效,则总和为0或N/A。
现在,回到脚本修改:
在现有循环中,当处理每个PID时,得到MEM_MB。需要检查这个值是否是数字,如果是,则累加到TOTAL_MEM;否则,忽略或者统计无效数。
例如:
在for循环之前,初始化变量:
TOTAL_MEM=0
INVALID_FLAG=0
然后在循环内部:
if [[ $MEM_MB =~ ^[0-9]+(\.[0-9]+)?$ ]]; then
TOTAL_MEM=$(echo "$TOTAL_MEM + $MEM_MB" | bc)
else
INVALID_FLAG=1
fi
这样,如果MEM_MB是数字,则累加,否则标记无效。
循环结束后,判断INVALID_FLAG是否为1,如果是,则在总和后面添加“(含无效数据)”,或者将总和显示为N/A。或者,不管是否有无效数据,都显示总和,但如果有无效数据,则在日志中注明。
或者,如果存在任何无效数据,总和显示为N/A,否则显示总和。
但用户可能更希望即使有部分无效数据,仍然显示有效部分的总和,并注明部分无效。例如:
总计:XX.XXMB(部分数据无效)
或者,如果所有数据都无效,则总计为N/A。
这需要额外的逻辑处理。但为了简化,可能暂时先处理所有有效的情况,假设所有MEM_MB都能正确获取,然后处理可能的错误情况。
不过在原脚本中,当无法获取VmRSS时,MEM_MB设为"N/A"。例如,如果进程在获取状态时已经终止,可能导致/proc/$PID/status不存在,此时grep命令失败,MEM_KB为空,导致MEM_MB被计算为N/A。
因此,在计算总和时,需要处理这些情况。
可能的修改步骤:
1. 在for循环之前,初始化TOTAL_MEM=0和INVALID=0。
2. 在for循环内部,处理每个PID的MEM_MB:
if [ "$MEM_MB" != "N/A" ]; then
TOTAL_MEM=$(echo "$TOTAL_MEM + $MEM_MB" | bc)
else
INVALID=1
fi
3. 在for循环结束后,构建LOG_ENTRY的总和部分:
if [ $INVALID -eq 0 ]; then
SUM=$(printf "%.2f" $TOTAL_MEM)
LOG_ENTRY+=" 总计:${SUM}MB"
else
LOG_ENTRY+=" 总计:N/A(存在无效进程数据)"
fi
不过,这里需要注意,当有部分进程数据无效时,是否仍然显示有效部分的总和。例如,如果有三个进程,其中两个有效,一个无效,总和是那两个的有效总和,但标记存在无效数据。
或者,如果有任何无效数据,总和标记为N/A。这取决于用户的需求。例如,如果用户希望总和必须是所有进程的有效数据之和,否则视为无效,那么当存在任何无效数据时,总和为N/A。
或者,即使有部分无效,总和仍然计算有效部分,并标记存在无效数据。
这需要根据实际情况决定。例如,在监控中,可能希望即使部分数据无效,仍然记录有效部分的总和,同时注明问题,这样用户知道总和可能不完整。
因此,修改后的逻辑可能是:
- 遍历所有PID,累加有效的MEM_MB到TOTAL_MEM,并统计无效的数量。
- 如果无效数量大于0,则在总计后添加备注。
- 如果所有PID都无效,则总计为N/A。
例如:
在循环前:
TOTAL_MEM=0
INVALID_COUNT=0
循环中:
if [[ "$MEM_MB" =~ ^[0-9.]+$ ]]; then
TOTAL_MEM=$(echo "$TOTAL_MEM + $MEM_MB" | bc)
else
INVALID_COUNT=$((INVALID_COUNT + 1))
fi
循环结束后:
if [ $INVALID_COUNT -eq 0 ]; then
SUM=$(printf "%.2f" $TOTAL_MEM)
LOG_ENTRY+=" 总计:${SUM}MB"
elif [ $INVALID_COUNT -eq ${#PIDS[@]} ]; then # 所有都无效
LOG_ENTRY+=" 总计:N/A"
else
SUM=$(printf "%.2f" $TOTAL_MEM)
LOG_ENTRY+=" 总计:${SUM}MB(${INVALID_COUNT}个进程数据无效)"
fi
不过,在Bash中,数组的个数可以用${#PIDS[@]}获取,但原脚本中PIDS是通过空格分隔的字符串,而不是数组。因此,需要先将PIDS转换为数组:
PIDS_ARR=($PIDS)
NUM_PIDS=${#PIDS_ARR[@]}
然后在判断是否所有都无效时:
if [ $INVALID_COUNT -eq $NUM_PIDS ]; then
...
fi
但原脚本中,PIDS变量是通过pgrep获取的PID列表,使用tr转换换行为空格,所以PIDS是一个由空格分隔的字符串。在for循环中,使用for PID in $PIDS; do,这会按空格分割成多个PID。因此,可以将PIDS转换为数组:
PIDS_ARR=($PIDS)
NUM_PIDS=${#PIDS_ARR[@]}
这样,在循环结束后,可以判断INVALID_COUNT是否等于NUM_PIDS。
综上,修改后的脚本可能如下:
在for循环之前:
TOTAL_MEM=0
INVALID_COUNT=0
PIDS_ARR=($PIDS) # 将空格分隔的字符串转换为数组
NUM_PIDS=${#PIDS_ARR[@]}
然后进入for循环:
for PID in $PIDS; do
MEM_KB=$(grep VmRSS /proc/$PID/status 2>/dev/null | awk '{print $2}')
MEM_MB=$(echo "scale=2; $MEM_KB / 1024" | bc 2>/dev/null || echo "N/A")
LOG_ENTRY+=" PID${PID}:${MEM_MB}MB;"
# 计算总和
if [[ "$MEM_MB" =~ ^[0-9.]+$ ]]; then
TOTAL_MEM=$(echo "$TOTAL_MEM + $MEM_MB" | bc)
else
INVALID_COUNT=$((INVALID_COUNT + 1))
fi
done
循环结束后处理总和:
if [ $NUM_PIDS -eq 0 ]; then
# 这里应该不会发生,因为前面已经处理了PIDS为空的情况
SUM_INFO=""
elif [ $INVALID_COUNT -eq $NUM_PIDS ]; then
SUM_INFO=" 总计:N/A(所有进程数据无效)"
elif [ $INVALID_COUNT -gt 0 ]; then
SUM=$(printf "%.2f" $TOTAL_MEM)
SUM_INFO=" 总计:${SUM}MB(${INVALID_COUNT}/${NUM_PIDS}个进程数据无效)"
else
SUM=$(printf "%.2f" $TOTAL_MEM)
SUM_INFO=" 总计:${SUM}MB"
fi
LOG_ENTRY+="$SUM_INFO"
不过,需要注意的是,当PIDS为空时,脚本已经处理了这种情况,直接continue,不会进入for循环。因此,在循环后的处理中,不需要考虑PIDS为空的情况。
另外,printf "%.2f" 在Bash中可能需要使用外部命令,比如使用bc来处理格式化。例如:
SUM=$(echo "scale=2; $TOTAL_MEM/1" | bc)
这样可以确保SUM有两位小数。例如,如果TOTAL_MEM是12.3,则scale=2会显示12.30,但除以1可能去掉后面的零,可能需要用更复杂的格式化方法。或者,使用printf来格式化:
SUM=$(printf "%.2f" $(echo "$TOTAL_MEM" | bc -l))
但需要确保TOTAL_MEM是一个有效的数值。否则,当TOTAL_MEM为空或非数值时,会导致错误。因此,在设置SUM之前,可能需要检查TOTAL_MEM是否是有效的数值。
例如,在计算SUM时:
if [[ $(echo "$TOTAL_MEM" | bc -l) =~ ^[0-9.]+$ ]]; then
SUM=$(printf "%.2f" $(echo "$TOTAL_MEM" | bc -l))
else
SUM="N/A"
fi
但这样会增加复杂度。可能简化处理,假设只要INVALID_COUNT小于NUM_PIDS,TOTAL_MEM就是有效的数值,可以正确格式化。
综上,修改后的脚本大致如下:
在for循环中,累加有效的MEM_MB到TOTAL_MEM,并统计无效数量。
循环结束后,根据无效数量构建SUM_INFO字符串,并追加到LOG_ENTRY中。
另外,需要注意bc的安装和可用性,因为有些系统可能默认不安装bc,或者路径问题。但原脚本已经使用了bc,所以假设用户环境中已经安装。
现在,将上述思路转化为具体的脚本修改:
用户原脚本的for循环部分:
for PID in $PIDS; do
MEM_KB=$(grep VmRSS /proc/$PID/status 2>/dev/null | awk '{print $2}')
MEM_MB=$(echo "scale=2; $MEM_KB / 1024" | bc 2>/dev/null || echo "N/A")
LOG_ENTRY+=" PID${PID}:${MEM_MB}MB;"
done
需要添加总和计算,修改后:
TOTAL_MEM=0
INVALID_COUNT=0
PIDS_ARR=($PIDS)
NUM_PIDS=${#PIDS_ARR[@]}
for PID in $PIDS; do
MEM_KB=$(grep VmRSS /proc/$PID/status 2>/dev/null | awk '{print $2}')
MEM_MB=$(echo "scale=2; $MEM_KB / 1024" | bc 2>/dev/null || echo "N/A")
LOG_ENTRY+=" PID${PID}:${MEM_MB}MB;"
# 统计总和
if [[ "$MEM_MB" =~ ^[0-9.]+$ ]]; then
TOTAL_MEM=$(echo "$TOTAL_MEM + $MEM_MB" | bc -l 2>/dev/null)
else
INVALID_COUNT=$((INVALID_COUNT + 1))
fi
done
# 处理总计
if [ $NUM_PIDS -gt 0 ]; then
if [ $INVALID_COUNT -eq $NUM_PIDS ]; then
SUM_INFO=" 总计:N/A(所有进程数据无效)"
elif [ $INVALID_COUNT -gt 0 ]; then
SUM=$(echo "scale=2; $TOTAL_MEM / 1" | bc -l 2>/dev/null)
if [ -z "$SUM" ]; then
SUM_INFO=" 总计:N/A(部分无效)"
else
SUM_INFO=" 总计:${SUM}MB(${INVALID_COUNT}/${NUM_PIDS}无效)"
fi
else
SUM=$(echo "scale=2; $TOTAL_MEM / 1" | bc -l 2>/dev/null)
SUM_INFO=" 总计:${SUM}MB"
fi
LOG_ENTRY+="$SUM_INFO"
fi
这样,在日志条目中会添加总计信息,并根据是否存在无效数据添加相应的备注。
现在,测试一些情况:
情况1:所有进程的MEM_MB有效:
例如,两个进程,分别MEM_MB为10.50和20.30,TOTAL_MEM=30.80,SUM显示为30.80MB。
情况2:其中一个进程无效:
例如,三个进程,两个有效(10.50和20.30),一个无效。TOTAL_MEM=30.80,INVALID_COUNT=1,NUM_PIDS=3。SUM_INFO显示为“总计:30.80MB(1/3无效)”。
情况3:所有进程无效:
SUM_INFO显示“总计:N/A(所有进程数据无效)”。
情况4:部分无效,但TOTAL_MEM计算时出错(例如,MEM_MB包含非数字字符,导致bc失败):
此时SUM可能为空,需要处理,设置SUM_INFO为“总计:N/A(部分无效)”。
另外,需要注意bc的scale设置,确保小数点后两位。例如,使用scale=2,并且在除法时,用/1来保留两位小数。
例如,echo "scale=2; (10.5 + 20.3)/1" | bc 会输出30.80。
因此,上述处理应该是正确的。
现在,将这些修改应用到原脚本中,并在适当的位置添加变量初始化和处理逻辑。
最后,确保所有变量作用域正确,没有在循环外残留值。例如,在每次循环开始时,需要重置TOTAL_MEM和INVALID_COUNT,否则会累积之前的值。这一点非常重要,因为脚本是无限循环,每次循环都需要独立计算总和。
因此,在每次循环的开始时(在for PID循环之前),应该初始化TOTAL_MEM=0和INVALID_COUNT=0,否则上一次循环的总和会影响到下一次。
因此,正确的代码位置是在进入for循环之前,即在每次主循环的迭代中:
while true; do
TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')
LOG_ENTRY="[$TIMESTAMP]"
PIDS=$(pgrep -f "$PROCESS_NAME" | tr '\n' ' ')
if [ -z "$PIDS" ]; then
echo "[$TIMESTAMP] 未找到匹配进程" >> $LOG_FILE
sleep 10
continue
fi
# 初始化总和相关变量
TOTAL_MEM=0
INVALID_COUNT=0
PIDS_ARR=($PIDS)
NUM_PIDS=${#PIDS_ARR[@]}
for PID in $PIDS; do
MEM_KB=$(grep VmRSS /proc/$PID/status 2>/dev/null | awk '{print $2}')
MEM_MB=$(echo "scale=2; $MEM_KB / 1024" | bc 2>/dev/null || echo "N/A")
LOG_ENTRY+=" PID${PID}:${MEM_MB}MB;"
if [[ "$MEM_MB" =~ ^[0-9.]+$ ]]; then
TOTAL_MEM=$(echo "$TOTAL_MEM + $MEM_MB" | bc -l 2>/dev/null)
else
INVALID_COUNT=$((INVALID_COUNT + 1))
fi
done
# 处理总计
if [ $NUM_PIDS -gt 0 ]; then
if [ $INVALID_COUNT -eq $NUM_PIDS ]; then
SUM_INFO=" 总计:N/A(所有进程数据无效)"
elif [ $INVALID_COUNT -gt 0 ]; then
SUM=$(echo "scale=2; $TOTAL_MEM / 1" | bc -l 2>/dev/null)
if [ -z "$SUM" ]; then
SUM_INFO=" 总计:N/A(部分无效)"
else
SUM_INFO=" 总计:${SUM}MB(${INVALID_COUNT}/${NUM_PIDS}无效)"
fi
else
SUM=$(echo "scale=2; $TOTAL_MEM / 1" | bc -l 2>/dev/null)
SUM_INFO=" 总计:${SUM}MB"
fi
LOG_ENTRY+="$SUM_INFO"
fi
echo "$LOG_ENTRY" >> $LOG_FILE
sleep 10
done
这样,每次循环都会重新初始化TOTAL_MEM和INVALID_COUNT,确保每次的总和计算都是针对当前循环的PID列表。
现在,测试一下可能的错误情况:
- 当所有PID的MEM_MB都是N/A时,INVALID_COUNT等于NUM_PIDS,显示“总计:N/A(所有进程数据无效)”。
- 当部分无效时,显示总和和无效数量。
- 当bc计算失败时(例如TOTAL_MEM不是有效数字),SUM可能为空,此时显示“总计:N/A(部分无效)”。
不过,可能还需要处理TOTAL_MEM为空的情况。例如,在累加过程中,如果所有的MEM_MB都是N/A,则TOTAL_MEM仍然是0,但INVALID_COUNT等于NUM_PIDS,此时会触发第一个条件,显示所有无效。但是如果部分有效,部分无效,但有效的MEM_MB导致TOTAL_MEM是数值,但后续的bc计算失败,比如因为TOTAL_MEM是无效的字符串,比如空值,此时SUM可能无法正确计算。
例如,如果有一个进程的MEM_MB是"N/A",另一个是10.50,则TOTAL_MEM=10.50,INVALID_COUNT=1,此时SUM=10.50,显示“总计:10.50MB(1/2无效)”。
但是如果某个MEM_MB的值导致TOTAL_MEM无法计算,比如在累加时出现错误,例如MEM_MB是字符串,但被错误地当作数字,可能导致TOTAL_MEM的计算失败。但根据原脚本中的处理,当MEM_KB无法获取时,MEM_MB被设置为"N/A",因此在累加时会被过滤掉,不会进入if条件中的加法操作,因此TOTAL_MEM应该始终是有效的数值之和。
因此,只要在if条件中正确过滤掉非数值的MEM_MB,TOTAL_MEM应该是有效的数值总和。
综上,这样的修改应该能满足用户的需求,即在日志中每10秒记录每个进程的内存使用,并添加所有进程的内存总和。</think>以下是修改后的脚本,新增了**内存总和统计**功能,并附带详细注释和注意事项:
---
### **修改后的脚本**
```bash
#!/bin/bash
# 参数检查
if [ $# -ne 1 ]; then
echo "用法:$0 <进程名关键词>"
exit 1
fi
PROCESS_NAME="$1"
LOG_FILE="group_mem.log"
# 主循环
while true; do
TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')
LOG_ENTRY="[$TIMESTAMP]"
# 动态获取所有匹配进程的PID
PIDS=$(pgrep -f "$PROCESS_NAME" | tr '\n' ' ')
if [ -z "$PIDS" ]; then
echo "[$TIMESTAMP] 未找到匹配进程" >> $LOG_FILE
sleep 10
continue
fi
# 初始化内存总和和无效计数器
TOTAL_MEM=0
INVALID_COUNT=0
PIDS_ARR=($PIDS)
NUM_PIDS=${#PIDS_ARR[@]}
# 遍历每个PID
for PID in $PIDS; do
MEM_KB=$(grep VmRSS /proc/$PID/status 2>/dev/null | awk '{print $2}')
MEM_MB=$(echo "scale=2; $MEM_KB / 1024" | bc 2>/dev/null || echo "N/A")
LOG_ENTRY+=" PID${PID}:${MEM_MB}MB;"
# 累加有效内存值
if [[ "$MEM_MB" =~ ^[0-9.]+$ ]]; then
TOTAL_MEM=$(echo "$TOTAL_MEM + $MEM_MB" | bc -l 2>/dev/null)
else
INVALID_COUNT=$((INVALID_COUNT + 1))
fi
done
# 计算并记录内存总和
if [ $NUM_PIDS -gt 0 ]; then
if [ $INVALID_COUNT -eq $NUM_PIDS ]; then
SUM_INFO=" 总计:N/A(所有进程数据无效)"
elif [ $INVALID_COUNT -gt 0 ]; then
SUM=$(echo "scale=2; $TOTAL_MEM / 1" | bc -l 2>/dev/null)
SUM_INFO=" 总计:${SUM}MB(${INVALID_COUNT}/${NUM_PIDS}无效)"
else
SUM=$(echo "scale=2; $TOTAL_MEM / 1" | bc -l 2>/dev/null)
SUM_INFO=" 总计:${SUM}MB"
fi
LOG_ENTRY+="$SUM_INFO"
fi
echo "$LOG_ENTRY" >> $LOG_FILE
sleep 10
done
```
---
### **主要改动说明**
1. **新增内存总和统计**:
- 遍历每个进程时,检查内存值是否有效(数值型)。
- 有效值累加到 `TOTAL_MEM`,无效值计数 `INVALID_COUNT`。
- 根据无效值比例生成不同格式的总和描述(例如 `总计:50.20MB(1/3无效)`)。
2. **日志格式优化**:
- 每条日志末尾添加内存总和,格式为 `总计:XX.XXMB` 或 `总计:N/A(备注)`。
---
### **使用示例**
假设监控进程名为 `my_app`,日志输出如下:
```
[2023-10-01 12:00:00] PID1234:10.50MB; PID5678:20.30MB; 总计:30.80MB
[2023-10-01 12:00:10] PID1234:N/A; PID5678:20.30MB; 总计:20.30MB(1/2无效)
```
---
### **注意事项**
1. **依赖工具**:
- `bc`:用于浮点运算,确保系统已安装(可通过 `apt install bc` 或 `yum install bc` 安装)。
2. **错误处理**:
- 若进程已退出,`/proc/$PID/status` 可能不存在,此时内存值标记为 `N/A`。
- 总和计算会跳过无效值,并在日志中标注。
3. **性能影响**:
- 高频访问 `/proc` 可能略微增加系统负载,建议保持 `sleep 10` 的间隔。
---
### **扩展建议**
1. **自动清理日志**:
```bash
# 添加日志轮转(例如保留最近7天)
find /path/to/logs -name "group_mem.log" -mtime +7 -delete
```
2. **告警功能**:
- 若总和超过阈值(如 `1000MB`),可通过邮件或API发送通知。
修改后的脚本已实现内存总和统计,可根据需求进一步扩展功能。
阅读全文
相关推荐



















