原文连接: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 的问题