REMOTE EXECUTION
远程执行命令主要包含两个方面,moudules和returners
salt Execution Modules
salt执行模块调用系统远程执行模块执行各种任务,模块提供了安装软件包,启动服务,传输文件等。
Full list of execution modules
参考链接:https://docs.saltstack.com/en/2016.11/ref/modules/all/index.html#all-salt-modules
REMOTE EXECUTION TUTORIAL
ORDER YOUR MINIONS AROUND
远程实行命令的命令格式:
salt '<target>' <function> [arguments]
TARGET
默认使用的是minion id,也可以使用grains变量等。
示例:
1 salt -L 'foo,bar,baz,quo' test.ping 2 salt -E 'virtmach[0-9]' test.ping 3 salt -C 'G@os:Ubuntu and webser* or E@database.*' test.ping
FUNCTION
利用下面这个命令可以列出minion端支持的函数
salt '*' sys.doc
ARGUMENTS
函数执行时可以带参数:
1 salt '*' cmd.exec_code python 'import sys; print sys.version' 2 salt '*' pip.install salt timeout=5 upgrade=True
RUNNING COMMANDS ON SALT MINIONS
在saltmaster上可以以root用户在minion上执行命令,也可以通过API的方式进行通信。
USING THE SALT COMMAND
DEFINING THE TARGET MINIONS
执行远程命令需要先定义好minion标记,可以匹配一个或一组minion
1 salt '*foo.com' sys.doc 2 salt -L foo.bar.baz,quo.qux cmd.run 'ps aux | grep foo'
MORE POWERFUL TARGETS
关于匹配minion的方法有很多种,参考前面的target章节的讲解
CALLING THE FUNCTION
函数调用
示例:
1 salt '*' sys.doc 2 salt '*' cmd.exec_code python 'import sys; print sys.version' 3 salt '*' pip.install salt timeout=5 upgrade=True 4 salt '*' cmd.run 'echo "Hello: $FIRST_NAME"' saltenv='{FIRST_NAME: "Joe"}'
使用sys.doc可以看到minion端可以使用的函数,及详细使用情况.
COMPOUND COMMAND EXECUTION
复合的多函数执行
salt '*' cmd.run,test.ping,test.echo 'cat /proc/cpuinfo',,foo
使用多个函数有利于减轻通信和执行负载压力,结果以字典的形式返回,参数和函数都是以列表的形式存放,即使为空也需要一个分隔符来占用。
可以使用指定的参数分隔符
salt --args-separator=:: '*' some.fun,test.echo params with , comma :: foo
WRITING EXECUTION MODULES
salt执行模块使用salt命令来调用
MODULES ARE EASY TO WRITE!
你可以写一个python或Cpython模块放在file_roots配置环境的_modules目录下,当执行以下三条命令的时候会将自定义的模块同步到minion上。
1 state.apply 2 saltutil.sync_modules 3 saltutil.sync_all
模块的名字默认是文件名,也可以被重写,使用 __virtual__ function进行重写。
如果模块有错误不能被导入的话,将不会影响其他正常模块的导入。
Cython模块需要以.pyx进行结尾。
ZIP ARCHIVES AS MODULES
在minion的配置文件中设置enable_zip_modules为True,这样salt可以将.zip的文件导入。
模块机器依赖包需要被进行zip打包,模块名为my_module.zip。
CREATING A ZIP ARCHIVE MODULE
创建一个模块目录,用于存放该模块的依赖包和相关组件,这里以lumberjack为例:
目录结构如下:
1 modules $ ls -R lumberjack 2 __init__.py sleep work 3 4 lumberjack/sleep: 5 __init__.py 6 7 lumberjack/work: 8 __init__.py 9 10 lumberjack/__init__.py文件的内容: 11 # Libraries included in lumberjack.zip 12 from lumberjack import sleep, work 13 14 15 def is_ok(person): 16 ''' Checks whether a person is really a lumberjack ''' 17 return sleep.all_night(person) and work.all_day(person) 18 19 打包成zip: 20 zip -r lumberjack lumberjack 21 返给模块的环境目录_modules: 22 同步模块到minion并执行,示例: 23 $ sudo salt minion1 saltutil.sync_modules 24 minion1: 25 - modules.lumberjack 26 $ sudo salt minion1 lumberjack.is_ok 'Michael Palin' 27 minion1: 28 True
CROSS CALLING EXECUTION MODULES
交叉调用执行模块,以为着模块之间可以进行相互调用。
__salt__是一个字典对象包含了所有的salt函数,字典键表示模块名称的字符串,值是函数本身。
示例:
1 def foo(bar): 2 return __salt__['cmd.run'](bar)
上例就是在自己定义的foo函数中使用cmd模块,并使用传进来的参数。
CALLING EXECUTION MODULES ON THE SALT MASTER
在master端调用执行模块,参看salt returner那一节。
PRELOADED EXECUTION MODULE DATA
将多种类型的数据载入模块中,以grains为例,grains变量数据以字典的形式存放,访问的时候以字典的形式访问即可,譬如:__grains__['id']。
使用如下命令查看minion端的grains变量:
salt 'hostname' grains.items --output=pprint
STRINGS AND UNICODE
字符编码问题
python2使用的unicode编码,python3使用str字符串。
OUTPUTTER CONFIGURATION
执行模块能够返回不同格式的数据,salt可以为单个函数指定输出类型,譬如yaml,json等。
__outputter__是一个函数名和对应输出类型的字典,支持的输出类型参考链接:
https://docs.saltstack.com/en/2016.11/ref/output/all/index.html#all-salt-output
VIRTUAL MODULES
虚拟模块,可以重写一个已经存在的模块。
__VIRTUAL__ FUNCTION
__VIRTUAL__会返回一个字符串,譬如True, False,如果返回TRUE,则使用当前模块名称加载模块,如果返回false,则不会加载模块。
在模块被加载之后__virtual__被调用,在这个时间点__salt__将不可用。
RETURNING ERROR INFORMATION FROM __VIRTUAL__
从__VIRTUAL__里面获取错误信息
示例:
1 ''' 2 Cheese execution (or returner/beacon/etc.) module 3 ''' 4 try: 5 import enzymes 6 HAS_ENZYMES = True 7 except ImportError: 8 HAS_ENZYMES = False 9 10 11 def __virtual__(): 12 ''' 13 only load cheese if enzymes are available 14 ''' 15 if HAS_ENZYMES: 16 return 'cheese' 17 else: 18 return False, 'The cheese execution module cannot be loaded: enzymes unavailable.' 19 20 ''' 21 Cheese state module 22 ''' 23 24 def __virtual__(): 25 ''' 26 only load cheese if enzymes are available 27 ''' 28 # predicate loading of the cheese state on the corresponding execution module 29 if 'cheese.slice' in __salt__: 30 return 'cheese' 31 else: 32 return False, 'The cheese state module cannot be loaded: enzymes unavailable.'
OVERRIDING VIRTUAL MODULE PROVIDERS
在minion端定义被重写后的模块,这样就覆盖了salt本身提供的模块:
1 providers: 2 service: systemd 3 pkg: aptpkg
虚拟模块的列表:
https://docs.saltstack.com/en/2016.11/ref/modules/all/salt.modules.pkg.html#virtual-pkg
__VIRTUALNAME__
__virtualname__是一个变量,可以重新定义模块名。
示例:
1 # Define the module's virtual name 2 __virtualname__ = 'pkg' 3 4 5 def __virtual__(): 6 ''' 7 Confine this module to Mac OS with Homebrew. 8 ''' 9 10 if salt.utils.which('brew') and __grains__['os'] == 'MacOS': 11 return __virtualname__ 12 return False
DOCUMENTATION
salt '*' sys.doc #查看minion端的可用模块
ADDING DOCUMENTATION TO SALT MODULES
在模块中添加使用帮助文档,这应该是作为一种规范的存在。
示例:
1 def spam(eggs): 2 ''' 3 A function to make some spam with eggs! 4 5 CLI Example:: 6 7 salt '*' test.spam eggs 8 ''' 9 return eggs
ADD EXECUTION MODULE METADATA
增加模块的说明文档,设置一个较好的规范格式来展示
1 :maintainer: Thomas Hatch <thatch@saltstack.com, Seth House <shouse@saltstack.com> 2 :maturity: new 3 :depends: python-mysqldb 4 :platform: all
LOG OUTPUT
调用日志模块,打印日志.
1 log = logging.getLogger(__name__) 2 3 log.info('Here is Some Information') 4 log.warning('You Should Not Do That') 5 log.error('It Is Busted')
ALIASING FUNCTIONS
设置模块函数的别名:
1 __func_alias__ = { 2 'set_': 'set', 3 'list_': 'list', 4 }
PRIVATE FUNCTIONS
定义私有函数,以_下划线开头的函数
这样的函数会被加载到minion端:
1 def foo(bar): 2 return bar
而下面的就不会,python中定义私有方法就是以_开头的:
1 def _foobar(baz): # Preceded with an _ 2 return baz 3 4 cheese = {} # Not a callable Python object
USEFUL DECORATORS FOR MODULES
在函数中使用装饰器.
示例:
1 import logging 2 3 from salt.utils.decorators import depends 4 5 log = logging.getLogger(__name__) 6 7 try: 8 import dependency_that_sometimes_exists 9 except ImportError as e: 10 log.trace('Failed to import dependency_that_sometimes_exists: {0}'.format(e)) 11 12 @depends('dependency_that_sometimes_exists') 13 def foo(): 14 ''' 15 Function with a dependency on the "dependency_that_sometimes_exists" module, 16 if the "dependency_that_sometimes_exists" is missing this function will not exist 17 ''' 18 return True 19 20 def _fallback(): 21 ''' 22 Fallback function for the depends decorator to replace a function with 23 ''' 24 return '"dependency_that_sometimes_exists" needs to be installed for this function to exist' 25 26 @depends('dependency_that_sometimes_exists', fallback_function=_fallback) 27 def foo(): 28 ''' 29 Function with a dependency on the "dependency_that_sometimes_exists" module. 30 If the "dependency_that_sometimes_exists" is missing this function will be 31 replaced with "_fallback" 32 ''' 33 return True 34 35 36 from salt.utils.decorators import depends 37 38 HAS_DEP = False 39 try: 40 import dependency_that_sometimes_exists 41 HAS_DEP = True 42 except ImportError: 43 pass 44 45 @depends(HAS_DEP) 46 def foo(): 47 return True