终于来了个重量级的,returner这东西简直是个神器啊。再也不用盯着管理端的屏幕看了,直接用returner这东西,把返回的结果同时保存在文件或者数据库里面一份。

returner支持很多输出,比如各种各样的数据库,mysql,redis,monggodb。也支持输入到文件,或者/var/local/syslog里面。

returner的工作过程是咋样的呢?楼主根据自己的实践总结了一下

1。其实,也就是当我们把自定义的returner同步到minion上面去后,

2.然后我们在master上执行一些操作,并指定return的对象,比如salt '*' cmd.run 'ls' --return mysql

3.这个时候,master上面发送过来的命令会在,mininon上面执行。minion上执行完命令后,产生一个结果,在salt里面这个结果用ret表示,

4.这个结果一方面会按照通常的方式返回给master并在master的屏幕上面输出打印。

5.另一方面,ret这个结果会传给我们自定义的returner,然后在minion端执行returner,

6.执行returner产生的结果就是把最终的结果导入文件或者数据库,这个和returner里面怎么写有关了。

7.第二方面怎么玩,和master就不搭嘎了。

8.注意:咱们returner里面咱们定义的文件或者数据库都是相对于minion来说,比如说我们把结果写入文件/tmp/returner里面,这个/tmp/returner是minion上面的,而不是在master上面的。楼主调试这个功能的时候,开始没搞清这层关系,吃了不小哦亏。

9.其实,returner可以任意的定义,我们在里面定义了啥,它就可以干什么活,比如我们可以定义

邮件,短信报警模块等等

官方地址:

https://github.com/saltstack/salt/blob/develop/salt/returners/mysql.py

我们先测试一下return接口是否能够正常使用。同时看一下,我们自定义的returner究竟接受到什么样的数据?

自定义returner默认路径是/srv/salt/_returners

mkdir /srv/salt/_returners

看一下测试returner

root@salt-master:~# cat /srv/salt/_returners/local.py 
from __future__ import print_function
def returner(ret):
    print(ret)
root@salt-master:~#

好了,这个时候,咱们为了看得清楚点。到minion上面,以debug的模块启动minion

root@salt-client:~# /etc/init.d/salt-minion 
Usage: /etc/init.d/salt-minion {start|stop|status|restart|force-reload}
root@salt-client:~# /etc/init.d/salt-minion stop
[ ok ] Stopping salt minion control daemon: salt-minion.
root@ansible:~# salt-minion  -l debug

OK,master端同步一下returners

root@salt-master:~# salt '*' saltutil.sync_returners           
salt-client:
root@salt-master:~# salt '*'  cmd.run   'hostname'  --return    local  
salt-client:
    salt-client
root@salt-master:~#

到minion端看一下debug的信息。看到了没,大括号里面的东西,就是minion执行完毕后,返回给master

或者返回给returner的东西。结构都是这个样子的

大伙应该都看得懂,jid,函数名,函数参数,等等信息

[INFO    ] Returning information for job: 20140624162233869962
{'fun_args': ['hostname'], 'jid': '20140624162233869962', 'return': 'ansible', 
'retcode': 0, 'success': True, 'fun': 'cmd.run', 'id': 'ansible'}

好了,这个东西出来了说明咱们的returner是木有问题的。

下面看一下,怎么把结果return到文件或者日志里面吧

先看看文件吧

楼主的returner代码
root@salt-master:~# cat /srv/salt/_returners/file.py 
import json
import time

def returner(ret):
    now = time.localtime() 
    now = time.strftime("%Y-%m-%d %H:%M:%S",now)
    result_file = '/tmp/returner'
    result = file(result_file,'a+')
    result.write('At'+str(json.dumps(now))+'\n')
    result.write(str(json.dumps(ret))+'\n')
    result.close()
    
同步一下returner
root@salt-master:~# salt '*' saltutil.sync_returners              
ansible:
    - returners.file
    
执行个命令并return到file
root@salt-master:~# salt '*'  cmd.run   'hostname'  --return  file
ansible:
    ansible
   
好查看一下minion上面的结果
root@salt-master:~# salt '*'  cmd.run   'cat /tmp/returner'  
ansible:
    At"2014-06-24 04:09:23"
    {"fun_args": ["hostname"], "jid": "20140624164743457542", "return": "ansible", "retcode": 0, "success": true, "fun": "cmd.run", "id": "ansible"}
    At"2014-06-24 04:09:47"
    {"fun_args": ["hostname"], "jid": "20140624164807042671", "return": "ansible", "retcode": 0, "success": true, "fun": "cmd.run", "id": "ansible"}
    At"2014-06-24 04:10:59"
    {"fun_args": ["hostname"], "jid": "20140624164918774162", "return": "ansible", "retcode": 0, "success": true, "fun": "cmd.run", "id": "ansible"}
root@salt-master:~#

OK,搞定,再看看return到syslog

看一下代码,这里用到里前几篇说过的虚拟模块
root@salt-master:~# cat /srv/salt/_returners/syslog.py 
import json
try:
    import syslog
    HAS_SYSLOG = True
except ImportError:
    HAS_SYSLOG = False

__virtualname__ = 'syslog'

def __virtual__():
    if not HAS_SYSLOG:
        return False
    return __virtualname__
def returner(ret):
    syslog.syslog(syslog.LOG_INFO, 'salt-minion: {0}'.format(json.dumps(ret)))

同步一下returner
root@salt-master:~# salt '*' saltutil.sync_returners              
ansible:
    - returners.syslog

执行个命令玩玩
root@salt-master:~# salt '*'  cmd.run   'hostname'  --return  syslog
ansible:
    ansible
看一下minion上的syslog日志。
root@salt-master:~# salt '*'  cmd.run   'grep 'jid' /var/log/syslog'
ansible:
   
 Jun 24 04:15:19 ansible salt-minion: salt-minion: {"fun_args": 
["hostname"], "jid": "20140624165338927188", "return": "ansible", 
"retcode": 0, "success": true, "fun": "cmd.run", "id": "ansible"}
root@salt-master:~#

OK,搞定,不过感觉放在syslog不太好吧,syslog还有别的很多其他的日志消息。觉得,放文件的话,最后弄个空文件放。

OK,下面该搞搞数据库,楼主只玩过mysql数据库,所以没得选择了。

这个例子基本上算是,按照官网上来的,楼主在本地跑通就这个样子。

注意:楼主的数据库是建立在master上面的,所以待会要需要远程连接

先看一下建表语句:

    CREATE DATABASE  `salt`
      DEFAULT CHARACTER SET utf8
      DEFAULT COLLATE utf8_general_ci;

    USE `salt`;
    
    DROP TABLE IF EXISTS `salt_returns`;
    CREATE TABLE `salt_returns` (
      `fun` varchar(50) NOT NULL,
      `jid` varchar(255) NOT NULL,
      `return` mediumtext NOT NULL,
      `id` varchar(255) NOT NULL,
      `success` varchar(10) NOT NULL,
      `full_ret` mediumtext NOT NULL,
      `alter_time` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
      KEY `id` (`id`),
      KEY `jid` (`jid`),
      KEY `fun` (`fun`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

看一下,returner吧

root@salt-master:~# cat /srv/salt/_returners/mysql_return.py
import json
import time
try:
    import MySQLdb
    HAS_MYSQL = True
except ImportError:
    HAS_MYSQL = False

__virtualname__ = 'mysql'

def __virtual__():
   if not HAS_MYSQL:
       return False
   else:
       return  __virtualname__
def returner(ret):
       conn=MySQLdb.connect(host='10.240.161.98',user='root',passwd='123456',db='salt',
                            port=3306)
       cursor=conn.cursor()
       sql = 'INSERT INTO salt_returns(`fun`,`jid`,`return`,`id`,`success`,`full_ret`)
             VALUES (%s,%s,%s,%s,%s,%s)'
       cursor.execute(sql % (str(json.dumps(ret['fun'])),str(json.dumps(ret['jid'])),
                      str(json.dumps(ret['return'])),str(json.dumps(ret['id'])),
                      '"'+str(ret['success'])+'"',"'"+json.dumps(ret)+"'"))
       conn.commit()
       cursor.close()
       conn.close()
root@salt-master:~#

同步并执行一下

root@salt-master:~# salt '*' saltutil.sync_returners 
salt-minion:
    - returners.mysql_return
root@salt-master:~# salt '*'    cmd.run 'ls'   --return=mysql
salt-minion:
    1
    123
    dec1.py
root@salt-master:~#

看一下数据库。

root@salt-master:~# mysql -uroot -p"123456" -e "select * from salt.salt_returns\G"
*************************** 1. row ***************************
       fun: cmd.run
       jid: 20140625105655939721
    return: 1
123
dec1.py
        id: salt-minion
   success: True
  full_ret: {"fun_args": ["ls"], "jid": "20140625105655939721", "return": "1
123
dec1.py", "retcode": 0, "success": true, "fun": "cmd.run", "id": "salt-minion"}
alter_time: 2014-06-25 10:56:55
root@salt-master:~#

ok,成功了