-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmonitor_java_cpu.sh
More file actions
160 lines (133 loc) · 7.2 KB
/
monitor_java_cpu.sh
File metadata and controls
160 lines (133 loc) · 7.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
#!/bin/bash
# Configuration
JAVA_PID=$1
CPU_THRESHOLD=${2:-50} # CPU threshold percentage, default: 50%
CHECK_INTERVAL=${3:-5} # Check interval in seconds, default: 5s
TOP_THREADS=${4:-10} # Number of top CPU threads, default: 10
STACK_LINES=${5:-20} # Stack trace lines per thread, default: 20
SNAPSHOT_DIR="./thread_snapshots"
if [ -z "$JAVA_PID" ]; then
echo "Usage: $0 <Java_PID> [CPU_Threshold] [Check_Interval] [Top_Threads] [Stack_Lines]"
echo "Example: $0 12345 50 5 10 20"
echo ""
echo "Parameters:"
echo " Java_PID - Java process ID (required)"
echo " CPU_Threshold - CPU threshold percentage (default: 50)"
echo " Check_Interval - Check interval in seconds (default: 5)"
echo " Top_Threads - Number of top CPU threads to capture (default: 10)"
echo " Stack_Lines - Number of stack trace lines per thread (default: 20)"
exit 1
fi
mkdir -p "$SNAPSHOT_DIR"
echo "Monitoring Java process: $JAVA_PID"
echo "CPU Threshold: ${CPU_THRESHOLD}%"
echo "Check Interval: ${CHECK_INTERVAL}s"
echo "Top Threads: ${TOP_THREADS}"
echo "Stack Lines: ${STACK_LINES}"
echo "Snapshot Directory: $SNAPSHOT_DIR"
echo "Press Ctrl+C to stop"
echo "================================"
while true; do
# Get process total CPU usage
TOTAL_CPU=$(top -b -n 1 -p $JAVA_PID | awk -v pid=$JAVA_PID '$1 == pid {print $9}')
if [ -z "$TOTAL_CPU" ]; then
echo "[$(date '+%Y-%m-%d %H:%M:%S')] Process $JAVA_PID not found"
exit 1
fi
# Convert to integer for comparison
CPU_INT=${TOTAL_CPU%.*}
echo "[$(date '+%Y-%m-%d %H:%M:%S')] CPU: ${TOTAL_CPU}%"
if [ "$CPU_INT" -ge "$CPU_THRESHOLD" ]; then
TIMESTAMP=$(date '+%Y%m%d_%H%M%S')
SNAPSHOT_FILE="$SNAPSHOT_DIR/jstack_${TIMESTAMP}_cpu${TOTAL_CPU}.txt"
THREAD_FILE="$SNAPSHOT_DIR/threads_${TIMESTAMP}_cpu${TOTAL_CPU}.txt"
STATS_FILE="$SNAPSHOT_DIR/stats_${TIMESTAMP}_cpu${TOTAL_CPU}.txt"
echo "⚠️ HIGH CPU DETECTED: ${TOTAL_CPU}% - Capturing snapshot..."
# Save full thread dump
jstack $JAVA_PID > "$SNAPSHOT_FILE"
# Save top N high CPU threads detail
{
echo "=== High CPU Threads at $(date) ==="
echo "Total Process CPU: ${TOTAL_CPU}%"
echo "Top ${TOP_THREADS} threads by CPU usage"
echo ""
top -H -p $JAVA_PID -b -n 1 | awk 'NR>7 {print $1,$9}' | head -${TOP_THREADS} | while read tid cpu; do
hex_tid=$(printf "0x%x" $tid)
echo "┌─────────────────────────────────────────────"
echo "│ Thread ID: $tid ($hex_tid) - CPU: ${cpu}%"
echo "└─────────────────────────────────────────────"
grep -A ${STACK_LINES} "nid=$hex_tid" "$SNAPSHOT_FILE" | head -$((STACK_LINES + 1))
echo ""
done
} > "$THREAD_FILE"
# Generate thread statistics report
{
echo "=== Thread Statistics Report ==="
echo "Generated at: $(date)"
echo "Process PID: $JAVA_PID"
echo "Total CPU: ${TOTAL_CPU}%"
echo ""
# Count total threads
TOTAL_THREADS=$(grep -c "^\"" "$SNAPSHOT_FILE")
echo "Total Threads: $TOTAL_THREADS"
echo ""
# Count threads by state
echo "Thread States:"
echo "─────────────────────────────────────────────"
RUNNABLE=$(grep "java.lang.Thread.State: RUNNABLE" "$SNAPSHOT_FILE" | wc -l)
WAITING=$(grep "java.lang.Thread.State: WAITING" "$SNAPSHOT_FILE" | wc -l)
TIMED_WAITING=$(grep "java.lang.Thread.State: TIMED_WAITING" "$SNAPSHOT_FILE" | wc -l)
BLOCKED=$(grep "java.lang.Thread.State: BLOCKED" "$SNAPSHOT_FILE" | wc -l)
NEW=$(grep "java.lang.Thread.State: NEW" "$SNAPSHOT_FILE" | wc -l)
TERMINATED=$(grep "java.lang.Thread.State: TERMINATED" "$SNAPSHOT_FILE" | wc -l)
printf "%-20s %6d (%5.1f%%)\n" "RUNNABLE" $RUNNABLE $(echo "scale=1; $RUNNABLE * 100 / $TOTAL_THREADS" | bc)
printf "%-20s %6d (%5.1f%%)\n" "TIMED_WAITING" $TIMED_WAITING $(echo "scale=1; $TIMED_WAITING * 100 / $TOTAL_THREADS" | bc)
printf "%-20s %6d (%5.1f%%)\n" "WAITING" $WAITING $(echo "scale=1; $WAITING * 100 / $TOTAL_THREADS" | bc)
printf "%-20s %6d (%5.1f%%)\n" "BLOCKED" $BLOCKED $(echo "scale=1; $BLOCKED * 100 / $TOTAL_THREADS" | bc)
printf "%-20s %6d (%5.1f%%)\n" "NEW" $NEW $(echo "scale=1; $NEW * 100 / $TOTAL_THREADS" | bc)
printf "%-20s %6d (%5.1f%%)\n" "TERMINATED" $TERMINATED $(echo "scale=1; $TERMINATED * 100 / $TOTAL_THREADS" | bc)
echo ""
# Count thread types
echo "Thread Types (Top 10):"
echo "─────────────────────────────────────────────"
grep "^\"" "$SNAPSHOT_FILE" | sed 's/"//g' | awk '{print $1}' | \
sed 's/-[0-9]*$//' | sort | uniq -c | sort -rn | head -10 | \
awk '{printf "%-40s %6d\n", $2, $1}'
echo ""
# RUNNABLE threads detail
if [ $RUNNABLE -gt 0 ]; then
echo "RUNNABLE Threads Detail:"
echo "─────────────────────────────────────────────"
grep -B 1 "java.lang.Thread.State: RUNNABLE" "$SNAPSHOT_FILE" | \
grep "^\"" | sed 's/"//g' | awk '{print $1}' | head -10
echo ""
fi
# BLOCKED threads detail
if [ $BLOCKED -gt 0 ]; then
echo "BLOCKED Threads Detail:"
echo "─────────────────────────────────────────────"
grep -B 1 "java.lang.Thread.State: BLOCKED" "$SNAPSHOT_FILE" | \
grep "^\"" | sed 's/"//g' | awk '{print $1}' | head -10
echo ""
fi
# Deadlock detection
echo "Deadlock Detection:"
echo "─────────────────────────────────────────────"
if grep -q "Found one Java-level deadlock" "$SNAPSHOT_FILE"; then
echo "⚠️ DEADLOCK DETECTED!"
grep -A 20 "Found one Java-level deadlock" "$SNAPSHOT_FILE"
else
echo "✓ No deadlock detected"
fi
} > "$STATS_FILE"
echo "✓ Snapshots saved:"
echo " - Full stack: $SNAPSHOT_FILE"
echo " - Top threads: $THREAD_FILE"
echo " - Statistics: $STATS_FILE"
echo ""
# Output statistics summary to terminal
echo "Thread Statistics Summary:"
grep -A 10 "Thread States:" "$STATS_FILE"
fi
sleep $CHECK_INTERVAL
done