152 lines
4.2 KiB
Bash
152 lines
4.2 KiB
Bash
|
|
#!/bin/bash
|
||
|
|
# 优化版:监控 gunicorn 主进程及其子进程资源变化(表格+彩色输出)
|
||
|
|
|
||
|
|
PROC_NAME="gunicorn"
|
||
|
|
LOG_DIR="/data/sh/monitor/logs"
|
||
|
|
LOG_FILE="$LOG_DIR/proc_monitor.log"
|
||
|
|
DATA_FILE="$LOG_DIR/last_snapshot.txt"
|
||
|
|
|
||
|
|
mkdir -p "$LOG_DIR"
|
||
|
|
|
||
|
|
# 颜色定义
|
||
|
|
RED='\033[1;31m'
|
||
|
|
GREEN='\033[1;32m'
|
||
|
|
YELLOW='\033[1;33m'
|
||
|
|
BLUE='\033[1;34m'
|
||
|
|
NC='\033[0m' # 无色
|
||
|
|
|
||
|
|
# 获取系统内存概况
|
||
|
|
get_sys_mem() {
|
||
|
|
free -h | awk '/Mem:/ {printf "系统内存概况:总 %s | 已用 %s | 空闲 %s | 可用 %s", $2, $3, $4, $7}'
|
||
|
|
}
|
||
|
|
|
||
|
|
# 获取时间
|
||
|
|
format_time() {
|
||
|
|
date "+%Y-%m-%d %H:%M:%S"
|
||
|
|
}
|
||
|
|
|
||
|
|
# 获取 gunicorn 主进程和子进程信息
|
||
|
|
get_proc_info() {
|
||
|
|
ps -eo pid,ppid,comm,%mem,%cpu,rss --no-headers | awk -v pname="$PROC_NAME" '$3 == pname {print $1, $2, $3, $4, $5, $6}'
|
||
|
|
}
|
||
|
|
|
||
|
|
# 保存当前状态快照
|
||
|
|
save_snapshot() {
|
||
|
|
get_proc_info | awk '{print $1,$3,$4,$5}' > "$DATA_FILE"
|
||
|
|
}
|
||
|
|
|
||
|
|
# 打印表格头
|
||
|
|
print_table_header() {
|
||
|
|
printf "%-10s %-12s %-12s %-12s %-12s\n" "PID" "进程名" "内存(Gi)" "CPU(%)" "备注"
|
||
|
|
}
|
||
|
|
|
||
|
|
# 打印分隔线
|
||
|
|
print_line() {
|
||
|
|
printf "%s\n" "---------------------------------------------------------------"
|
||
|
|
}
|
||
|
|
|
||
|
|
# 获取主进程 PID
|
||
|
|
MAIN_PID=$(pgrep -f "$PROC_NAME" | head -n 1)
|
||
|
|
if [ -z "$MAIN_PID" ]; then
|
||
|
|
echo -e "${RED}未找到进程:$PROC_NAME${NC}"
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
|
||
|
|
TIMESTAMP=$(format_time)
|
||
|
|
echo "==== $TIMESTAMP ====" >> "$LOG_FILE"
|
||
|
|
echo "$(get_sys_mem)" >> "$LOG_FILE"
|
||
|
|
echo "主进程名:$PROC_NAME | PID: $MAIN_PID" >> "$LOG_FILE"
|
||
|
|
|
||
|
|
# 写表格头
|
||
|
|
print_table_header >> "$LOG_FILE"
|
||
|
|
print_line >> "$LOG_FILE"
|
||
|
|
|
||
|
|
# 获取当前进程信息
|
||
|
|
CUR_INFO=$(get_proc_info)
|
||
|
|
|
||
|
|
echo "$CUR_INFO" | while read -r pid ppid name mem cpu rss; do
|
||
|
|
mem_gi=$(awk "BEGIN {printf \"%.2f\", $rss/1024/1024}") # KB -> Gi
|
||
|
|
printf "%-10s %-12s %-12s %-12s\n" "$pid" "$name" "${mem_gi}Gi" "${cpu}%" >> "$LOG_FILE"
|
||
|
|
done
|
||
|
|
|
||
|
|
print_line >> "$LOG_FILE"
|
||
|
|
|
||
|
|
# 若无上次记录,跳过变化分析
|
||
|
|
if [ ! -f "$DATA_FILE" ]; then
|
||
|
|
echo "暂无上次记录,跳过变化分析。" >> "$LOG_FILE"
|
||
|
|
save_snapshot
|
||
|
|
echo "==== $TIMESTAMP ====" >> "$LOG_FILE"
|
||
|
|
exit 0
|
||
|
|
fi
|
||
|
|
|
||
|
|
# 对比分析部分
|
||
|
|
declare -A CUR_MEM CUR_CPU PRE_MEM PRE_CPU
|
||
|
|
|
||
|
|
while read -r pid name mem cpu; do
|
||
|
|
CUR_MEM["$pid"]=$mem
|
||
|
|
CUR_CPU["$pid"]=$cpu
|
||
|
|
done < <(get_proc_info | awk '{print $1,$3,$4,$5}')
|
||
|
|
|
||
|
|
while read -r pid name mem cpu; do
|
||
|
|
PRE_MEM["$pid"]=$mem
|
||
|
|
PRE_CPU["$pid"]=$cpu
|
||
|
|
done < "$DATA_FILE"
|
||
|
|
|
||
|
|
CUR_PIDS=$(printf "%s\n" "${!CUR_MEM[@]}" | sort)
|
||
|
|
PRE_PIDS=$(printf "%s\n" "${!PRE_MEM[@]}" | sort)
|
||
|
|
|
||
|
|
NEW_PIDS=$(comm -23 <(echo "$CUR_PIDS") <(echo "$PRE_PIDS"))
|
||
|
|
OLD_PIDS=$(comm -13 <(echo "$CUR_PIDS") <(echo "$PRE_PIDS"))
|
||
|
|
|
||
|
|
echo "分析变化:" >> "$LOG_FILE"
|
||
|
|
|
||
|
|
# 新旧进程分析
|
||
|
|
if [ -n "$NEW_PIDS" ]; then
|
||
|
|
echo -e " ${GREEN}新出现的子进程:${NC}" >> "$LOG_FILE"
|
||
|
|
for pid in $NEW_PIDS; do
|
||
|
|
echo " $PROC_NAME (PID:$pid)" >> "$LOG_FILE"
|
||
|
|
done
|
||
|
|
fi
|
||
|
|
|
||
|
|
if [ -n "$OLD_PIDS" ]; then
|
||
|
|
echo -e " ${YELLOW}已消失的子进程:${NC}" >> "$LOG_FILE"
|
||
|
|
for pid in $OLD_PIDS; do
|
||
|
|
echo " $PROC_NAME (PID:$pid)" >> "$LOG_FILE"
|
||
|
|
done
|
||
|
|
fi
|
||
|
|
|
||
|
|
# 资源变化分析
|
||
|
|
echo " 子进程资源变化:" >> "$LOG_FILE"
|
||
|
|
for pid in $CUR_PIDS; do
|
||
|
|
if [ -n "${PRE_MEM[$pid]}" ]; then
|
||
|
|
cpu_diff=$(awk "BEGIN {printf \"%.1f\", ${CUR_CPU[$pid]} - ${PRE_CPU[$pid]}}")
|
||
|
|
mem_diff=$(awk "BEGIN {printf \"%.2f\", ${CUR_MEM[$pid]} - ${PRE_MEM[$pid]}}")
|
||
|
|
|
||
|
|
color_start=""
|
||
|
|
color_end="$NC"
|
||
|
|
if (( $(echo "$mem_diff > 0.2" | bc -l) )); then
|
||
|
|
color_start=$RED
|
||
|
|
elif (( $(echo "$mem_diff < -0.2" | bc -l) )); then
|
||
|
|
color_start=$GREEN
|
||
|
|
else
|
||
|
|
color_start=$YELLOW
|
||
|
|
fi
|
||
|
|
|
||
|
|
echo -e " ${color_start}$PROC_NAME (PID:$pid): CPU变化 ${cpu_diff}% | 内存变化 ${mem_diff}%${color_end}" >> "$LOG_FILE"
|
||
|
|
fi
|
||
|
|
done
|
||
|
|
|
||
|
|
# 当前最高占用进程
|
||
|
|
top_cpu_pid=$(ps -eo pid,comm,%cpu --no-headers | grep "$PROC_NAME" | sort -k3 -nr | head -n 1 | awk '{print $1}')
|
||
|
|
top_mem_pid=$(ps -eo pid,comm,%mem --no-headers | grep "$PROC_NAME" | sort -k3 -nr | head -n 1 | awk '{print $1}')
|
||
|
|
|
||
|
|
if [ -n "$top_cpu_pid" ]; then
|
||
|
|
echo -e " ${BLUE}当前占用最高CPU的进程:${NC} $PROC_NAME (PID:$top_cpu_pid)" >> "$LOG_FILE"
|
||
|
|
fi
|
||
|
|
if [ -n "$top_mem_pid" ]; then
|
||
|
|
echo -e " ${BLUE}当前占用最高内存的进程:${NC} $PROC_NAME (PID:$top_mem_pid)" >> "$LOG_FILE"
|
||
|
|
fi
|
||
|
|
|
||
|
|
save_snapshot
|
||
|
|
echo "==== $TIMESTAMP ====" >> "$LOG_FILE"
|