rc脚本的编写,普通和daemon模式启动
2018-01-15 22:53
435 查看
一、编写启动脚本
1.写一个启动脚本。
对mencached做启动脚本。
2.先把一个结构搭建好。
3.编写start方法。
1.先对_init方法进行编写。
测试Popen函数,可以看到执行了shell命令。
3.继续定义2个方法,一个是定义pid的绝对路径,一个是定义写入pid文件的方法。
4.start方法完整
1.定义start方法前,先定义了2个方法_pidFile,_writePid ,一个是定义pid文件的路径,和写入PID文件的值。
4.编写stop和status方法
1.stop方法的思路,判断这个程序在不在运行,如果在运行找到进程号,kill掉,并删除pid文件,如果不在运行,查看pid文件是否存在。如果存在删掉。如果都不存在,说明已经stop了
2.使用pidof命令可以得到程序是否在运行,并且获取到进程号,还是调用Popen方法来运行shell的pidof命令。
3.定义一个获取pid的方法
4.kill进程号
使用os模块里的kill方法。
os.kill(PIDnumber,15) 一般kill的信号是15.
5.stop方法完整版。
6.status方法思路:判断pid 是否存在,如果存在就说明在运行。不在就没运行
7.定义help方法
这就完成了一个启动脚本,但是这个启动脚本不是daemon方式运行的。
5.以daemon方式启动脚本
1.当我们执行了start后如果在次执行start ,会发现pid的文件数值会改变,但是进程的pid号还是没有改变的。这就有一个小bug了
在start方法里加上这段代码就可以了,如果有pid提示正在运行然后退出脚本
2.用daemon的方式写脚本。可以使用默认参数运行,在文件中定义参数,以定义的文件为主。完整代码如下:
这样就写好了一个以daemon方式启动的脚本。通过定义一个class,然后4个主要核心方法,start stop status restart 来围绕编写的。
1.写一个启动脚本。
对mencached做启动脚本。
2.先把一个结构搭建好。
import sys class Progames(object): # 创建一个类 def __init__(self, name, progame, workdir, args): # 通过构造函数,在脚本运行的时候就传入4个参数,就不用手动去指定参数了。 self.name = name self.progame = progame self.args = args self.workdir = workdir def _init(self): #初始化普通的方法。判断有没有目录,如果没有就创建。 def start(self): # 定义start 方法。启动程序 def stop(self): # 定义stop方法,关闭程序 def restart(self): # 定义重启方法,重启程序,也就是执行关闭和启动的方法。 self.stop() self.start() def status(self): # 定义status方法,查看运行情况 def help(self): # 定义help方法,查看帮助 def main(): # 定义一个函数,通过调用这个函数来控制程序。 name = 'memcached' #这几个参数就是调用类时初始化传入的参数 progame = '/usr/bin/memcached' workdir = '/var/tmp/memcached' args = '-u nobody -p 11211 -c 1024 -m 64' pm = Progames(name = name, progame = progame, workdir = workdir, args = args) try: #判断输入的第一个参数 类似$1 cmd = sys.argv[1] except IndexError, e: #当捕获了indexerror错误后,输出错误信息 print("Option error") sys.exit() if cmd == 'start': #如果参数为start ,调用start方法 pm.start() elif cm == 'stop': #如果参数为start ,调用stop方法 pm.stop() elif cm == 'restart': #如果参数为start ,调用restart方法 pm.restart() elif cm == 'status': #如果参数为start ,调用status方法 pm.status() else: #如果都不是以上参数,输出help信息 pm.help() if __name__ == '__main__': # 如果调用的是本身,就启动main函数。 main()
3.编写start方法。
1.先对_init方法进行编写。
def _init(self): if not os.path.exists(self.workdir): #判断文件是否存在。如果不存在,创建目录 os.mkdir(self.workdir) #不存在就创建目录, os.chdir(self.workdir) #进入目录,chdir 类似cd命令 2.调用from subprocess import PIPE,Popen 来执行shell from subprocess import PIPE,Popen def start(self): cmd = self.progame + ' '+ self.args #定义启动的命令。shell下的启动命令。 cmd = Popen(cmd,stdout=PIPE,shell=True) self.pid = p.pid #p.pid可以得到进程号。用一个对象属性接收一下,方便写入到pid文件中
测试Popen函数,可以看到执行了shell命令。
3.继续定义2个方法,一个是定义pid的绝对路径,一个是定义写入pid文件的方法。
def _pidFile(self): #判断pid文件 return os.path.join(self.workdir,"%s.pid" % self.name) #连接路径和文件名,形成pid的绝对路径 def _writePid(self): #定义写入pid值得方法。 if self.pid: #如果有pid with open(self._pidFile(),'w') as fd: #打开pid文件写入 fd.write(str(self.pid)) #得到的值是数值型的,需要转换str 才可以写入
4.start方法完整
1.定义start方法前,先定义了2个方法_pidFile,_writePid ,一个是定义pid文件的路径,和写入PID文件的值。
def _pidFile(self): #返回文件路径的方法。 return os.path.join(self.workdir,"%s.pid" % self.name) #连接路径和文件名,形成pid的绝对路径 def _writePid(self): #定义写入pid值得方法。 if self.pid: #如果有pid with open(self._pidFile(),'w') as fd: #打开pid文件写入 fd.write(str(self.pid)) #得到的值是数值型的,需要转换str 才可以写入 def start(self): # 定义start 方法。启动程序 self._init() #调用判断pid文件是否存在的方法 cmd = self.progame + ' '+ self.args #定义启动的命令。shell下的启动命令。 p = Popen(cmd,stdout=PIPE,shell=True) self.pid = p.pid self._writePid() #调用写入方法。 print("%s start sucessfull" % (self.name))
4.编写stop和status方法
1.stop方法的思路,判断这个程序在不在运行,如果在运行找到进程号,kill掉,并删除pid文件,如果不在运行,查看pid文件是否存在。如果存在删掉。如果都不存在,说明已经stop了
2.使用pidof命令可以得到程序是否在运行,并且获取到进程号,还是调用Popen方法来运行shell的pidof命令。
3.定义一个获取pid的方法
def _getPid(self): #定义获取pid的方法。 p = Popen(['pidof',self.name],stdout=PIPE) #执行获取PID的命令 pid = p.stdout.read().strip() #获取到的PID分割一下,删除换行符 return pid #返回pid的值
4.kill进程号
使用os模块里的kill方法。
os.kill(PIDnumber,15) 一般kill的信号是15.
5.stop方法完整版。
def _getPid(self): #定义获取pid的方法。 p = Popen(['pidof',self.name],stdout=PIPE) #执行获取PID的命令 pid = p.stdout.read().stri 4000 p() #获取到的PID分割一下,删除换行符 return pid #返回pid的值 def stop(self): # 定义stop方法,关闭程序 pid = self._getPid() #获取PID if pid: #如果有PID的话 os.kill(int(pid),15) #因为获取到的是一个字符串,要转换整形才可以杀死 if os.path.exists(self._pidFile()): #如果pid文件存在 os.remove(self._pidFile()) #删除文件 print("%s is stopped" % self.name)
6.status方法思路:判断pid 是否存在,如果存在就说明在运行。不在就没运行
def status(self): # 定义status方法,查看运行情况 pid = self._getPid() #判断pid是否存在 if pid: print("%s is running" % self.name) else: print("$s is not running" % self.name)
7.定义help方法
def help(self): # 定义help方法,查看帮助 print("Usage: %s {start|restart|stop|status}" % __file__) #%__file__ 类似shell的$0代表脚本本身。完整的代码:
import sys import os from subprocess import PIPE,Popen #调用shell命令行。 class Progames(object): # 创建一个类 def __init__(self, name, progame, workdir, args): # 通过构造函数,在脚本运行的时候就传入4个参数,就不用手动去指定参数了。 self.name = name self.progame = progame self.args = args self.workdir = workdir def _init(self): #初始化普通的方法。判断有没有目录,如果没有就创建。 if not os.path.exists(self.workdir): #判断文件是否存在。如果不存在,创建目录 os.mkdir(self.workdir) #不存在就创建目录, os.chdir(self.workdir) #进入目录,chdir 类似cd命令 def _pidFile(self): #返回文件路径的方法。 return os.path.join(self.workdir,"%s.pid" % self.name) #连接路径和文件名,形成pid的绝对路径 def _writePid(self): #定义写入pid值得方法。 if self.pid: #如果有pid with open(self._pidFile(),'w') as fd: #打开pid文件写入 fd.write(str(self.pid)) #得到的值是数值型的,需要转换str 才可以写入 def start(self): # 定义start 方法。启动程序 pid = self._getPid() #获取PID if pid: #如果有PID提示。 print("%s is running" % self.name) sys.exit() self._init() #调用判断pid文件是否存在的方法 cmd = self.progame + ' '+ self.args #定义启动的命令。shell下的启动命令。 p = Popen(cmd,stdout=PIPE,shell=True) self.pid = p.pid self._writePid() #调用写入方法。 print("%s start sucessfull" % (self.name)) def _getPid(self): #定义获取pid的方法。 p = Popen(['pidof',self.name],stdout=PIPE) #执行获取PID的命令 pid = p.stdout.read().strip() #获取到的PID分割一下,删除换行符 return pid #返回pid的值 def stop(self): # 定义stop方法,关闭程序 pid = self._getPid() #获取PID if pid: #如果有PID的话 os.kill(int(pid),15) #因为获取到的是一个字符串,要转换整形才可以杀死 if os.path.exists(self._pidFile()): #如果pid文件存在 os.remove(self._pidFile()) #删除文件 print("%s is stopped" % self.name) def restart(self): # 定义重启方法,重启程序,也就是执行关闭和启动的方法。 self.stop() self.start() def status(self): # 定义status方法,查看运行情况 pid = self._getPid() #判断pid是否存在 if pid: print("%s is running" % self.name) else: print("$s is not running" % self.name) def help(self): # 定义help方法,查看帮助 print("Usage: %s {start|restart|stop|status}" % __file__) #%__file__ 类似shell的$0代表脚本本身。 def main(): # 定义一个函数,通过调用这个函数来控制程序。 name = 'memcached' #这几个参数就是调用类时初始化传入的参数 progame = '/usr/bin/memcached' workdir = '/var/tmp/memcached' args = '-u nobody -p 11211 -c 1024 -m 64' pm = Progames(name = name, progame = progame, workdir = workdir, args = args) try: #判断输入的第一个参数 类似$1 cmd = sys.argv[1] except IndexError, e: #当捕获了indexerror错误后,输出错误信息 print("Option error") sys.exit() if cmd == 'start': #如果参数为start ,调用start方法 pm.start() elif cm == 'stop': #如果参数为start ,调用stop方法 pm.stop() elif cm == 'restart': #如果参数为start ,调用restart方法 pm.restart() elif cm == 'status': #如果参数为start ,调用status方法 pm.status() else: #如果都不是以上参数,输出help信息 pm.help() if __name__ == '__main__': # 如果调用的是本身,就启动main函数。 main()
这就完成了一个启动脚本,但是这个启动脚本不是daemon方式运行的。
5.以daemon方式启动脚本
1.当我们执行了start后如果在次执行start ,会发现pid的文件数值会改变,但是进程的pid号还是没有改变的。这就有一个小bug了
pid = self._getPid() #获取PID if pid: #如果有PID提示。 print("%s is running" % self.name) sys.exit()
在start方法里加上这段代码就可以了,如果有pid提示正在运行然后退出脚本
2.用daemon的方式写脚本。可以使用默认参数运行,在文件中定义参数,以定义的文件为主。完整代码如下:
import sys import os from subprocess import PIPE,Popen #调用shell命令行。 class Progames(object): # 创建一个类 args = {'USER':'memcached', #创建默认参数,所有方法都可以调用 'PORT':11211, 'MAXCONN':1024, 'CACHESIZE' : 64 'OPTIONS': ''} def __init__(self, name, progame, workdir, ): # 通过构造函数,在脚本运行的时候就传入4个参数,就不用手动去指定参数了。 self.name = name self.progame = progame self.workdir = workdir def _init(self): #初始化普通的方法。判断有没有目录,如果没有就创建。 if not os.path.exists(self.workdir): #判断文件是否存在。如果不存在,创建目录 os.mkdir(self.workdir) #不存在就创建目录, os.chdir(self.workdir) #进入目录,chdir 类似cd命令 def _pidFile(self): #返回文件路径的方法。 return os.path.join(self.workdir,"%s.pid" % self.name) #连接路径和文件名,形成pid的绝对路径 def _writePid(self): #定义写入pid值得方法。 if self.pid: #如果有pid with open(self._pidFile(),'w') as fd: #打开pid文件写入 fd.write(str(self.pid)) #得到的值是数值型的,需要转换str 才可以写入 def _readConf(self,f): #定义一个查看参数文件的方法。 with open(f) as fd: #打开参数文件 lines = readlines() #获取里面的值 return dict(i.strip().replace('"','').split('=') for i in lines) #使用列表重写的方式得到一个字典类型的值,strip去掉空格,replace替换"双引号为单引号,split 以=号来进行切割。最后的到一个字典。 def _parseArgs(self): #定义一个使用参数文件覆盖默认参数的值得方法。 conf = self._readConf('/etc/sysconfig/memcached') #定义打开的参数文件路径 if 'USER' in conf: #判断如果字典里有USER这个KEY就用参数文件里的值去替换默认参数里的值。下面也是一个意思。 self.args['USER'] = conf['USER'] if 'PORT' in conf: self.args['PORT'] = conf['PORT'] if 'MAXCONN' in conf: self.args['MAXCONN'] = conf['MAXCONN'] if 'CACHESIZE' in conf: self.args['CACHESIZE'] = conf['CACHESIZE'] options = ['-u' ,self.args['USER'], #定义启动参数 '-p',self.args['PORT]', '-m',self.args['CACHESIZE'], '-c',self.args['MAXCONN' ]] os.system('chown %s %s' % (self.args['USER'],self.workdir)) #对PID目录进行授权,可以写入文件。 return options #返回启动参数列表。 def start(self): # 定义start 方法。启动程序 pid = self._getPid() #获取PID if pid: #如果有PID提示。 print("%s is running" % self.name) sys.exit() self._init() #调用判断pid文件是否存在的方法 cmd = [self.progame] + self._parseArgs() ['-d','-P',self._pidFile()] #定义启动的命令。shell下的启动命令。 p = Popen(cmd,stdout=PIPE) #默认是false print("%s start sucessfull" % (self.name)) def _getPid(self): #定义获取pid的方法。 p = Popen(['pidof',self.name],stdout=PIPE) #执行获取PID的命令 pid = p.stdout.read().strip() #获取到的PID分割一下,删除换行符 return pid #返回pid的值 def stop(self): # 定义stop方法,关闭程序 pid = self._getPid() #获取PID if pid: #如果有PID的话 os.kill(int(pid),15) #因为获取到的是一个字符串,要转换整形才可以杀死 if os.path.exists(self._pidFile()): #如果pid文件存在 os.remove(self._pidFile()) #删除文件 print("%s is stopped" % self.name) def restart(self): # 定义重启方法,重启程序,也就是执行关闭和启动的方法。 self.stop() self.start() def status(self): # 定义status方法,查看运行情况 pid = self._getPid() #判断pid是否存在 if pid: print("%s is running" % self.name) else: print("$s is not running" % self.name) def help(self): # 定义help方法,查看帮助 print("Usage: %s {start|restart|stop|status}" % __file__) #%__file__ 类似shell的$0代表脚本本身。 def main(): # 定义一个函数,通过调用这个函数来控制程序。 name = 'memcached' #这几个参数就是调用类时初始化传入的参数 progame = '/usr/bin/memcached' workdir = '/var/tmp/memcached' pm = Progames(name = name, progame = progame, workdir = workdir) try: #判断输入的第一个参数 类似$1 cmd = sys.argv[1] except IndexError, e: #当捕获了indexerror错误后,输出错误信息 print("Option error") sys.exit() if cmd == 'start': #如果参数为start ,调用start方法 pm.start() elif cm == 'stop': #如果参数为start ,调用stop方法 pm.stop() elif cm == 'restart': #如果参数为start ,调用restart方法 pm.restart() elif cm == 'status': #如果参数为start ,调用status方法 pm.status() else: #如果都不是以上参数,输出help信息 pm.help() if __name__ == '__main__': # 如果调用的是本身,就启动main函数。 main()
这样就写好了一个以daemon方式启动的脚本。通过定义一个class,然后4个主要核心方法,start stop status restart 来围绕编写的。
相关文章推荐
- rc脚本(类的定义与脚本的结构、start方法、stop和status方法、以daemon方式启动)
- Linux 开机启动的 执行rc脚本(shell编写)的顺序
- 解析Android启动脚本init.rc && Android的启动模式
- shell学习二十三--case语句编写mysql启动脚本
- Android启动脚本init.rc
- linux启动后执行脚本(/etc/rc.local文件)
- .NET应用架构设计―表模块模式与事务脚本模式的代码编写
- linux环境下编写shell脚本启动和关闭jar包服务程序
- Android的启动脚本–init.rc
- Android启动脚本init.rc
- elipse 突然debug模式 启动不了,普通模式可以启动
- Ubuntu 创建开机启动脚本的一种方法(rc.local)
- Windows下编写批处理脚本来启动和重置Oracle数据库
- nginx在windows下的安装,以及编写启动关闭nginx等操作的脚本
- 使用 python 实现 memcached 的启动服务脚本 rc
- LNMP安装与启动脚本编写
- .NET应用架构设计—表模块模式与事务脚本模式的代码编写
- 解决selenium-RC无法启动firefox浏览器进行java测试脚本的问题
- nginx优化-使用普通用户启动nginx(监牢模式)
- 编写使用systemctl启动服务脚本