原文連接:http://www.huangdc.com/66 html
一、什麼是 Job python
在salt 中,每次執行一次salt命令就會產生一個Job ,Salt 實時管理的任務都是做爲Job來執行的;在maste執行一次salt 命令,minion 就會產生一個惟一的 job id ,job id 能夠在minion 機器 /var/cache/salt/minion/proc/ 查看 ,咱們能夠經過 job id 獲取到job 的執行狀態等信息 linux
例如,測試環境以下: shell
master : 192.168.202.72 vim
minion : 192.168.201.37 bash
咱們在master 執行一個命令: salt '192.168.201.37' cmd.run "sh /root/dc.sh" 函數
## minion 的腳本:(爲方便測試及查看,dc.sh 腳本作了 sleep 50s) [root@localhost ~]# cat /root/dc.sh #!/bin/sh i=1 while (($i<50)) ; do echo "$i" let ++i sleep 1 done ## master 執行: [root@local200-72 ~]# salt '192.168.201.37' cmd.run "sh /root/dc.sh" ## minion 查看: [root@localhost ~]# ll /var/cache/salt/minion/proc/ total 8 -rw-r--r-- 1 root root 113 Aug 8 15:11 20150808231316960508
二、Job 經常使用管理命令 測試
(1)saltutil 模塊中的 job管理⽅法 https://docs.saltstack.com/en/develop/ref/modules/all/salt.modules.saltutil.html spa
saltutil.running #查看minion當前正在運⾏的jobs code
saltutil.find_job <jid> #查看指定jid的job(minion正在運⾏的jobs)
saltutil.signal_job <jid> <single> #給指定的jid進程發送信號
saltutil.term_job <jid> #終⽌指定的jid進程(信號爲15)
saltutil.kill_job <jid> #終⽌指定的jid進程(信號爲9)
## salt '*' saltutil.signal_job <job id> 15
(2)salt runner 中的job管理⽅法 https://docs.saltstack.com/en/develop/topics/jobs/index.html
salt-run jobs.active #查看全部minion當前正在運⾏的jobs(在全部minions上運⾏saltutil.running)
salt-run jobs.lookup_jid <jid> #從master jobs cache中查詢指定jid的運⾏結果
salt-run jobs.list_jobs #列出當前master jobs cache中的全部job
(3)runner 模塊獲取job 狀態信息
import salt.runner opts = salt.config.master_config('/etc/salt/master') runner = salt.runner.RunnerClient(opts) runner.cmd('jobs.lookup_jid', [str(job_id)])
三、簡單實例
(1)在master 執行一個命令: salt '192.168.201.37' cmd.run "sh /root/dc.sh" ; 並查看job 的狀態
## master 窗口1執行: [root@local200-72 ~]# salt '192.168.201.37' cmd.run "sh /root/dc.sh" ## master 窗口2查看: [root@local200-72 ~]# salt-run jobs.active 20150808232959218377: ---------- Arguments: - sh /root/dc.sh Function: cmd.run Returned: Running: |_ ---------- 192.168.201.37: 15767 Target: 192.168.201.37 Target-type: glob User: root [root@local200-72 ~]# salt-run jobs.lookup_jid 20150808232959218377 192.168.201.37: 1 2 3 ...(省略) ## minion: [root@localhost ~]# ll /var/cache/salt/minion/proc/ total 8 -rw-r--r-- 1 root root 113 Aug 8 15:26 20150808232959218377
(2)在master 執行一個命令: salt '192.168.201.37' cmd.run "sh /root/dc.sh" ; 並在中途經過job id kill 掉這個 job
## master 窗口1執行: [root@local200-72 ~]# salt '192.168.201.37' cmd.run "sh /root/dc.sh" ## minion:查看 job id [root@localhost ~]# ll /var/cache/salt/minion/proc/ total 8 -rw-r--r-- 1 root root 113 Aug 8 15:44 20150808234707827791 [root@localhost ~]# ps -ef |grep dc.sh root 16986 16985 0 15:44 ? 00:00:00 sh /root/dc.sh [root@localhost ~]# ps -ef |grep 16985 root 16985 1 0 15:44 ? 00:00:00 /usr/bin/python2.6 /usr/bin/salt-minion -d root 16986 16985 0 15:44 ? 00:00:00 sh /root/dc.sh ## master 查看執行 kill [root@local200-72 ~]# salt '192.168.201.37' saltutil.signal_job 20150808234707827791 15 192.168.201.37: Signal 15 sent to job 20150808234707827791 at pid 16985 ## minion 繼續查看 進程及job id [root@localhost ~]# ps -ef |grep dc.sh root 16986 1 0 15:44 ? 00:00:00 sh /root/dc.sh [root@localhost ~]# ll /var/cache/salt/minion/proc/ total 0 ## 細心的朋友會發現,當咱們在master 執行命令調用其餘腳本的時候, saltutil.signal_job 把 job id kill 掉了,可是以前此 job 調用的腳本,並無被kill 掉 (爲何呢)
四、Job 管理中的 signal_job 問題(如上問題)
當咱們在master 執行命令調用其餘腳本的時候, saltutil.signal_job 把 job id kill 掉了,可是以前此 job 調用的腳本,並無被kill 掉 。
(1)linux 中,子進程及父進程的問題 , 咱們能夠來測試一下 linux 中是如何kill 掉進程及父進程的
經過a.sh 腳本調用 dc.sh (dc.sh 如上不變) , a.sh 以下:
測試1 , kill 命令
[root@localhost ~]# cat a.sh #!/bin/sh sh /root/dc.sh echo "xx" [root@localhost ~]# sh a.sh & [root@localhost ~]# ps -ef |grep a.sh root 17559 14095 0 15:52 pts/2 00:00:00 sh a.sh [root@localhost ~]# ps -ef |grep 17559 root 17559 14095 0 15:52 pts/2 00:00:00 sh a.sh root 17560 17559 0 15:52 pts/2 00:00:00 sh /root/dc.sh [root@localhost ~]# kill 17559 [root@localhost ~]# ps -ef |grep 17559 root 17633 17569 0 15:52 pts/3 00:00:00 grep 17559 [root@localhost ~]# ps -ef |grep dc.sh root 17560 1 0 15:52 pts/2 00:00:00 sh /root/dc.sh ## 一樣,當kill 掉 父進程的id 17559 後, 子進程 dc.sh 仍然在運行 (發現父進程是被kill掉了,可是子進程還活着,並且PPID已經換成爲1,也就是init(1)進程)
測試2 , kill -9 命令 (測試結果同上)
說明: kill 通常只能殺掉單個進程,一樣,咱們也能夠發送信號給進程組
好,測試3,kill -- -<gpid> (kill 掉進程組) ( 注意 兩個橫線<空格>一個橫線<gpid>)
查看組進程ID : ps efo pid,pgid,ppid,comm
好了,終於把 父進程和 子進程都kill 掉了,,,問題又來了,,,爲何 salt saltutil.signal_job 並無把 子進程也kill 掉呢?
(2)修改 minion 的 /usr/lib/python2.6/site-packages/salt/modules/saltutil.py 模塊代碼
咱們來看一下 salt saltutil 模塊的代碼:/usr/lib/python2.6/site-packages/salt/modules/saltutil.py
[root@local200-72 modules]# vim /usr/lib/python2.6/site-packages/salt/modules/saltutil.py ... (前面省略) ## 咱們直接來看一下 signal_job 函數的代碼,下面我加了註釋 def signal_job(jid, sig): ''' Sends a signal to the named salt job's process CLI Example: .. code-block:: bash salt '*' saltutil.signal_job <job id> 15 ''' for data in running(): if data['jid'] == jid: try: os.kill(int(data['pid']), sig) ## 這個地方,你會發現 saltutil 只是使用kill 命令,因此沒法kill 掉子進程 ; ## 但你往下看代碼,你會發現 saltutil 是有去kill child_pids ,我測試後發現,data['child_pids'] 的值是爲空的; 有就是說 salt並無獲取到 child_pids 。 因此 沒法kill 掉子進程。 ## 好了,緣由咱們知道了,咱們應該如何修改呢,固然能夠修改salt的saltutil 模塊代碼 ## 解決方法 使用 os.killpg(gpid,sig) ## 將上面的 os.kill(int(data['pid']), sig) 修改成 os.killpg(os.getpgid(int(data['pid'])),sig) 便可 if 'child_pids' in data: for pid in data['child_pids']: os.kill(int(pid), sig) return 'Signal {0} sent to job {1} at pid {2}'.format( int(sig), jid, data['pid'] ) except OSError: path = os.path.join(__opts__['cachedir'], 'proc', str(jid)) if os.path.isfile(path): os.remove(path) return ('Job {0} was not running and job data has been ' ' cleaned up').format(jid) return '' ... (後面省略)
好了,問題終於解決了,,,
總結,這裏簡單描述一下 salt job 的管理及遇到saltutil.signal_job 的問題