背景
ansible 本身提供了很多内置模块用于完成各种功能。
这样做的好处,一是屏蔽系统差异,比如包管理,你不需要再去操心yum还是apt。(当然包名其实也不省心。)
二是面向终态的设计,避免了过程式的问题。
好处很多,可有些时候你就是不想用。
放弃吧,让 ansible shell 模块拯救你于水火。
基本用法
ad-hoc直接运行,瞬间上手。常用于一次性任务或者测试:ansible localhost -m shell -a 'ls'
play用法
支持一条、多条命令,可以通过 ignore_errors 忽略返回值,可以引用 ansible 变量。
一条命令
最基本最简单的用法,shell 后直接跟要执行的命令即可。
可以使用 &&
将多条命令连接为一条命令。
- name: Exec single shell command # 执行单条命令 |
注意:如果直接写多行,按照 ansible 语法,会被拼为一条。
- name: Exec multi line command # 这样执行的结果会打印: 1 ls umask |
多条命令
除了上面说的,使用&&
将多条命令拼接为一条命令外,还有以下办法:
- name: Exec multi line command with | |
注意:
这两种方法,都相当于bash中执行了多条命令。所以命令的stdout、stderr都会显示出来,但中间的 wrong_command 的 rc 就被吞掉了。
所以如果需要中间任意一条命令出错就退出,那么尽量使用 && 的方式。
返回值处理
返回值:
- rc: shell命令返回的code,相当于shell里面的
$?
- stdout: 标准输出
- stderr: 标准错误输出
常见用法是比较 stdout 或 stderr 是否为空。
忽略错误
默认rc不为0则报错退出,类似 set -x
。
可以通过以下方法忽略错误:
- 设置
ignore_errors
为true commands|| /bin/true
commands|| cat
command||:
注意:上述方法所有错误被忽略,比如grep结果为0和错误的命令。需要通过其它方法鉴别。
测试代码
|
执行测试
ansible-playbook -v test.yml |
注意事项
grep
grep 是最容易出错的,因为 grep 后的条数为0的话,rc不为0,默认会导致报错退出。
而很多场景下,这与我们期望相悖。
所以一般使用 grep 的场景都需要考虑下如何忽略错误。
shell比较语法
如果文件不存在,下面命令的返回值为非0:[[ -e file_not_exist.log ]] && echo "exist"
下面命令的返回值始终为0:[[ -e file_not_exist.log ]] && echo "exist" || echo "not exist"
幂等
ansible本身的思想,是面向终态,非过程式的。
而我们使用 shell 脚本的时候,尤其容易引入不幂等的操作。
那如何弥补呢?尽量先检查再执行。比如添加记录到/etc/hosts,不要简单的echo ‘xxx’ >> /etc/hosts,而应该先检查下是否已经存在再添加。