天天看點

【Shell腳本程式設計(八)】大型腳本開發實戰

1. 腳本工具功能概述

需求描述:

  1. 實作一個腳本工具,該腳本提供類似supervisor功能,可以對程序進行管理;
  2. 一鍵檢視所有程序運作狀态;
  3. 單個或批量啟動程序,單個或批量停止程序;
  4. 提供程序分組功能,可以按組檢視程序運作狀态,可以按組啟動或停止該組内所有程序;

2. 拆分腳本功能,抽象函數

  1. function get_all_process 傳回程序名稱清單字元串"nginx httpd mysql datanode"
  2. function get_all_group 傳回程序組清單字元串
  3. function get_process_info(該函數可以接收一個參數,參數為程序名稱) 傳回程序詳細資訊清單字元串,詳細資訊包括:運作狀态、PID、CPU、MEM、啟動時間
  4. function get_all_process_by_group 傳回程序組内的所有程序名稱清單字元串
例子:DB組--> "mysql postgresql oracle"
           

3. 功能函數

  • process.cfg
[GROUP_LIST]
WEB
DB
HADOOP
YARN

[WEB]
nginx
httpd

[DB]
mysql
postgresql
oracle

[HADOOP]
datanode
namenode
journalnode

[YARN]
resourcemanager
nodemanager

[nginx]
description="Web Server 1"
program_name=tail
parameter=-f /root/lesson/9.1/tmp/web-nginx.conf

[httpd]
description="Web Server 2"
program_name=tail
parameter=-f /root/lesson/9.1/tmp/web-httpd.conf

[mysql]
description="High Performance DataBase"
program_name=tail

           
  1. function get_all_group 傳回程序組清單字元串
vim app_status.sh

#!/bin/bash
#
# Func: Get Porcess Status In process.cfg

# Define Variables
HOME_DIR="/root/lesson/9.1"
CONFIG_FILE="process.cfg"

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

groups=`get_all_group`

echo $groups
           
  1. function get_all_process 傳回程序名稱清單字元串
  2. function get_process_info(注:該函數可以接收一個參數,參數為程序名稱) 傳回程序詳細資訊清單字元串,詳細資訊包括:運作狀态、PID、CPU、MEM、啟動時間
  3. function get_all_process_by_group 傳回程序組内的所有程序名稱清單字元串(例子:DB組–> “mysql postgresql oracle”
vim app_status.sh

#!/bin/bash
#
# Func: Get Porcess Status In process.cfg

# Define Variables
HOME_DIR="/root/lesson/9.1"
CONFIG_FILE="process.cfg"
this_pid=$$

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

function get_all_process
{
    for g in `get_all_group`
    do
        P_LIST=`sed -n "/\[$g\]/,/\[.*\]/p" $HOME_DIR/$CONFIG_FILE | egrep -v "(^$|\[.*\])"`
        echo "$P_LIST"
    done
}

function get_process_pid_by_name #process_name
{
    if [ $# -ne 1 ];then
        return 1
    else
        pids=`ps -ef | grep $1 | grep -v grep | grep -v $0 | awk '{print $2}'`
        echo $pids
    fi
}

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

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

function get_all_process_by_group
{
    is_group_in_config $1
    if [ $? -eq 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
}

if [ !-e $HOME_DIR/$CONFIG_FILE ];then
    echo "$CONFIG_FILE is not exist..please check.."
    exit 1
fi
           

4. 程式主流程設計

./app_status.sh 執行有三種情況:

  1. 無參數 列出配置檔案中所有程序的運作資訊
  2. -g GroupName 列出GroupName組内的所有程序
  3. process_name1 列出指定程序的運作資訊
#說明:該函數無需輸入任何參數;傳回配置檔案 process.cfg中所有的組資訊,例如WEB、DB等
function get_all_group

#說明:該函數無需輸入任何參數;傳回配置檔案 process.cfg 中所有的程序資訊。
function get_all_process

#說明:該函數接收一個參數,參數為程序名稱;傳回值是一個PID的清單,可能有一個PID,也可能有多個
function get_process_pid_by_name

#說明:該函數接收一個參數,參數為程序PID;傳回值是一個程序運作資訊的清單,清單包含運作狀态、CPU占用率、記憶體占用率、程序啟動時間
function get_process_info_by_pid

#說明:該函數接收一個參數,參數為組的名稱;傳回值是0或1,0代表該組在配置檔案中,1代表該組不在配置檔案中
function is_group_in_config

#說明:該函數接受一個參數,參數為組名稱;傳回值是對應組内的所有程序名稱清單
function get_all_process_by_group

#說明:該函數接收一個參數,參數是一個程序名稱;傳回值是一個組名
function get_group_by_process_name

#說明:該函數接收兩個參數,第一個參數為process_name,第二個參數為組名稱;傳回值是針對每一個程序PID的運作資訊
funcion format_print

#說明:該函數接收一個參數,參數為程序名稱;傳回值是0或1,0代表該程序在配置檔案中,1代表程序不在配置檔案中
function is_process_in_config
           
vim app_status.sh

#!/bin/bash
#
# Func: Get Porcess Status In process.cfg

# Define Variables
HOME_DIR="/root/lesson/9.1"
CONFIG_FILE="process.cfg"
this_pid=$$

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

function get_all_process
{
    for g in `get_all_group`
    do
        P_LIST=`sed -n "/\[$g\]/,/\[.*\]/p" $HOME_DIR/$CONFIG_FILE | egrep -v "(^$|\[.*\])"`
        echo "$P_LIST"
    done
}

function get_process_pid_by_name #process_name
{
    if [ $# -ne 1 ];then
        return 1
    else
        pids=`ps -ef | grep $1 | grep -v grep | grep -v $0 | awk '{print $2}'`
        echo $pids
    fi
}

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

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

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_all_process_by_group
{
    is_group_in_config $1
    if [ $? -eq 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 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
                echo "$gn"
            fi
        done
    done
}

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_status=$pro_status \
                -v p_pid=$pid \
                -v p_cpu=$pro_cpu \
                -v p_mem=$pro_mem \
                -v p_start_time="$pro_start_time" \
                'BEGIN{printf "%-10s%-12s%-5s%-5s%-5s%-5s%-15s\n",p_name,g_name,p_status,p_pid,p_cpu,p_mem,p_start_time}'
        done
    else
        awk -v p_name=$1 -v g_name=$2 'BEGIN{printf "%-10s%-12s%-5s%-5s%-5s%-5s%-15s\n",p_name,g_name,"STOPED","NULL","NULL","NULL","NULL"}'
    fi
}

awk 'BEGIN{printf "%-20s%-10s%-10s%-6s%-7s%-10s%-20s\n","ProcessName---------","GroupName---","Status----","PID---","CPU----","MEMORY----","StartTime---"}'

if [ $# -gt 0 ];then
    if [ "$1" == "-g" ];then
        shift
        for gn in [email protected];do
            is_group_in_config $gn || continue
            for pn in `get_all_process_by_group $gn`;do
                is_process_in_config $pn && format_print $pn $gn
            done
        done
    else
        for pn in [email protected];do
            gn=`get_group_by_process_name $pn`
            is_process_in_config $pn && format_print $pn $gn
        done
    fi
else
    for pn in `get_all_process`;do
        gn=`get_group_by_process_name $pn`
        is_process_in_config $pn && format_print $pn $gn
    done
fi
           

繼續閱讀