Monit 和 shell python脚本

python脚本基本写法

1
2
3
4
5
6
7
8
9
#!/usr/bin/python
import os, time, sys
f = open('/home/hikari/MonitTest/pid/mypython.pid', 'w')
f.writelines(str(os.getpid()))
f.close()
for i in range(1,99999):
print ("Hello World!")
time.sleep(1)
~
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#!/usr/bin/python
import sys, os, time, signal
mypid = 0
mypath = "/home/hikari/Learn/pid/mypython.pid"
if len(sys.argv) >1 :
if sys.argv[1] == "start":
f = open(mypath,'w')
mypid = os.getpid()
print (mypid)
f.write(str(mypid))
f.close()
for i in range(1,100000):
print("Hello World")
time.sleep(2)
if sys.argv[1] == "stop":
if os.path.exists(mypath):
f = open(mypath,'r')
mypid = int(f.read())
f.close()
os.kill(mypid,signal.SIGKILL)
os.remove(mypath)

shell 脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#!/bin/bash

PIDFILE=/var/run/scraper.pid

case $1 in
start)
source /home
# Launch your program as a detached process
python /home/scraper.py 2>/dev/null &
# Get its PID and store it
echo $! > ${PIDFILE}
;;
stop)
kill `cat ${PIDFILE}`
# Now that it's killed, don't forget to remove the PID file
rm ${PIDFILE}
;;
*)
echo "usage: scraper {start|stop}" ;;
esac
exit 0

总结出来的一个稳定版本

monit 控制文件

1
2
3
check process shellXpython matching "/home/hikari/Learn/python/test.sh"
start program = "/home/hikari/Learn/python/test.sh"
stop program = "/home/hikari/Learn/sh/kill.sh"

tesh.sh

1
2
3
4
5
6
7
8
#!/bin/bash

{
#在shell内新建一个后台进程
python /home/hikari/Learn/python/test.py start
} &
#正常退出
exit 0

kill.sh

1
2
3
4
#!/bin/sh
pidfile=/home/hikari/Learn/pid/mypy.pid
kill `cat ${pidfile}`
exit 0

test.py

负责模拟一个长期运行的后台进程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!/usr/bin/python
import sys, os, time, signal
mypid = 0
mypath = "/home/hikari/Learn/pid/mypy.pid"
if len(sys.argv) >1 :
if sys.argv[1] == "start":
f = open(mypath,'w')
mypid = os.getpid()
print(mypid)
f.write(str(mypid))
f.close()
for i in range(1,10000):
print(i)
time.sleep(2)
if sys.argv[1] == "stop":
if os.path.exists(mypath):
f = open(mypath,'r')
mypid = int(f.read())
f.close()
os.kill(mypid,signal.SIGKILL)
os.remove(mypath)
time.sleep(99)

改进-myscript.sh

将test.sh 和 kill.sh 合并,通过输入不同参数决定调用对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!/bin/bash
PIDFILE=/var/run/myscript.pid
case $1 in
start)
source /home
# Launch your program as a detached process
python /home/hikari/Learn/python/test.py start 2>/dev/null &
# 2>/dev/null 的含义是把标准错误输出到/dev/null文件中
# Get its PID and store it
echo $! > ${PIDFILE}
;;
stop)
kill `cat ${PIDFILE}`
# Now that it's killed, don't forget to remove the PID file
rm ${PIDFILE}
;;
*)
echo "usage: myscript {start|stop}" ;;
esac
exit 0

关于program 与process的选择

在选择check服务时,process和program代表两种不同的程序。
process代表长时间工作的后台进程,在check process服务中可以接pidfile或matching,而matching可以选择文件路径。process中不能使用status。
program代表短时间内可以执行结束的程序或脚本,status只能与program配对。其原因是status是隔一段指定时间检测程序的退出值,根据退出值采取不同行动。而process要长期运行,故status属性不适用process。
program必须是短时间内可以结束的,否则一段时间后检测不到退出值,将报Execute Failed错误。原因就是程序没有结束,status检测不到程序退出值,以为程序执行失败。
据此,要在program内执行长进程要采用并发进程。假设并发进程为A,令program进程调用并发进程A & 后,立即退出,就可以达到需求。在A后面加&的效果是使A在后台运行。
至此program在短时间内得到了退出值,而长进程A也可以继续执行。