Linux中如何获得进程的运行时堆栈
关于这个话题,我们一般是为了处理一下生产环境中程序出现死循环或者死锁等问题。我们一般想到的方法就是gdb attach上一个运行中的进程。但是这个需要手动交互。通过网上查找和实践,可以有以下几种选择:
- 第一种:pstack 进程ID (pstack就是一个利用gdb实现的shell脚本)
- 第二种:gcore 进程IP (gcore也是一个gdb实现的脚本)
- (看来目前现成的工具都是站在gdb的肩膀上了,除非我们利用ptrace()API参考gdb的源码自己写一个)
- 第三种:利用fork()的方式,继承一个进程,然后再新的子进程里面直接使用异常信号产生coredump。
描述 | 优点/缺点 | |
pstack | 依赖系统中的gdb,会是程序短暂的停止运行。 |
优点:不需要对原有程序做任何改变,直接可以产看运行时。 缺点: 依赖gdb |
gcore | 依赖系统中的gdb,会是程序短暂的停止运行。 |
优点:不需要对原有程序做任何改变,直接可以产看运行时。 缺点: 依赖gdb |
fork() | 需要改造原有程序,增加事件代码触发fork()动作 |
优点:不依赖gdb。 缺点: 需要修改源程序 |
相关代码:
pstack
[root@localhost ~]# cat /usr/bin/gstack#!/bin/shif test $# -ne 1; thenecho "Usage: `basename $0 .sh` <process-id>" 1>&2exit 1fiif test ! -r /proc/$1; thenecho "Process $1 not found." 1>&2exit 1fi# GDB doesn't allow "thread apply all bt" when the process isn't# threaded; need to peek at the process to determine if that or the# simpler "bt" should be used.backtrace="bt"if test -d /proc/$1/task ; then# Newer kernel; has a task/ directory.if test `/bin/ls /proc/$1/task | /usr/bin/wc -l` -gt 1 2>/dev/null ; thenbacktrace="thread apply all bt"fielif test -f /proc/$1/maps ; then# Older kernel; go by it loading libpthread.if /bin/grep -e libpthread /proc/$1/maps > /dev/null 2>&1 ; thenbacktrace="thread apply all bt"fifiGDB=${GDB:-/usr/bin/gdb}if $GDB -nx --quiet --batch --readnever > /dev/null 2>&1; thenreadnever=--readneverelsereadnever= fi# Run GDB, strip out unwanted noise.$GDB --quiet $readnever -nx /proc/$1/exe $1 <<EOF 2>&1 |$backtraceEOF/bin/sed -n \ -e 's/^(gdb) //' \ -e '/^#/p' \-e '/^Thread/p' [root@localhost ~]#
2. gcore
root@xxx:/App/Log# cat /usr/bin/gcore
#!/bin/sh# Copyright (C) 2003-2016 Free Software Foundation, Inc.# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.##############################
# check /opt/tmp/corefile and left lastest gcore files!
# check /App/corefile and left lastest gcore.tar.gz files!
##############################
function check_gcore_files () {dir_list=(/opt/tmp/corefile /App/corefile)for item in ${dir_list[*]}doecho "$item"cd $itemcorecounts=0for file in $(ls -t gcore-*)do#echo file=$filecorecounts=`expr $corecounts + 1`;#echo corecounts=$corecounts# rm the more fileif [ $corecounts -gt 5 ]; thenrm $fileecho "rm $file"fidone#go back path:cd -done
}#
# Script to generate a core file of a running program.
# It starts up gdb, attaches to the given PID and invokes the gcore command.
#if [ "$#" -eq "0" ]
thenecho "usage: $0 [-o filename] pid"exit 2
fi# Need to check for -o option, but set default basename to "core".
name_tail=`date +"%Y-%m-%d-%H.%M.%S"`
tmp_name=gcore-"$name_tail"name=gcore-"$name_tail"if [ "$1" = "-o" ]
thenif [ "$#" -lt "3" ]then# Not enough arguments.echo "usage: gcore [-o filename] pid"exit 2finame=$2# Shift over to start of pid listshift; shift
fiecho "tmpfile:$tmp_name, outfile:$name"# Attempt to fetch the absolute path to the gcore script that was
# called.
#binary_path=`dirname "$0"`
binary_path="/usr/bin"if test "x$binary_path" = x. ; then# We got "." back as a path. This means the user executed# the gcore script locally (i.e. ./gcore) or called the# script via a shell interpreter (i.e. sh gcore).binary_basename=`basename "$0"`# If the gcore script was called like "sh gcore" and the script# lives in the current directory, "which" will not give us "gcore".# So first we check if the script is in the current directory# before using the output of "which".if test -f "$binary_basename" ; then# We have a local gcore script in ".". This covers the case of# doing "./gcore" or "sh gcore".binary_path="."else# The gcore script was not found in ".", which means the script# was called from somewhere else in $PATH by "sh gcore".# Extract the correct path now.binary_path_from_env=`which "$0"`binary_path=`dirname "$binary_path_from_env"`fi
fi# Check if the GDB binary is in the expected path. If not, just
# quit with a message.
if [ ! -f "$binary_path"/gdb ]; thenecho "gcore: GDB binary (${binary_path}/gdb) not found"exit 1
fi# Initialise return code.
rc=0
echo "---------------------------"
# Loop through pids
for pid in $*
do# `</dev/null' to avoid touching interactive terminal if it is# available but not accessible as GDB would get stopped on SIGTTIN.date$binary_path/gdb </dev/null --nx --batch \-ex "set pagination off" -ex "set height 0" -ex "set width 0" \-ex "attach $pid" -ex "gcore /tmp/$tmp_name.$pid" -ex detach -ex quitif [ -r "/tmp/$tmp_name.$pid" ] ; thenrc=0echo "------------------"datetar -czvPf $name.$pid.tar.gz "/tmp/$tmp_name.$pid"echo "------------------"dateecho "------------------"rm -rf "/tmp/$tmp_name.$pid"dateelseecho "gcore: failed to create $name.$pid"rc=1breakfi
check_gcore_filesdone
echo "------------------"
exit $rc
Note: 我们可以一些参数控制gcore参数的coredump文件的大小
3. 使用fork() (代码略)
参考:
如何获取运行时进程堆栈
Linux中如何获得进程的运行时堆栈相关推荐
- linux aspnet服务器,在Linux中安装ASPNET.Core3.0运行时的示例代码
摘要: # 以下示例适用于x64位runtime v3.0.0mkdir /runtimescd /runtimeswget https://... # 以下示例适用于x64位runtime v3.0 ...
- Linux中创建Daemon进程的三种方法
Linux中创建Daemon进程的三种方法 什么是daemon进程? Unix/Linux中的daemon进程类似于Windows中的后台服务进程,一直在后台运行运行,例如http服务进程nginx, ...
- Linux中线程和进程的区别
Linux中线程和进程的区别 进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,它是系统进行资源分配和调度的一个独立单位.例如,用户运行自己的程序,系统就创建一个进程,并为它分配资源,包括 ...
- suse 新增用户oracle,在SUSE Linux中让其他用户能运行Oracle命令
SUSE Linux中让其他用户能运行Oracle命令的方法介绍: suid/guid的问题: 要求非Oracle用户也能运行sqlplus等oracle命令. 解决方法: 假如希望设置s u i d ...
- linux中终止停止进程_如何在Linux中终止进程或停止程序
linux中终止停止进程 当一个进程行为异常时,您有时可能想要终止或终止它. 在本文中,我们将探讨几种使用gedit作为示例应用程序从命令行以及图形界面终止进程或应用程序的方法. 使用命令行/终止符 ...
- linux中启动 java -jar 后台运行程序
ps -ef | grep java 查询java 端口占用 linux中启动 java -jar 后台运行程序 直接用java -jar xxx.jar,当退出或关闭shell时,程序就会停止掉. ...
- 在linux下python爬虫进程发生异常时自动重启直至正常结束的方法
在linux下python爬虫进程发生异常时自动重启直至正常结束的方法 参考文章: (1)在linux下python爬虫进程发生异常时自动重启直至正常结束的方法 (2)https://www.cnbl ...
- ActiveReports中如何在后台导出运行时绑定数据源报表
ActiveReports支持运行时绑定数据源功能,这种绑定数据源方法使用较为普及,然而很多系统中都需要在后台导出报表文件,所以用户就很困惑,ActiveReports中如何在后台导出运行时绑定数据源 ...
- 如何在linux中关闭一个进程
如何在linux中kill一个进程 刚开始学习Linux的时候,总是直接点击×来关闭程序.虽然知道这是关闭整个终端程序,但是奈何如此简单的事情对于新手来说都是很困难的.
最新文章
- C#软件自动更新程序
- C:\WINDOWS\WinSxS目录介绍,来自百度词条
- php图片案例,web开发N例-案例2:PHP绘制图片、绘制中文
- intellij idea 代码错误设置 Error 提示颜色修改
- CentOS基本的命令与快捷建
- oracle在线重定义表分区,oracle把一张表在线重定义成分区表
- JDBC实战(一)JDBC概述
- 解决win 7的Aero Peek无效的方法
- (Mysql)跨表查询和跨库查询
- DDoS攻击--CC攻击防护详解(HTTP)
- 【小算法】求约数个数
- 菜鸟教程,css小白入门
- 好文章,转的Java重构
- 21-4-21 USB接口
- 菩提本无树,明镜亦非台,本来无一物,何处惹尘埃。
- 深入理解connect by levelxxx
- 倍福PLC--C#实现ADS通信超时重传设定
- 制作关于计算机的ppt图片,10步教你制作图片墙PPT封面
- JavaScript核心 DOM 和 BOM操作
- ncnn 框架分析 openmp多核加速 缓存 仿存 cache 快速矩阵乘法 单指令多数据指令SIMD