1. 前置准备
确保服务器上已安装以下工具(通常 Linux 发行版默认都有,但 lrzsz 可能需要手动安装):
- JDK: 必须包含
jmap命令(通常在$JAVA_HOME/bin下)。 - lrzsz: 用于
sz命令。- CentOS/RedHat:
yum install -y lrzsz - Ubuntu/Debian:
apt-get install -y lrzsz
- CentOS/RedHat:
2. 创建脚本文件
vi dump_heap.sh
3. 赋予执行权限
chmod +x dump_heap.sh
4. (可选) 修改配置
修改顶部的配置区:
KEYWORD="你的进程关键词" # 比如 "my-app.jar" 或 "com.example.Main"
DUMP_DIR="./dump" # 输出目录
SPLIT_SIZE="1G" # 分卷大小,如果网络好可以改大,网络差改小 (如 500M)
5. 执行脚本
./dump_heap.sh
6. 脚本内容
#!/bin/bash set -e # ================= 配置区 ================= KEYWORD="yh-hsb-engine.jar" # 进程关键词,用于匹配目标 Java 进程 DUMP_DIR="./dump" # 堆 dump 文件及压缩包的输出目录 RAW_FILE_NAME="heapdump.hprof" # jmap 生成的原始堆 dump 文件名 BASE_NAME="heapdump" # 最终压缩包的基础文件名(不含后缀) SPLIT_SIZE="1000m" # 分卷大小 (1G = 1024MB),超过阈值时每个分卷的大小 SIZE_LIMIT=1073741824 # 分割阈值(字节),约 1024MB,超过此值才触发分卷 # ========================================= SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" DUMP_PATH="${SCRIPT_DIR}/${DUMP_DIR/#.\//}" mkdir -p "$DUMP_PATH" RAW_FILE="${DUMP_PATH}/${RAW_FILE_NAME}" TAR_FILE="${DUMP_PATH}/${BASE_NAME}.tar.gz" # 1. 获取 PID PID=$(ps -ef | grep "$KEYWORD" | grep -v grep | head -n 1 | awk '{print $2}') [ -z "$PID" ] && echo "Error: Process '$KEYWORD' not found!" && exit 1 echo "Found PID: $PID" # 2. 执行 Dump echo "Dumping heap..." jmap -dump:live,format=b,file="$RAW_FILE" "$PID" || exit 1 # 3. 压缩前清理旧文件 # 只清理旧的 .tar.gz 及其分卷,确保本次生成的文件名不冲突 echo "Cleaning up old archive files before compressing..." rm -f "${DUMP_PATH}/${BASE_NAME}.tar.gz"* 2>/dev/null || true # 4. 压缩 (Tar + Gzip) echo "Compressing..." tar -czf "$TAR_FILE" -C "$DUMP_PATH" "$RAW_FILE_NAME" # 压缩成功后删除原始 hprof 以节省空间 rm -f "$RAW_FILE" # 5. 判断并分割 FILE_SIZE=$(stat -c%s "$TAR_FILE") if [ $FILE_SIZE -gt $SIZE_LIMIT ]; then echo "Size ($FILE_SIZE) > Limit ($SIZE_LIMIT). Splitting..." echo "Executing: split -b ${SPLIT_SIZE} -d -a 2 ${TAR_FILE} ${TAR_FILE}" split -b "$SPLIT_SIZE" -d -a 2 "$TAR_FILE" "$TAR_FILE" rm -f "$TAR_FILE" # 分割后删除原大文件,只保留分卷 (.00, .01...) else echo "No split needed (Size: $FILE_SIZE)." # 不分割,保留原压缩包 fi # 6. 展示文件 echo "" echo "==========================================" echo "Generated files:" cd "$DUMP_PATH" ls -lh ${BASE_NAME}.tar.gz* echo "==========================================" # 7. 询问是否发送 read -p "Send via sz? (y/n): " CONFIRM if [[ "$CONFIRM" =~ ^[Yy]$ ]]; then command -v sz &>/dev/null || { echo "Error: sz command not found."; exit 1; } echo "Starting transfer... (Do not interrupt)" sz ${BASE_NAME}.tar.gz* echo "" echo "Transfer finished." echo "Files are RETAINED in: $DUMP_PATH" echo "Please manually clean them up later if needed." else echo "Skipped sending." echo "Files are RETAINED in: $DUMP_PATH" echo "You can send them manually later." fi
浙公网安备 33010602011771号