rc腳本的編寫,普通和daemon模式啓動

rc腳本的編寫,普通和daemon模式啓動

一、編寫啓動腳本

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方法。

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命令。

1.jpg

3.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 纔可以寫入


3.4.start方法完整

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命令。

2.jpg

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.jpg

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

版權聲明:本文爲博主原創文章,轉載請附上博文鏈接!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章