1、编写启动脚本shell
1.写一个启动脚本。bash
对mencached作启动脚本。运维
2.先把一个结构搭建好。ide
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方法。memcached
3.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文件中
3.2.测试Popen函数,能够看到执行了shell命令。测试
3.3.继续定义2个方法,一个是定义pid的绝对路径,一个是定义写入pid文件的方法。spa
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 才能够写入
3.4.start方法完整.net
3.4.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方法
4.1.stop方法的思路,判断这个程序在不在运行,若是在运行找到进程号,kill掉,并删除pid文件,若是不在运行,查看pid文件是否存在。若是存在删掉。若是都不存在,说明已经stop了
4.2.使用pidof命令能够获得程序是否在运行,而且获取到进程号,仍是调用Popen方法来运行shell的pidof命令。
4.3.定义一个获取pid的方法
def _getPid(self): #定义获取pid的方法。
p = Popen(['pidof',self.name],stdout=PIPE) #执行获取PID的命令
pid = p.stdout.read().strip() #获取到的PID分割一下,删除换行符
return pid #返回pid的值
4.4.kill进程号
使用os模块里的kill方法。
os.kill(PIDnumber,15) 通常kill的信号是15.
4.5.stop方法完整版。
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)
4.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)
4.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方式启动脚本
5.1.当咱们执行了start后若是在次执行start ,会发现pid的文件数值会改变,可是进程的pid号仍是没有改变的。这就有一个小bug了
pid = self._getPid() #获取PID
if pid: #若是有PID提示。
print("%s is running" % self.name)
sys.exit()
在start方法里加上这段代码就能够了,若是有pid提示正在运行而后退出脚本
5.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 来围绕编写的。
---------------------
做者:运维白菜鹏
来源:CSDN
原文:https://blog.csdn.net/shuaizy2017/article/details/79069790