Shell脚本定期使用 jcmd
对目标 Java 应用进行监控、诊断数据导出,并带有日志输出。用于定时采样、OOM分析、死锁排查等场景。
功能
-
自动获取 Java 进程 ID;
-
每次执行记录:
- 当前时间;
- 堆信息 (
GC.heap_info
); - 类实例直方图 (
GC.class_histogram
); - 线程堆栈 (
Thread.print
); - 导出 heap dump;
-
每次写入带时间戳的日志文件中。
Shell 脚本
jcmd_monitor.sh
#!/bin/bash
# ===== 配置项 =====
APP_NAME="MyApp" # 可为主类、jar名关键字、完整名称等
DUMP_DIR="/tmp/jcmd_dumps" # 输出目录
INTERVAL=60 # 间隔秒数
MAX_DUMPS=10 # 最多保留多少轮快照
# ===== 初始化目录 =====
mkdir -p "$DUMP_DIR"
echo "[INFO] Starting jcmd monitoring for: $APP_NAME"
echo "[INFO] Dump folder: $DUMP_DIR"
while true; do
TIMESTAMP=$(date "+%Y%m%d-%H%M%S")
LOG_PREFIX="$DUMP_DIR/jcmd-$TIMESTAMP"
# 查找 Java 进程 PID(可根据 APP_NAME 修改)
PID=$(jcmd | grep "$APP_NAME" | awk '{print $1}')
if [[ -z "$PID" ]]; then
echo "[WARN] No Java process found for keyword: $APP_NAME"
sleep "$INTERVAL"
continue
fi
echo "[INFO] Running jcmd diagnostics on PID: $PID at $TIMESTAMP"
# 输出 JVM 堆信息
jcmd "$PID" GC.heap_info > "$LOG_PREFIX.heap_info.log" 2>&1
# 输出类直方图
jcmd "$PID" GC.class_histogram > "$LOG_PREFIX.class_histogram.log" 2>&1
# 输出线程栈
jcmd "$PID" Thread.print > "$LOG_PREFIX.thread_dump.log" 2>&1
# 可选:导出 heap dump(如不需要可注释掉)
jcmd "$PID" GC.heap_dump "$LOG_PREFIX.heap.hprof" > "$LOG_PREFIX.heap_dump.log" 2>&1
echo "[INFO] Dump complete: $LOG_PREFIX"
# 自动清理最旧的文件
ls -1t "$DUMP_DIR"/* | tail -n +$((MAX_DUMPS * 5 + 1)) | xargs -r rm -f
sleep "$INTERVAL"
done