Back
Featured image of post Shell脚本之进程管理

Shell脚本之进程管理

从 0 到 1 实现一个大型进程 shell 脚本, 带你启发思考

函数功能划分:

函数定义 函数功能
function get_all_group 获取所有进程组
function get_all_process 获取所有进程
function get_process_info 返回进程详细信息(运行状态, PID, CPU, MEM, 启动时间)
function get_all_process_by_group 返回进程组中所有进程名称

函数实现:

function get_all_group:

根据对应字段获取其下的所有组名

HOME_DIR="/root/shell"
CONFIG_FILE="process.cfg"

function get_all_group
{
    if [ ! -e $HOME_DIR/$CONFIG_FILE ]; then
        echo "$CONFIG_FIEL is not exist. Please check..."
        exit 1
    else
        G_LIST=`sed -n '/\[GROUP_LIST\]/,/\[.*\]/p' process.cfg  | egrep -v "(\[.*\]|^$)"`
        echo "$G_LIST"
    fi
}

function get_all_process

遍历所有组, 获取其下的所有进程

function get_all_processes
{
    for g in `get_all_group`;do
        P_LIST=`sed -n '/\['$g'\]/,/\[.*\]/p' process.cfg  | egrep -v "^\[|^$"`
        echo $P_LIST
    done
}

function get_process_info

  1. 继续拆分函数, 拆分为 get_process_pid_by_name, get_process_info_by_pid
  2. 可直接使用 ps aux 把统计的名称的数据一并处理

get_process_pid_by_name:

function get_process_pid_by_name
{
    # 只接受一个参数
    if [ $# != 1 ]; then
        return 1   # 非 0 即为错误
    else
    	# 过滤掉脚本本身
        pids=`ps -ef | grep "$1" | grep -v grep | grep -v $0 | awk '{print $2}'`
        echo $pids
    fi
}

get_process_info_by_pid:

function get_process_info_by_pid
{
   if [ `ps -ef | awk -v p_id=$1 '$2==p_id{print}' | wc -l` == 1 ]; then
        pro_status="RUNNING"
   else
        pro_status="STOPED"
   fi
   pro_cpu=`ps aux | awk -v p_id=$1 '$2==p_id{print $3}'`
   pro_mem=`ps aux | awk -v p_id=$1 '$2==p_id{print $4}'`
   pro_start="`ps -p $1 -o lstart`"
}

function get_all_process_by_group

function is_group_in_config
{
    for g in `get_all_group`;do
        if [ "$1" == $g ];then
            return 0
        fi
    done
    return 1
}

function get_all_processes_by_group
{
    is_group_in_config $1
    if [ $? == 0 ];then
        p_list=`sed -n '/\['$1'\]/,/\[.*\]/p' $HOME_DIR/$CONFIG_FILE | egrep -v "(^$|^#|^\[)"`
        echo $p_list
    else
        echo "GroupName $1 is not in process.cfg"
    fi
}

主流程设计

接受参数 行为
无参数 打印所有信息
-g 组名 接受多个组名, 打印组下所有进程
进程名 打印指定进程名
if [ $# -gt 0 ];then
    if [ $1 == "-g" ];then
        # 接受组名, 把参数左移, 去掉 -g
        shift
        for gn in $@; do
            is_group_in_config $gn || continue
            for pn in `get_all_processes_by_group`;do
                is_process_in_config $pn && format_print $pn $gn
            done
        done
    else
        for pn in $@;do
            is_process_in_config $pn && format_print $pn $gn
        done
    fi
else
    # 没有参数, 打印所有
    for pn in `get_all_processes`;do
        gn=`get_group_by_process_name $pn`
        is_process_in_config $pn && format_print $pn $gn
    done
fi

完整脚本

#!/bin/bash
#
# Func: Get app info from process.cfg

HOME_DIR="/root/shell"
CONFIG_FILE="process.cfg"
this_pid=$$

function get_all_group
{
    G_LIST=`sed -n '/\[GROUP_LIST\]/,/\[.*\]/p' process.cfg  | egrep -v "(\[.*\]|^$)"`
    echo "$G_LIST"
}

function get_all_processes
{
    for g in `get_all_group`;do
        P_LIST=`sed -n '/\['$g'\]/,/\[.*\]/p' process.cfg  | egrep -v "^\[|^$"`
        echo $P_LIST
    done
}

function get_process_pid_by_name
{
    # 只接受一个参数
    if [ $# != 1 ]; then
        return 1   # 非 0 即为错误
    else
        pids=`ps -ef | grep "$1" | grep -v grep | grep -v $0 | awk '{print $2}'`
        echo $pids
    fi
}

function get_process_info_by_pid
{
   if [ `ps -ef | awk -v p_id=$1 '$2==p_id{print}' | wc -l` == 1 ]; then
        pro_status="RUNNING"
   else
        pro_status="STOPED"
   fi
   pro_cpu=`ps aux | awk -v p_id=$1 '$2==p_id{print $3}'`
   pro_mem=`ps aux | awk -v p_id=$1 '$2==p_id{print $4}'`
   pro_start_time="`ps -p $1 -o lstart`"
}

function is_group_in_config
{
    for g in `get_all_group`;do
        if [ "$1" == $g ];then
            return 0
        fi
    done
    echo "Group $1 is not in process.cfg"
    return 1
}

function get_all_processes_by_group
{
    is_group_in_config $1
    if [ $? == 0 ];then
        p_list=`sed -n '/\['$1'\]/,/\[.*\]/p' $HOME_DIR/$CONFIG_FILE | egrep -v "(^$|^#|^\[)"`
        echo $p_list
    else
        echo "GroupName $1 is not in process.cfg"
    fi
}

function format_print
{
    ps -ef | grep $1 | grep -v grep | grep -v $this_pid &> /dev/null
    if [ $? -eq 0 ]; then
        pids=`get_process_pid_by_name $1`
        for pid in $pids; do
            get_process_info_by_pid $pid
            awk -v p_name=$1 -v g_name=$2 -v p_id=$pid -v p_status=$pro_status -v p_cpu=$pro_cpu -v p_mem=$pro_mem $p_start_time="$pro_start_time" 'BEGIN{printf "%-10s%-10s%-5s%-5s%-5s%-5s%-15s",p_name,g_name,p_id,p_status,p_cpu,p_mem,p_start_time}'
        done
    else
        # 进程不存在
        awk -v p_name=$1 -v g_name=$2  'BEGIN{printf "%-10s%-10s%-5s%-5s%-5s%-5s%-15s",p_name,g_name,"NULL","STOPED","NULL","NULL","NULL"}'
    fi
}

function is_process_in_config
{
    for pn in `get_all_process`;do
        if [ $pn == $1 ];then
            return
        fi
    done
    echo "Process $1 is not in process.cfg"
    return 1
}

function get_group_by_process_name
{
    for gn in `get_all_group`;do
        for pn in `get_all_process_by_group $gn`;do
            if [ $pn == $1 ]; then
                ehco $gn
            fi
        done
    done
}

if [ $# -gt 0 ];then
    if [ $1 == "-g" ];then
        # 接受组名, 把参数左移, 去掉 -g
        shift
        for gn in $@; do
            is_group_in_config $gn || continue
            for pn in `get_all_processes_by_group`;do
                is_process_in_config $pn && format_print $pn $gn
            done
        done
    else
        for pn in $@;do
            is_process_in_config $pn && format_print $pn $gn
        done
    fi
else
    # 没有参数, 打印所有
    for pn in `get_all_processes`;do
        gn=`get_group_by_process_name $pn`
        is_process_in_config $pn && format_print $pn $gn
    done
fi
Licensed under CC BY-NC-SA 4.0