守护进程是一个在后台运行并且不受任何终端控制的进程(守护进程独立于所有终端,之所以脱离于终端是为了避免进程被任何终端所产生的信息所打断,其在执行过程中的信息也不在任何终端上显示。)
二、守护进程的作用
守护进程是一类在后台执行,生命周期较长的进程,它一般随系统启动运行,在系统关闭的时候停止。所以守护进程一般用作系统后台服务。
三、如何编写一个守护进程
编写守护进程实际上是把一个普通进程按照守护进程的特性进行改造。
守护进程的开发涉及到子进程、进程组、会晤期、信号量、文件权限、目录和控制终端等多个概念。
由于守护进程是脱离控制终端的,因此首先创建子进程,终止父进程,使得程序在shell终端里造成一个已经运行完毕的假象。之后所有的工作都在子进程中完成,而用户在shell终端里则可以执行其他的命令,从而使得程序以僵尸进程形式运行,在形式上做到了与控制终端的脱离。
四、python 编写守护进程
参考: https://cloud.tencent.com/developer/article/1411989
**1、编写守护进程的步骤 **
创建守护进程其实和c创建守护进程的方式大同小异了,其实就是那么几个步骤:
2、定义一个Daemon类,有其他人写好的标准类,可以直接引用
**3、写一个测试的守护进程,每隔两秒向文件中写入数据 **
测试程序先写一个测试程序,用于输出日志和打印到控制台。
#-*- coding: utf-8 -*-
import logging
import time
from logging.handlers import RotatingFileHandler
def func():
init_log()
while True:
print "output to the console"
logging.debug("output the debug log")
logging.info("output the info log")
time.sleep(3)
def init_log():
logging.getLogger().setLevel(logging.DEBUG)
console = logging.StreamHandler()
console.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s')
console.setFormatter(formatter)
logging.getLogger().addHandler(console)
# add log ratate
Rthandler = RotatingFileHandler("backend_run.log", maxBytes=10 * 1024 * 1024, backupCount=100,
encoding="gbk")
Rthandler.setLevel(logging.INFO)
# formatter = logging.Formatter('%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s')
Rthandler.setFormatter(formatter)
logging.getLogger().addHandler(Rthandler)
if __name__ == '__main__':
func()
后台启动Python脚本
可以使用下面的命令来启动上面的脚本,让Python在后台运行。
nohup python -u main.py >test.out 2>&1 &
来解释一下这几个命令的参数。这一段来自
其中 0、1、2分别代表如下含义:
0 – stdin (standard input)
1 – stdout (standard output)
2 – stderr (standard error)
nohup python -u main.py >test.out 2>&1 &
nohup+最后面的&是让命令在后台执行
>out.log 是将信息输出到out.log日志中
2>&1 是将标准错误信息转变成标准输出,这样就可以将错误信息输出到out.log 日志里面来。
运行命令后,会返回一个pid。像下面这样:
[1] 9208
后续可以学习Hadoop它们,把pid存起来,到时候stop的时候就把它杀掉。
跟踪输出文件变化
为了验证脚本可以在后台继续运行,我们退出当前会话。然后重新连接一个Session,然后输入下面的命令来跟踪文件的输出:
tail -f test.out
输出内容如下:
output to the console
2017-03-21 20:15:02,632 main.py[line:11] DEBUG output the debug log
2017-03-21 20:15:02,632 main.py[line:12] INFO output the info log
output to the console
2017-03-21 20:15:05,635 main.py[line:11] DEBUG output the debug log
2017-03-21 20:15:05,636 main.py[line:12] INFO output the info log
output to the console
2017-03-21 20:15:08,637 main.py[line:11] DEBUG output the debug log
2017-03-21 20:15:08,638 main.py[line:12] INFO output the info log
output to the console
2017-03-21 20:15:11,640 main.py[line:11] DEBUG output the debug log
2017-03-21 20:15:11,642 main.py[line:12] INFO output the info log
output to the console
2017-03-21 20:15:14,647 main.py[line:11] DEBUG output the debug log
2017-03-21 20:15:14,647 main.py[line:12] INFO output the info log
output to the console
2017-03-21 20:15:17,653 main.py[line:11] DEBUG output the debug log
2017-03-21 20:15:17,654 main.py[line:12] INFO output the info log
output to the console
2017-03-21 20:15:20,655 main.py[line:11] DEBUG output the debug log
2017-03-21 20:15:20,656 main.py[line:12] INFO output the info log
output to the console
2017-03-21 20:15:23,661 main.py[line:11] DEBUG output the debug log
2017-03-21 20:15:23,661 main.py[line:12] INFO output the info log
output to the console
2017-03-21 20:15:26,665 main.py[line:11] DEBUG output the debug log
2017-03-21 20:15:26,666 main.py[line:12] INFO output the info log
output to the console
2017-03-21 20:15:29,670 main.py[line:11] DEBUG output the debug log
2017-03-21 20:15:29,671 main.py[line:12] INFO output the info log
说明我们的脚本确实在后台持续运行。
结束程序
可以直接通过之前的那个pid杀掉脚本,或者可以通过下面的命令查找pid。
ps -ef | grep python
输出的内容如下:
root 1659 1 0 17:40 ?00:00:00 /usr/bin/python /usr/lib/python2.6/site-packages/ambari_agent/AmbariAgent.py start
root 1921 1659 0 17:40 ?00:00:48 /usr/bin/python /usr/lib/python2.6/site-packages/ambari_agent/main.py start
user 8866 8187 0 20:03 ?00:00:06 /usr/bin/python3 /usr/bin/update-manager --no-update --no-focus-on-map
root 9208 8132 0 20:12 pts/16 00:00:00 python -u main.py
root 9358 8132 0 20:17 pts/16 00:00:00 grep --color=auto python
可以看到我们的pid是9208,调用kill杀掉就可以了。
kill -9 9208
编写启动及停止脚本
启动脚本
#!/bin/sh
pid=`ps -ef|grep "python -u main.py"| grep -v "grep"|awk '{print $2}'`
if [ "$pid" != "" ]
then
echo "main.py already run, stop it first"
kill -9 ${pid}
fi
echo "starting now..."
nohup python -u main.py >test.out 2>&1 &
pid=`ps -ef|grep "python -u main.py"| grep -v "grep"|awk '{print $2}'`
echo ${pid} >pid.out
echo "main.py started at pid: "${pid}
停止脚本
#!/bin/sh
pid=`ps -ef|grep "python -u main.py"| grep -v "grep"|awk '{print $2}'`
if [ "$pid" != "" ]
then
kill -9 ${pid}
echo "stop main.py complete"
else
echo "main.py is not run, there's no need to stop it"
fi
稍后我会把实例代码上传到资料共享里面。