zoukankan      html  css  js  c++  java
  • 定位一个进程出现超时或卡死的方法

    当定位一个进程出现超时或者卡死的问题,我们通常会怀疑是否是io超时或者其他调度问题,我们需要在这个进程出现卡死或超时,获取当时的调用栈信息,通过调用栈信息来分析可能的原因。如下为一个journald进程监控的方法:

    workdir=/root/journald
    coredir=${workdir}/cores
    
    function prepare() {
        mkdir -p ${workdir}
        mkdir -p ${coredir}
        systemctl start systemd-journald
        systemctl start rsyslog
    }
    
    function monitor_one() {
        local -i count="$1"
        message="${count}: this is a log to monitor journald."
        logger "${message}" &
        sleep 2
        contents=$(cat /var/log/messages | grep "${message}")
        if [ -z "$contents" ] ; then
            echo "journald in stuck...."
            pid=$(pgrep -f /usr/lib/systemd/systemd-journald)
            filename="journald-$(date +%s)-${count}"
                    cat /proc/${pid}/stack > ${coredir}/${filename}.stack
            gcore  -o ${coredir}/${filename} "${pid}"
            local -i core_count=$(ls -l ${coredir} | grep journald | wc -l)
            if [ ${core_count} -gt 100 ] ; then
                exit
            fi
        fi
    }
    
    function monitor_journal() {
        local -i count=0
        while : ; do
            ((count++))
            monitor_one $count
            sleep 4
            
        done
    }
    prepare
    monitor_journal

    这里主要的内容是当出现进程卡住时,获取进程的stack信息,使用gcore工具,在进程不重启的情况下,获取进程的core信息。获取到这些后用于问题分析。

    /proc/[pid]/stack

    /proc/[pid]/stack 示当前进程的内核调用栈信息,只有内核编译时打开了 CONFIG_STACKTRACE 编译选项,才会生成这个文件。举例如下:

    1
    2
    3
    4
    5
    6
    7
    $ cat /proc/2406/stack
    [<ffffffff810fa996>] futex_wait_queue_me+0xc6/0x130
    [<ffffffff810fb05d>] futex_wait+0x17d/0x270
    [<ffffffff810fd2d5>] do_futex+0xd5/0x520
    [<ffffffff810fd791>] SyS_futex+0x71/0x150
    [<ffffffff8180cc76>] entry_SYSCALL_64_fastpath+0x16/0x75
    [<ffffffffffffffff>] 0xffffffffffffffff

    gcore

    当调试一个程序的时候,理想状态是不重启应用程序就获取core文件。

    gcore命令可以使用下面步骤来获取core文件:

    1. 确认gdb软件包已经被正确安装。

    2. 使用调试参数编译程序(例如: gcc中使用"-g"选项),编译后不要去除文件的调试符号信息。

    3. 执行应用程序。

    4. 执行gcore命令生成指定应用程序的core文件并且保存在当前目录下。

    下面为一个监控dbus的脚本:

    workdir=/root/dbus
    coredir=${workdir}/cores
    
    function prepare() {
        mkdir -p ${workdir}
        mkdir -p ${coredir}
        systemctl start systemd-journald
        systemctl start rsyslog
        systemctl start sshd
        systemctl start dbus
    }
    
    function monitor_dbus() {
        local -i count=0
        local -i ecount=0
        while : ; do
        ((count++))
        
        /usr/bin/ssh 127.0.0.1 pwd >/dev/null 2>&1 &
        local -i ssh_pid=$!
        sleep 4
        process=$(ps -Lwwo pid,ppid,tid,psr,pri,stat,wchan:30,uname,vsize,rss,start_time,args --no-header -p ${ssh_pid} | grep "/usr/bin/ssh")
        if [ -n "${process}" ] ; then  ##当ssh进程超过4s都还没有退出的话,说明dbus可能占用了很长时间
            echo "dbus in stuck...."
            date_text=$(date +%s)
            dbus_pid=$(pgrep -f /bin/dbus-daemon)
            machined_pid=$(pgrep -f /usr/lib/systemd/systemd-machined)
            dbus_filename="dbus-${date_text}-${count}"
            machined_filename="machined-${date_text}-${count}"
            systemd_filename="systemd-${date_text}-${count}"
            cat /proc/1/stack > ${coredir}/${systemd_filename}.stack
            ps -eLwwo pid,ppid,tid,psr,pri,stat,wchan:30,uname,vsize,rss,start_time,args > ${coredir}/${systemd_filename}.ps
            top > ${coredir}/${systemd_filename}.top
            cat /proc/meminfo > ${coredir}/${systemd_filename}.mem
            cat /proc/interrupts > ${coredir}/${systemd_filename}.intr
            #gcore  -o ${coredir}/${dbus_filename} "${dbus_pid}"
            #gcore  -o ${coredir}/${machined_filename} "${machined_pid}"
            #gcore  -o ${coredir}/${systemd_filename} 1
            local -i core_count=$(ls -l ${coredir} | grep dbus | wc -l)
            ((ecount++))
            if [ $ecount -gt 3 ] ; then
                cp -frpa /run/cgroup_time.txt ${coredir}/cgroup_time.txt
                echo 3 > /proc/sys/vm/drop_caches
                echo c >/proc/sysrq-trigger
            fi
            if [ ${core_count} -gt 100 ] ; then
                exit
            fi
        else
            ((ecount=0))
        fi
        
        
        done
    }
    
    prepare
    monitor_dbus

      

    
    
  • 相关阅读:
    python单线程,多线程和协程速度对比
    python redis模块的常见的几个类 Redis 、StricRedis和ConnectionPool
    saltstack安装部署以及简单实用
    python编码详解--转自(Alex的博客)
    老铁,这年头不会点Git真不行!!!
    个人阅读&个人总结
    提问回顾
    结对项目
    个人作业Week3-案例分析
    个人作业Week2-代码复审
  • 原文地址:https://www.cnblogs.com/xingmuxin/p/9712113.html
Copyright © 2011-2022 走看看