进程开关实例及shell技巧

后端程序免不了经常启动、关闭和检查进程。本文简单实现这3个操作,引出一些shell技巧。

只是自己的一些经验,难免会有偏颇,不过抛砖引玉罢。

进程列表

进程列表是key-value结构,通过进程名称(key),获取其对应配置信息(value)。不像其它高级编程语言,shell原生没有key-value容器。另外列表不会很长,选择遍历列表的做法不会对性能影响太大

# 配置列表
proc_list=\
(
 loginSrv="-cfg loginSrv.cfg -ip 192.168.0.2 -port 123"
 dbSrv="-cfg dbSrc.cfg -ip 192.168.0.3 -port 456" 
)

# 通过进程名称,获取列表配置信息
function get_proc_cfg()
{
    local target=$1
    # 使用for data in ${proc_list[@]}遍历,会被第1个分隔符隔断,信息不完整
    iMax=`expr ${#proc_list[@]} - 1`
    for i in `seq 0 $iMax`
    do
        local args=${proc_list[i]}
        # 获取等号左边字符
        local key=${args%%=*}
        # 获取等号右边字符
        local value=${args#*=}
        # [[]] 运算符是[]运算符的扩充。支持字符串比较大小。支持逻辑运算符:|| &&
        if [[ $target == $key ]]; then
            # shell return只能返回[0,255]的整数
            # 如果要返回值字符串,需要用echo输出。而调用端使用$()来获取结果
            echo $value
        fi
    done
}

启动进程

根据上面的列表结构。启动时只需简单的指定进程名称(如loginSrv),通过调用get_proc_cfg,找到启动参数列表

# 假设执行程序是test
BIN=/home/root/test

function start()
{
    local KEY=$1
    # 使用$()来获取ehco的输出
    local VALUE=$(get_proc_cfg $KEY)
    # nohup指定$BIN后台运行
    nohup $BIN $VALUE &
}

# 调用示例
start "loginSrv"

停止进程

对经常使用linux的人来说,ps auxkill -9并不令他们陌生。ps aux列出当前系统进程信息,如进程ID。kill -9关闭进程。如下为例,当前选项是loginSrv的test进程ID是21750

# 显示启动的test进程
$ ps aux | grep test
root      21750  2.5  1.7 226040 68588 pts/5    Sl   17:54   7:08 /home/root/test -cfg loginSrv.cfg -ip 192.168.0.2 -port 123
root      21751  2.5  1.7 226040 68588 pts/5    Sl   17:54   7:08 /home/root/test -cfg dbSrv.cfg -ip 192.168.0.2 -port 456

# 删除ID为21750的进程。即loginSrv
$ kill -9 21750

如何准确找出进程ID,需要另一个文本处理命令awk,它默认以空格、换行符分隔字符串,按照上面例子读取变量$2(第二列)就是进程ID

function search_proc()
{
    local VALUE=$1
    # 一个命令后随字符-,会被认为是命令的选项。所以这里把首字符-去除
    VALUE=${VALUE:1}
    # 以整个选项列表过滤进程
    local PID=`ps aux | grep "\b$VALUE\b" | grep -v grep | awk '{print $2}'`
    echo $PID
}

function stop()
{
    local KEY=$1
    local VALUE=$(get_proc_cfg $KEY)

    # 查找进程ID
    local PID=$(search_proc $VALUE)
    if [ -n "$PID" ] ; then
        # 删除进程
        kill -9 $PID
    fi
}

重启进程

执行流程上无非是先stop后start。但start前必须保证,所有业务资源释放成功。否则当不允许新旧两份资源共存时,业务很可能发生逻辑错误。

function restart()
{
    local KEY=$1
    stop $KEY
    sleep 1
    start $KEY
}



实现可能千差万别,不必执着别人的做法,或者推翻现有的做法,找到适全框架的做法才是最好方案!


以下简略介绍关闭进程的另一种做法:启动进程后,利用$! 返回后台Process的PID,将其保存在磁盘。当需要关闭进程时,再从磁盘读入。

function start()
{
    # do something here 
    
    nohup $BIN $VALUE &
    # 将进程ID写入file文件 
    echo $! > file
}

function stop()
{
    # 从磁盘读入 
    local PID=`cat file`
    stop -9 $PID
}



原文:
https://lizijie.github.io/2018/03/09/%E8%BF%9B%E7%A8%8B%E5%BC%80%E5%85%B3%E5%AE%9E%E4%BE%8B%E5%8F%8Ashell%E6%8A%80%E5%B7%A7.html
作者github:
https://github.com/lizijie

PREVIOUS修复toluapp在lua5.3的整数错误
NEXT斯蒂芬·金《写作那会事》