shell获取进程运行时长

shell获取进程运行时长

Administrator 1452 2020-10-30

因为项目需求,需要对部分定时任务的进程进行监控,其中脚本的重点是获取指定进程的运行时长,并直接杀死超过指定时长的进程,这里记录一下整个脚本:


#!/bin/bash

# 函数的参数为过滤出的进程信息,然后进行运行时间的处理
function time_handler() {
	# 获取进程执行时间的信息列,格式有三种,min:sec,h:m:s,d-h:m:s
    exec_time=`echo $1 | awk '{print $2}'`
    # 获取exec_time变量的时间组成部分的数量
    time_field_count=`echo $exec_time | awk -F ':' '{print NF}'`
    # 获取倒数第二列数据,即分钟数
    count_minutes=`echo $exec_time | awk -F ':' '{print $(NF-1)}'`
	
	# 判断当前exec_time变量的数据属于哪种格式,如果是第一种,则天数,小时为0
    if [ $time_field_count -lt 3 ];then
        count_hours=0
        count_days=0
    else
    	# 如果判断不是第一种,还需要判断是否属于第二或第三种格式,并把对应的day,hours赋值给变量
        count_hours=`echo $exec_time | awk -F ':' '{print $(NF-2)}'`
        fields=`echo $count_hours |awk -F '-' '{print NF}'`
        if [ $fields -ne 1 ];then
            count_days=`echo $count_hours | awk -F '-' '{print $1}'`
            count_hours=`echo $count_hours | awk -F '-' '{print $2}'`
        else
            count_days=0
        fi
    fi
    # 以分钟为单位,计算总的分钟数
    elapsed_minutes=`expr $count_days \* 1440 + $count_hours \* 60 + $count_minutes`
}

while true;do
	# 获取进程信息,通过grep过滤需要的进程,并写入到文件,ps的etime参数即为进程运行时长
    process_list=`ps -eo pid,etime,cmd |grep -E 'magento queue:consumers'\|'magento cron:run'\|'magento setup:cron:run' |grep -v "grep" | tee result.txt`
    
    # 判断当前是否过滤到所需要的进程信息,没有则重新获取ps信息
    if test -z "$process_list";then
        continue
    fi
    # 按行读取文件信息,每一行为一个进程信息。
    cat result.txt | while read line;do
    	# 获取进程的pid
        pid=`echo $line | awk '{print $1}'`
        # 交给函数time_handler计算运行总时长
        time_handler "$line"
        # 判断运行时长是否超过指定时间,如果超过,则直接杀死进程。
        if [ $elapsed_minutes -gt 60 ];then
            echo "pid: $pid process is running $elapsed_minutes minutes."
            # 反复判断进程是否已被杀死。
            while [ `ps -eo pid | grep $pid | grep -v "grep"` ];do
                echo "killing pid:$pid process...."
                kill -9 $pid
            done
            echo "kill pid: $pid process success!"
        fi
    done
    sleep 30
done

其中,ps命令的 -eo 选项,是指定需要输出的信息,这里指定输出了pid,运行时间etime和cmd详细命令,输出的格式如下:

[root@localhost 2020TNT-1021]# ps -eo pid,etime,cmd
   PID     ELAPSED CMD
 18496  2-08:43:09 sshd: root@pts/1
 18498  2-08:43:08 -bash
 34092    06:31:13 [kworker/0:1]
 44152  1-23:53:06 [kworker/u256:0]
 50538       52:41 [kworker/u256:2]
 51102       41:00 [kworker/1:0]
 51962       23:08 pickup -l -t unix -u
 52071       20:54 [kworker/1:2]
 53034       00:50 [kworker/1:1]
 53075       00:00 ps -eo pid,etime,cmd

可以看到etime的三种格式,另外在对写入文件的进行信息进行循环读取时,如果使用for line in file进行读取,会由于每一行存在空格,导致读取出来的数据不正确,这里使用cat file.txt|while read line按行进行循环读取。