Shell脚本监控程序运行情况(重启程序)

Shell脚本监控程序运行情况(重启程序)

使用Linux系统时经常需要监控程序运行情况,比如最近我遇到了一个情况就是一个控制程序偶尔会在运行中退出,在这种情况下我需要立即重启该程序。最后在谢枫同学脚本的基础上完成了重启脚本。
目前遇见了两种情况: 一是程序是一个可执行文件; 二是使用python打开的多个程序。两种的区别在哪里呢?对于前者,它的进程名字由路径名字和程序名字组成,比如:
我有个程序是qt生成的可执行文件,名字为Manipulator,路径是/home/mk90/Documents/qt_exercise/build-Manipulator-Desktop-Debug
输入命令**(命令的含义在下面再解释)**

ps -ef | grep Manipulator|grep -v grep

结果是

mk90     20604 18895  0 19:11 ?        00:00:00 /home/mk90/Documents/qt_exercise/build-Manipulator-Desktop-Debug/Manipulator

对于后者,他的进程名字既有python字眼,又有程序名字,但是没有路径。比如有一个test.py程序,使用

python test.py

打开程序,然后在打开一个新的终端输入:

ps -ef | grep python|grep -v grep
或者
ps -ef | grep test.py|grep -v grep

都能得到结果:

mk90      3345  3307  0 21:12 pts/1    00:00:00 python test.py

如果使用上面的那条指令,在有多个python程序运行时,显示的进程名字都以python开头,如:
Shell脚本监控程序运行情况(重启程序)_第1张图片
这时候就需要判断是哪一个python进程了。

一、监控的程序是一个可执行文件

还以上面的Manipulator程序为例,其shell脚本为:
restart.sh

#! /bin/bash

while true 
do
	monitor=`ps -ef | grep Manipulator | grep -v grep | wc -l ` 
	if [ $monitor -eq 0 ] 
	then
		echo "Manipulator program is not running, restart Manipulator"
		./home/mk90/Documents/qt_exercise/build-Manipulator-Desktop-Debug/Manipulator
	else
		echo "Manipulator program is running"
	fi
	sleep 5
done

脚本解释:
#! /bin/bash :其中#!为Sha-bang符号,是shell脚本的起始符号,告诉Linux系统这个文件需要指定解释器; /bin/bash 指明了解释器所在的路径,对于一般的shell脚本而言,解释器可以是bash,也可以是sh。
while … do … done : shell脚本里while循环的用法

	monitor=`ps -ef | grep Manipulator | grep -v grep | wc -l ` 

上面这一句的作用是把后面指令运行的结果赋值给monitor,注意等号“=”前后不要有空格表示赋值,如果有空格则表示判断是否相等。
注意符号 ` 不是单引号 ’ ,位置是数字键1左边的那个键,上面是~,下面是它,它叫反引号或者又叫后引号,这个引号包围的为命令,可以执行包围的命令,并将执行的结果赋值给变量。
ps -ef 指令中ps的意思是process status,即进程状态, -ef 是ps命令的选项,表示以详细格式显示所有进程内容。
竖线 “ | ” 称为管道符号,是Linux系统一个很强大的功能,表示把前一个命令的输出结果传递给后一个命令处理。
grep(global search regular expression(RE) and print out the line,全面搜索正则表达式并把行打印出来)是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹配的行打印出来。后面的Manipulator是要搜索的关键字。
grep -v grep : 其中 -v 是grep命令的选项,表示反向选择,这几个字符表示在前面搜索结果的基础上去除掉带有grep关键字的内容。 因为使用 ”grep+关键字“ 命令搜索时会有一个grep本身的进程,而且带有搜索的关键字,这个就是要排除自身搜索的影响。
wc -l : wc命令统计指定文件中的字节数、字数、行数,并将统计结果显示输出。选项 ”-l “ 表示统计行数。

综合起来这句指令的意思就是:

以详细格式查看所有进程,从中选出具有关键字 Manipulator 的进程,但是排除掉用于查找的grep自身进程,对于满足上面条件的结果,统计其行数,也就是看有几个带有Manipulator关键字的进程,将统计的结果赋值给变量monitor 。

if…then…else…fi : shell脚本里面 if 语句的用法, fi 符号与 if 符号成对使用,表示 if 语句的结束。
if [ $monitor -eq 0 ] : if 语句的判断用 test 或者 “[ ]” ,符号” $“ 表示取变量的值, -eq表示等于, -gt大于, -lt小于, -ge大于等于,-le小于等于。
echo :用于输出显示。

./home/mk90/Documents/qt_exercise/build-Manipulator-Desktop-Debug/Manipulator

用于运行Manipulator程序。

sleep 5 : 休眠5秒钟。

二、对使用python打开的多个程序的监控

因为知道自己想要监控的程序的具体名字,所以对于这一类程序的监控也可以用上面的方法,但是这一类情况也让我们思索另一种方法进行监控。
在我的 /home/mk90/Documents/restart_pro 文件夹里有 test.py 和 test2.py 两个python程序,现在我要看这两个程序是否已经打开,如果没有就打开它们。

multi_restart.sh

#!/bin/bash

declare -a Array

while(true)
do
	echo -e `date`
	Array[0]=0
	Array[1]=1

	Array[0]=`pgrep python | sed -n 1p | awk '{print $1}'`
	Array[1]=`pgrep python | sed -n 2p | awk '{print $1}'`

	if [ ${Array[0]} ]
	then
		echo -e "test.py is running!"
	else
		echo -e "test.py is not running and restart it"
		gnome-terminal -x bash -c "python /home/mk90/Documents/restart_pro/test.py; exec bash"
	fi

	if [ ${Array[1]} ]
	then
		echo -e "test2.py is running!"
	else
		echo -e "test2.py is not running and restart it"
		gnome-terminal -x bash -c "python /home/mk90/Documents/restart_pro/test2.py; exec bash"
	fi

	#clear
	echo -e "\n"
	sleep 1

done

里面有很多内容在前面的例子里讲过了,需要解释的有以下几点:
declare -a Array : 表示声明了一个数组 Array
echo -e date : 用来打印日期和时间,参数 -e表示激活转义字符,详细可以参考
https://www.cnblogs.com/karl-python/p/9261920.html

pgrep python | sed -n 1p | awk '{print $1}

这句指令包含的内容较多
pgrep 是通过程序的名字来查询进程的工具;
sed是一个很好的文件处理工具,本身是一个管道命令,主要是以行为单位进行处理,可以将数据行进行替换、删除、新增、选取等特定工作,详细用法可以参考
https://blog.csdn.net/zhushuai1221/article/details/53114178
sed -n 1p : 的作用就是对前面查找的结果,读取第一行,同样 sed -n 2p 就是读取第二行 ;
awk '{print $1}’ : awk命令通常是将所列出的行,根据条件打印出某一列或几列,这里就是打印以空格为分隔符的第一列(其实也只有一列,因为pgrep命令只输出进程的pid号;

那么

	Array[0]=`pgrep python | sed -n 1p | awk '{print $1}'`
	Array[1]=`pgrep python | sed -n 2p | awk '{print $1}'`

两条指令的意思就是,查看名为python的进程,把查到的第一个进程的pid号赋值给Array[0],把第二个赋值给Array[1];
后面的判断就是只要有进程pid号,说明进程存在,否则进程不存在。

		gnome-terminal -x bash -c "python /home/mk90/Documents/restart_pro/test2.py; exec bash"

这句代码的意思就是打开一个新的终端,执行命令 ”python /home/mk90/Documents/restart_pro/test2.py“,执行完毕后该终端保持存在不关闭。
gnome-terminal 是终端的一种,Ubuntu系统的终端就是这种版本, 参数 -x 表示后面出现的都当做命令执行,并且只执行一次;
bash 是防止终端立即关闭,如果输入:

gnome-terminal -x ls

终端执行后会一闪就关闭,甚至看不到执行的效果;
"-c"选项使shell解释器从一个字符串中而不是从一个文件中读取并执行shell命令;
exec bash 使终端运行命令后仍然存在。
缺陷:
用这种方法有一个缺陷,就是需要知道会有几个python程序以及它们的的顺序;如果有两个的话,操作第二个是正常的,可以重启,但是如果第一个程序死了,也会重启第二个程序!!!因为第一个进程中断之后,系统实时监测,第二个进程变成了最前面的也是唯一的python进程,那么它认为第一个程序还在运行,而第二个程序停止了,所以会重启第二个程序。
这种方法仅作为思路参考吧。。。。。。

你可能感兴趣的:(shell,Linux,shell,脚本,监控,重启)