在playbook中定义变量

在playbook中,可以直接定义变量,如下所示:

- hosts: webservers

vars:

http_port: 80

YAML陷阱

YAML语法要求如果值以{{ foo }}开头的话我们需要将整行用双引号包起来.这是为了确认你不是想声明一个YAML字典.该知识点在 YAML 语法 页面有所讲述.

这样是不行的:

- hosts: app_servers

vars:

app_path: {{ base_path }}/22

应该这么做

- hosts: app_servers

vars:

app_path: "{{ base_path }}/22"

使用Facts获取的信息

还有其它地方可以获取变量,这些变量是自动发现的,而不是用户自己设置的.

Facts通过访问远程系统获取相应的信息. 一个例子就是远程主机的IP地址或者操作系统是什么. 使用以下命令可以查看哪些信息是可用的:

ansible hostname -m setup

可以在playbook中这样引用以上例子中第一个硬盘的模型:

{{ ansible_devices.sda.model }}

同样,作为系统报告的主机名如以下所示:

{{ ansible_nodename }}

不合格的主机名显示了句号(.)之前的字符串:

{{ ansible_hostname }}

在模板和条件判断(请看 playbook_conditionals )中会经常使用Facts.

关闭Facts

- hosts: whatever

gather_facts: no

另外 ,关闭了facts,ansible执行的速度会快很多

注册变量

变量的另一个主要用途是在运行命令时,把命令结果存储到一个变量中.不同模块的执行结果是不同的.运行playbook时使用-v选项可以看到可能的结果值. 在ansible执行任务的结果值可以保存在变量中,以便稍后使用它

示例:

- hosts: web_servers

tasks:

- shell: /usr/bin/foo

register: foo_result

ignore_errors: True

- shell: /usr/bin/bar

when: foo_result.rc == 5

访问复杂变量数据

有些提供的facts,比如网络信息等,是一个嵌套的数据结构.访问它们使用简单的 {{ foo }} 语法并不够用,

当仍然很容易.如下所示:

{{ ansible_eth0["ipv4"]["address"] }}

或者这样写:

{{ ansible_eth0.ipv4.address }}

相似的,以下代码展示了我们如何访问数组的第一个元素:

{{ foo[0] }}

命令行中传递变量

如果你想编写一个通用的发布playbook时则特别有用,你可以传递应用的版本以便部署:

ansible-playbook release.yml --extra-vars "version=1.23.45 other_variable=foo"

其它场景中也很有用,比如为playbook设置主机群组或用户.

---

- hosts: '{{ hosts }}'

remote_user: '{{ user }}'

tasks:

- ...

ansible-playbook release.yml --extra-vars "hosts=vipers user=starbuck"

Ansible 1.2中你也可以给extra-vars传递JSON,比如:

--extra-vars '{"pacman":"mrs","ghosts":["inky","pinky","clyde","sue"]}'

key=value形式非常简单,但很实用!

Ansible 1.3中,实用”@”语法可以为extra-vars传递JSON文件:

--extra-vars "@some_file.json"

同样在Ansible 1.3中,我们可以为extra-vars传递YAML格式,无论直接通过命令行还是放置在文件中.

如:添加用户的剧本,用传递了json文件

---

- hosts: "{{ host }}"

 gather_facts: no

 remote_user: root

 vars:

   UserName: "{{ user }}"

   UserPassword: "{{ pass }}"

 tasks:

   - name: create new user {{ UserName }}

     user: name={{ UserName }} shell=/bin/bash  password={{ UserPassword |password_hash('sha512') }} update_password=always append=yes

   - name: Config /etc/sudoers

     lineinfile: dest=/etc/sudoers state=present  line='{{ item }}' validate='visudo -cf %s'

     with_items:

      - "{{ user }} ALL=(ALL) NOPASSWD:ALL,!/bin/rm,!/bin/su,!/usr/bin/passwd,!/usr/sbin/visudo,!/sbin/shutdown,!/sbin/reboot,!/sbin/halt"

      - "Defaults: {{ user }}  !requiretty"

ansible-playbook useradd.yml -e "host=192.168.20.110 user=zhangsan pass=12345678"

在上例中,new_pass是密码,如果new_pass里有特殊的字符,或者new_pass是一串数组的话,它将被转义。若不想被转义,可以使用如下方法:

# cat user.json

host: web                              #ansible里面定义的主机组

user: zhangsan                     #添加的用户名

pass: 'Fxx6unM$R%I$Jna&'   #添加的用户的密码,可以用百度上随机密码生成器生成

指定user,json文件执行剧本:

# ansible-playbook useradd.yml -e "@user.json"    #使用JSON格式的文件即可,-e 传递变量,优先级最高

删除web组中所有用户

# ansible web -m user -a 'name=zhangsan state=absent remove=yes'

变量的优先级: 我该在什么地方放置变量?

* extra vars (在命令行中使用 -e)优先级最高

* 然后是在inventory中定义的连接变量(比如ansible_ssh_user)

* 接着是大多数的其它变量(命令行转换,play中的变量,included的变量,role中的变量等)

* 然后是在inventory定义的其它变量

* 然后是由系统发现的facts

* 然后是 "role默认变量", 这个是最默认的值,很容易丧失优先权