salt advanced topic

salt高级话题

  1. salt job管理

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    // job概念
    slat每次运行任务时都会将作业任务发布到pub-sub总线,minion会对任务做出响应.为区分不同任务,salt-master每次发布一个任务都会为该任务创建一个jobid,不同的jobid对应一个独立的操作任务,master端默认会缓存24小时内的所有job详细操作

    master 缓存目录: /var/cache/salt/master/jobs
    minion 缓存目录: /var/cache/salt/minion/proc,创建以jobid为名的文件,文件内容是对本次任务的缓存,任务执行完后文件会被删除.使用"strings /var/cache/salt/minion/proc/2017080912124243524"进行查看缓存文件内容

    例如:
    在master上长时间执行一个命令:
    [root@saltserver ~]# salt '*' cmd.run 'sleep 1000;echo hello'
    在minion上查看:
    [root@saltminion ~]# ls /var/cache/salt/minion/proc/20170807162006823661
    /var/cache/salt/minion/proc/20170807162006823661
    [root@saltminion ~]# strings /var/cache/salt/minion/proc/20170807162006823661
    tgt_type
    glob
    20170807162006823661
    user
    root
    sleep 1000;echo hello
    cmd.run


    // 管理job
    通过 salt-run 命令来管理job,这种方式其实是通过runner系统对job进行管理;另一种管理job的方式是通过 saltutil模块

    例如: 执行过程中 中断
    [root@saltserver ~]# salt '*' cmd.run 'sleep 1000;echo hello'
    ^C
    Exiting gracefully on Ctrl-c
    This job's jid is: 20170807162218636420
    The minions may not have all finished running and any remaining minions will return upon completion. To look up the return data for this job later, run the following command:
    salt-run jobs.lookup_jid 20170807162218636420

    综上,我们看到jobid是20170807162218636420
    在minion上查看:
    [root@saltminion ~]# ls /var/cache/salt/minion/proc/20170807162218636420
    /var/cache/salt/minion/proc/20170807162218636420

    通过saltutil进行查看:
    [root@saltserver ~]# salt '*' saltutil.find_job 20170807162218636420
    192.168.13.187:
    ----------
    arg:
    - sleep 1000;echo hello
    fun:
    cmd.run
    jid:
    20170807162218636420
    pid:
    30823
    ret:
    tgt:
    *
    tgt_type:
    glob
    user:
    root

    通过kill指令杀死job:
    [root@saltserver ~]# salt '*' saltutil.kill_job 20170807162218636420
    192.168.13.187:
    Signal 9 sent to job 20170807162218636420 at pid 30823

    查看master上cache的所有job:
    [root@saltserver ~]# salt '*' saltutil.runner jobs.list_jobs
  2. runner系统

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    前面通过salt master通过执行模块管理salt minion,除此之外,salt还为我们提供了runners系统,runner和salt的模块类似,不同点是salt的模块在minion上执行,runner在sat master上执行,而salt master可以在任意minion执行任务.
    所以,通过runner可以控制不同minion的执行顺序,这一点是state模块无法做到的.通过salt-run可以调用salt的runner功能

    //minion管理
    探测主机是否存活:
    [root@saltserver ~]# salt '*' test.ping
    192.168.13.187:
    True
    通过runner也可以达到同样效果,不同的是runner不需要匹配目标minion:
    [root@saltserver ~]# salt-run manage.up
    - 192.168.13.187
    这条命令实质上是runner调用master并对所有minion进行test.ping,不同的是runner只在master上执行,没有和任何minion进行通信

    [root@saltserver ~]# salt-run manage.down
    这条命令也是通过master对所有minion调用test.ping函数,然后和已经注册的minion做比较,找出现在已经不能连接的minion,然后进行输出

    //job管理
    查看所有和job管理相关的命令:
    [root@saltserver ~]# salt-run -d |grep job

    列出24小时内所有job:
    [root@saltserver ~]# salt-run jobs.list_jobs

    查看某一个特定的job:
    [root@saltserver ~]# salt-run jobs.list_job 20170807162218636420

    //orchestrate
    runner可以控制不同minion的执行顺序,runner有一项功能用于管理多台minion的状态:orchestrate runner.
    例如:
    [root@saltserver ~]# vim /srv/salt/orch.sls
    mysql_mod:
    salt.state:
    - tgt: 'minion-one'
    - tgt_type: list
    - sls: mysql
    web_mod:
    salt.state:
    - tgt: 'minion-two'
    - tgt_type: list
    - sls: httpd
    - require:
    - salt: mysql_mod

    执行:
    [root@saltserver ~]# salt-run state.orchestrate orch

    综上,通过这样的模块顺序控制使得minion-one必须先安装mysql后,才能让minion-two再安装httpd
  3. event系统和reactor系统

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    343
    344
    345
    346
    347
    348
    349
    350
    351
    352
    353
    354
    355
    356
    357
    358
    359
    360
    361
    362
    363
    364
    365
    366
    //event系统
    event是salt通信的核心,每一个event可以认为是salt的一个执行单元,比job要宽泛,job可以看成一种特殊的event

    例如: 写一个脚本用于监听master的event
    * 编写脚本:
    [root@saltserver ~]# vim eventlisten.py
    #-*- coding:utf-8 -*-
    """
    This script is a generic tool to test event output
    """

    # import python libs
    from __future__ import absolute_import,print_function
    import optparse
    import pprint
    import time
    import os

    # import salt libs
    import salt.utils.event

    # import 3rd-party libs
    import salt.ext.six as six

    def parse():
    """
    Parse the script command line inputs
    """
    parser = optparse.OptionParser()
    parser.add_option(
    '-s',
    '--sock-dir',
    dest='sock_dir',
    default='/var/run/salt',
    help=('statically define the directory holding the salt unix sockets for communication')
    )
    parser.add_option(
    '-n',
    '--node',
    dest='node',
    default='master',
    help=('state if this listener will attach to a master or a minion daemon,pass "master" or "minion"')
    )
    parser.add_option(
    '-f',
    '--func_count',
    default='',
    help=('Return a count of the number of minions which hava replied to a job with a ggiven func.')
    )
    parser.add_option(
    '-i',
    '--id',
    default='',
    help=('if connection to a live master or minion,pass in the id')
    )
    parser.add_option(
    '-t',
    '--transport',
    default='zeromq',
    help=('Transport to use. Default:\'zeromq\'')
    )

    options, args = parser.parse_args()

    opts = {}

    for k,v in six.iteritems(options.__dict__):
    if v is not None:
    opts[k] = v

    opts['sock_dir'] = os.path.join(opts['sock_dir'],opts['node'])

    if 'minion' in options.node:
    if args:
    opts['id'] = args[0]
    return opts
    if options.id:
    opts['id'] = options.id
    else:
    opts['id'] = options.node
    return opts

    def check_access_and_print_warning(sock_dir):
    """
    check if this user is able to access the socket directory and print a warning if not
    """
    if (os.access(sock_dir,os.R_OK) and
    os.access(sock_dir,os.W_OK) and
    os.access(sock_dir,os.X_OK)):
    return
    else:
    print('Warning: Events will not be reported "(not able to access {0})".format(sock_dir)')


    def listen(opts):
    """
    attach to the pub socket and grab messges
    """
    event = salt.utils.event.get_event(
    opts['node'],
    sock_dir = opts['sock_dir'],
    transport = opts['transport'],
    opts = opts,
    listen = True
    )
    check_access_and_print_warning(opts['sock_dir'])
    print(event.puburi)
    jid_counter = 0
    found_minions = []
    while True:
    ret = event.get_event(full=True)
    if ret is None:
    continue
    if opts['func_count']:
    data = ret.get('data',False)
    if data:
    if 'id' in six.iterkeys(data) and data.get('id',False) not in found_minions:
    if data['fun'] == opts['func_count']:
    jid_counter += 1
    found_minions.append(data['id'])
    print('Reply received from [{0}]. Total replies now:[{1}].'.format(ret['data']['id'],jid_counter))
    continue
    else:
    print('Event fired at {0}'.format(time.asctime()))
    print('*' * 25)
    print('Tag: {0}'.format(ret['tag']))
    print('Data:')
    pprint.pprint(ret['data'])

    if __name__ == '__main__':
    opts = parse()
    listen(opts)

    * 在salt-master上执行脚本:
    [root@saltserver ~]# python eventlisten.py
    /var/run/salt/master/master_event_pub.ipc

    * 在打开一个salt-master终端进行执行:
    [root@saltserver ~]# salt '*' test.ping
    192.168.13.187:
    True

    * 在salt-master上查看输出信息:
    [root@saltserver ~]# python eventlisten.py
    /var/run/salt/master/master_event_pub.ipc
    Event fired at Tue Aug 8 10:06:47 2017
    *************************
    Tag: 20170808100647714897
    Data:
    {'_stamp': '2017-08-08T02:06:47.715514', 'minions': ['192.168.13.187']}
    Event fired at Tue Aug 8 10:06:47 2017
    *************************
    Tag: salt/job/20170808100647714897/new
    Data:
    {'_stamp': '2017-08-08T02:06:47.716171',
    'arg': [],
    'fun': 'test.ping',
    'jid': '20170808100647714897',
    'minions': ['192.168.13.187'],
    'tgt': '*',
    'tgt_type': 'glob',
    'user': 'root'}
    Event fired at Tue Aug 8 10:06:47 2017
    *************************
    Tag: salt/job/20170808100647714897/ret/192.168.13.187
    Data:
    {'_stamp': '2017-08-08T02:06:47.797479',
    'cmd': '_return',
    'fun': 'test.ping',
    'fun_args': [],
    'id': '192.168.13.187',
    'jid': '20170808100647714897',
    'retcode': 0,
    'return': True,
    'success': True}

    综上,event输出包含两部分:
    部分一: tag,类似于一个url
    salt/job/20170808100647714897/new
    这条tag从左到右说明了:类型,任务ID,任务标识
    部分二: 数据字典,包含:时间戳,调用函数,jid,minion信息



    //salt为我们提供了event.send模块可自定义event,例如:
    * 在master端执行
    [root@saltserver ~]# python eventlisten.py
    /var/run/salt/master/master_event_pub.ipc
    * 在minion端执行
    [root@saltminion ~]# salt-call event.send myco/mytag foo=Foo bar=Bar
    local:
    True
    * 在master端查看
    [root@saltserver ~]# python eventlisten.py
    /var/run/salt/master/master_event_pub.ipc
    Event fired at Tue Aug 8 10:21:41 2017
    *************************
    Tag: salt/auth
    Data:
    {'_stamp': '2017-08-08T02:21:41.187922',
    'act': 'accept',
    'id': '192.168.13.187',
    'pub': '-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnZHnTfGzMpKiNqPmwM1Q\nrgnRGSrA8eNghWRBECq+raT3qG99xvY7sjP1at8Ul/fnEMCC/K1W4CJz/6TN2lG/\n1jVh77zk9W/PbABGv5i00ZpmxZBtgNywRj4wL9IPPDmalSqm13HnjnVQ7+1I4MK7\naQDmkihGWynSh5U/CGLpApWNowcGw2Xui0d3jdrhGjngvmFuwooCLHlXDOXE3kLY\n1/5oE1+NpM4+6Hbg09XQ6wXtAnM7zNW1GFBfuNTh9ZymkicUso8uqZXCH2dUrf+e\n8VViFb01jBOBgThXm4hmqyF+NfbrjlFmcfSMJ73pJBC1VvmfQ4+F9oSksJGVufkl\n7QIDAQAB\n-----END PUBLIC KEY-----',
    'result': True}
    Event fired at Tue Aug 8 10:21:41 2017
    *************************
    Tag: minion/refresh/192.168.13.187
    Data:
    {'Minion data cache refresh': '192.168.13.187',
    '_stamp': '2017-08-08T02:21:41.311715'}
    Event fired at Tue Aug 8 10:21:41 2017
    *************************
    Tag: myco/mytag
    Data:
    {'_stamp': '2017-08-08T02:21:41.396306',
    'cmd': '_minion_event',
    'data': {'__pub_fun': 'event.send',
    '__pub_jid': '20170808102141379062',
    '__pub_pid': 31706,
    '__pub_tgt': 'salt-call',
    'bar': 'Bar',
    'foo': 'Foo'},
    'id': '192.168.13.187',
    'tag': 'myco/mytag'}
    Event fired at Tue Aug 8 10:21:41 2017
    *************************
    Tag: salt/job/20170808102141404168/ret/192.168.13.187
    Data:
    {'_stamp': '2017-08-08T02:21:41.405667',
    'arg': ['myco/mytag', 'foo=Foo', 'bar=Bar'],
    'cmd': '_return',
    'fun': 'event.send',
    'fun_args': ['myco/mytag', 'foo=Foo', 'bar=Bar'],
    'id': '192.168.13.187',
    'jid': '20170808102141404168',
    'retcode': 0,
    'return': True,
    'tgt': '192.168.13.187',
    'tgt_type': 'glob'}

    综上,我们看到新产生的event的tag正是我们自己触发的Event.我们既然可以获取这么多的Event,如果能对这些event做定制化的相应会使salt更加灵活强大. salt为我们设计了Reactor系统,可以对event做出相应


    //reactor系统
    reactor分两部分来配置:
    部分一: 在master配置文件中,定义哪些event触发哪些reactor文件
    部分二: reactor的SLS配置文件,定义对事件作出相应时采取哪些操作

    例如:(修改master配置)
    * 修改master配置文件
    [root@saltserver ~]# vim /etc/salt/master
    reactor:
    - 'myco/*':
    - salt://reactor.sls

    * 重启salt-master
    [root@saltserver ~]# pkill salt-master
    [root@saltserver ~]# salt-master -c /etc/salt -d

    * 定义reactor.sls文件
    [root@saltserver ~]# vim /srv/salt/reactor.sls
    my_first_reactor:
    local.cmd.run:
    - tgt: '192.168.13.187'
    - arg:
    - 'touch /tmp/my_first_reactor'

    * 在master上执行
    [root@saltserver ~]# python eventlisten.py
    /var/run/salt/master/master_event_pub.ipc

    * 在minion上执行
    [root@saltminion ~]# salt-call event.send myco/mytag foo=Foo bar=Bar
    local:
    True

    * 在master上观察输出结果
    [root@saltserver ~]# python eventlisten.py
    /var/run/salt/master/master_event_pub.ipc
    Event fired at Tue Aug 8 10:32:51 2017
    *************************
    Tag: salt/auth
    Data:
    {'_stamp': '2017-08-08T02:32:51.543849',
    'act': 'accept',
    'id': '192.168.13.187',
    'pub': '-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnZHnTfGzMpKiNqPmwM1Q\nrgnRGSrA8eNghWRBECq+raT3qG99xvY7sjP1at8Ul/fnEMCC/K1W4CJz/6TN2lG/\n1jVh77zk9W/PbABGv5i00ZpmxZBtgNywRj4wL9IPPDmalSqm13HnjnVQ7+1I4MK7\naQDmkihGWynSh5U/CGLpApWNowcGw2Xui0d3jdrhGjngvmFuwooCLHlXDOXE3kLY\n1/5oE1+NpM4+6Hbg09XQ6wXtAnM7zNW1GFBfuNTh9ZymkicUso8uqZXCH2dUrf+e\n8VViFb01jBOBgThXm4hmqyF+NfbrjlFmcfSMJ73pJBC1VvmfQ4+F9oSksJGVufkl\n7QIDAQAB\n-----END PUBLIC KEY-----',
    'result': True}
    Event fired at Tue Aug 8 10:32:51 2017
    *************************
    Tag: minion/refresh/192.168.13.187
    Data:
    {'Minion data cache refresh': '192.168.13.187',
    '_stamp': '2017-08-08T02:32:51.669152'}
    Event fired at Tue Aug 8 10:32:51 2017
    *************************
    Tag: myco/mytag
    Data:
    {'_stamp': '2017-08-08T02:32:51.755789',
    'cmd': '_minion_event',
    'data': {'__pub_fun': 'event.send',
    '__pub_jid': '20170808103251736557',
    '__pub_pid': 31742,
    '__pub_tgt': 'salt-call',
    'bar': 'Bar',
    'foo': 'Foo'},
    'id': '192.168.13.187',
    'tag': 'myco/mytag'}
    Event fired at Tue Aug 8 10:32:51 2017
    *************************
    Tag: salt/job/20170808103251765140/ret/192.168.13.187
    Data:
    {'_stamp': '2017-08-08T02:32:51.768086',
    'arg': ['myco/mytag', 'foo=Foo', 'bar=Bar'],
    'cmd': '_return',
    'fun': 'event.send',
    'fun_args': ['myco/mytag', 'foo=Foo', 'bar=Bar'],
    'id': '192.168.13.187',
    'jid': '20170808103251765140',
    'retcode': 0,
    'return': True,
    'tgt': '192.168.13.187',
    'tgt_type': 'glob'}
    Event fired at Tue Aug 8 10:32:51 2017
    *************************
    Tag: 20170808103251827538
    Data:
    {'_stamp': '2017-08-08T02:32:51.829254', 'minions': ['192.168.13.187']}
    Event fired at Tue Aug 8 10:32:51 2017
    *************************
    Tag: salt/job/20170808103251827538/new
    Data:
    {'_stamp': '2017-08-08T02:32:51.829749',
    'arg': ['touch /tmp/my_first_reactor'],
    'fun': 'cmd.run',
    'jid': '20170808103251827538',
    'minions': ['192.168.13.187'],
    'tgt': '192.168.13.187',
    'tgt_type': 'glob',
    'user': 'root'}
    Event fired at Tue Aug 8 10:32:51 2017
    *************************
    Tag: salt/auth
    Data:
    {'_stamp': '2017-08-08T02:32:51.890407',
    'act': 'accept',
    'id': '192.168.13.187',
    'pub': '-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnZHnTfGzMpKiNqPmwM1Q\nrgnRGSrA8eNghWRBECq+raT3qG99xvY7sjP1at8Ul/fnEMCC/K1W4CJz/6TN2lG/\n1jVh77zk9W/PbABGv5i00ZpmxZBtgNywRj4wL9IPPDmalSqm13HnjnVQ7+1I4MK7\naQDmkihGWynSh5U/CGLpApWNowcGw2Xui0d3jdrhGjngvmFuwooCLHlXDOXE3kLY\n1/5oE1+NpM4+6Hbg09XQ6wXtAnM7zNW1GFBfuNTh9ZymkicUso8uqZXCH2dUrf+e\n8VViFb01jBOBgThXm4hmqyF+NfbrjlFmcfSMJ73pJBC1VvmfQ4+F9oSksJGVufkl\n7QIDAQAB\n-----END PUBLIC KEY-----',
    'result': True}
    Event fired at Tue Aug 8 10:32:51 2017
    *************************
    Tag: salt/job/20170808103251827538/ret/192.168.13.187
    Data:
    {'_stamp': '2017-08-08T02:32:51.984504',
    'cmd': '_return',
    'fun': 'cmd.run',
    'fun_args': ['touch /tmp/my_first_reactor'],
    'id': '192.168.13.187',
    'jid': '20170808103251827538',
    'retcode': 0,
    'return': '',
    'success': True}

    * 在minion上查看
    [root@saltminion ~]# ls -1 /tmp/my_first_reactor
    /tmp/my_first_reactor
  4. salt api

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    salt 提供了大量的 python API 来供第三方程序调用,这些python API可以让我们将Salt强大的功能通过几行代码嵌入到自己的脚本和程序中来完成复杂的任务

    // salt配置文件信息获取
    >>> import salt.config
    >>> master_opts = salt.config.client_config('/etc/salt/master')
    >>> master_opts

    >>> minion_opts = salt.config.client_config('/etc/salt/minion')
    >>> minion_opts

    // salt loader API
    通过Loader API我们加载salt的执行模块,还可以获取salt的grains等数据信息
    >>> import salt.config
    >>> import salt.loader
    >>> __opts__ = salt.config.minion_config('/etc/salt/minion')
    >>> __grains__ = salt.loader.grains(__opts__)
    >>> __grains__

    加载执行模块:
    >>> import salt.config
    >>> import salt.loader
    >>> __opts__ = salt.config.minion_config('/etc/salt/minion')
    >>> __salt__ = salt.loader.minion_mods(__opts__)
    >>> __salt__['cmd.run']("ls /")

    //LocalClient
    LocalClient是最常用的Salt API之一,通过LocalClient的cmd等方法我们可以实现salt执行远程模块的功能
    * 用local.cmd批量执行远程模块
    >>> import salt.client
    >>> local = salt.client.LocalClient()
    >>> local.cmd('*','test.fib','10')
    * 用local.cmd_async批量异步执行远程模块
    >>> import salt.client
    >>> local = salt.client.LocalClient()
    >>> local.cmd_async('*','test.sleep',[30])
    '20170808104645529446'
    [root@saltserver ~]# salt-run jobs.list_job 20170808104645529446
    Arguments:
    - 30
    Function:
    test.sleep
    Minions:
    - 192.168.13.187
    Result:
    ----------
    192.168.13.187:
    ----------
    return:
    True
    StartTime:
    2017, Aug 08 10:46:45.529446
    Target:
    *
    Target-type:
    glob
    User:
    root
    jid:
    20170808104645529446