Ansible playbooks

playbook是由一个或多个“play”组成的列表。play的主要功能在于将事先归并为一组的主机装扮成事先通过ansible中的task定义好的角色。从根本上来讲,所谓task无非是调用ansible的一个module。将多个play组织在一个playbook中,即可以让它们联同起来按事先编排的机制同唱一台大戏。下面是一个简单示例。

- hosts: webnodes    //webnodes定义一个主机组,表示应用的目标主机。下面定义的任务只对此组内的主机生效

vars:   //这里是一个键值对,vars是键,它的值是一个字典

http_port: 80

max_clients: 256

remote_user:root   //表示链接远程主机以哪个主机的身份进行

tasks:  //定义接下来要执行的任务

- name: ensure apache is at the latest version  //第一个任务,

yum: name=httpd state=latest                         //基于yum模块安装httpd程序包

- name: ensure apache is running                    //第二个任务

service: name=httpd state=started                 //基于service模块启动httpd服务

handlers:

- name: restart apache

service: name=httpd state=restarted

1、playbook基础组件

1.1 Hosts和Users

playbook中的每一个play的目的都是为了让某个或某些主机以某个指定的用户身份执行任务。hosts用于指定要执行指定任务的主机(这些主机一定是在Inventory定义的主机),其可以是一个或多个由冒号分隔主机组;remote_user则用于指定远程主机上的执行任务的用户。如上面示例中的

- hosts: webnodes

remote_user: root

不过,remote_user也可用于各task中。也可以通过指定其通过sudo的方式在远程主机上执行任务,其可用于play全局或某任务;此外,甚至可以在sudo时使用sudo_user指定sudo时切换的用户。

编写playbooks定义了hosts和users之后,接下来就是定义任务列表。任务可以有多个,所以每一个都要使用“-”引导。

在playbooks中一个剧本应用于不同主机上操作有很多,所以每一个主机组都应该使用"-"来引导

- hosts: webnodes

remote_user: mageedu

tasks:

- name: test connection

ping:

remote_user: dongshi   //此tasks中定义了在远程主机主机上执行任务的用户,这里的优先级最高,不再使用全局中定义的remote_user。

sudo: yes   //表示以dongshi用户的身份切入到远程主机上,以dongshi这个用户的身份sudo到root用户在远程主机来运行命令,这样做的好处是在管控端保存的普通用户身份、                      //权限信息在遭到泄露时不知道导致太大的风险。

基本结构:

- host:websrvs

remote_user:

tasks:      //play的主题部分

- task1    //在所有主机上完成第一个任务,才开始在所有主机上执行第二个任务

module_name:module_args

- task2

1.2 任务列表和action

play的主体部分是task list。task list中的各任务按次序逐个在hosts中指定的所有主机上执行,即在所有主机上完成第一个任务后再开始第二个。

在运行自下而下某playbook时,如果中途发生错误,所有已执行任务都可能将回滚(有些任务无法回滚),因此,在更正playbook后重新执行一次即可。

task的目的是使用指定的参数执行模块,而在模块参数中可以使用变量。模块执行是幂等的,这意味着多次执行是安全的,因为其结果均一致。

每个task都应该有其name,用于playbook的执行结果输出,建议其内容尽可能清晰地描述任务执行步骤。如果未提供name,则action的结果将用于输出。

定义task的可以使用“action: module options”或“module: options”的格式,推荐使用后者以实现向后兼容。如果action一行的内容过多,也中使用在行首使用几个空白字符进行换行。

tasks:

- name: make sure apache is running

service: name=httpd state=running

在众多模块中,只有command和shell模块仅需要给定一个列表而无需使用“key=value”格式,例如:

tasks:

- name: disable selinux      //变量后的":"与值用空格隔开

command: /sbin/setenforce 0

如果某个命令或脚本运行失败,退出码不为零的情况下,可能会阻止playnook继续向后运行,为了避免此情况的出现,可以在某个命令运行结束以后,可以强行让它输出正确的信息。

可以使用如下方式替代:

tasks:

- name: run this command and ignore the result

shell: /usr/bin/somecommand || /bin/true          //此处命令执行成功了,就返回0,如果执行不成功就返回true,所以不会阻止后面的命令继续执行

或者使用ignore_errors来忽略错误信息:

tasks:

- name: run this command and ignore the result

shell: /usr/bin/somecommand

ignore_errors: True     //即使出错无不管不问,继续向后运行。

示例:在3台被管控主机上都创建系统组叫nginx,创建用户也叫nginx

# vim nginx.yml     //由哪个用户的身份在哪些主机上运行什么样的任务

- hosts: websrvs     //定义主机组
remote_user: root //定义用户的身份
tasks: //定义运行什么样的任务
- name: create nginx group //第一个任务。创建nginx组
group: name=nginx system=yes gid=
- name: create nginx user //第二个任务,创建nginx用户
user: name=nginx uid= group=nginx system=yes - host: dbsrvs
remote_user: root
tasks:
- name: copy file to dbsrvs
copy: src=/etc/inittab dest=/tmp/inittab.ans

# ansible-playbook nginx.yml   //执行playbook

PLAY [websrvs] ********************//首先在websrvs主机组上执行任务************************************************************************

TASK [Gathering Facts] ************//在websrvs组主机上执行任务前,每一个被管控主机首先要向管控端报告跟自身主机相关的各种变量,即facts***************
ok: [192.168.184.142]
ok: [192.168.184.143]
ok: [192.168.184.145] TASK [create nginx group] *********//创建nginx组****************************************************************************************
changed: [192.168.184.142] //显示changed表示任务执行成功。表示目标主机不处于已定义(即tasks中的定义)的目标状态,所以要对目标做修改。
changed: [192.168.184.143] //比如nginx组不存在,所以就在被管控主机上创建,就显示changed。
changed: [192.168.184.145] TASK [create nginx user] **********//创建nginx用户**************************************************************************************
changed: [192.168.184.142]
changed: [192.168.184.143]
changed: [192.168.184.145] PLAY [dbsrvs] **********************//然后在dbsrvs主机组上执行任务************************************************************************ TASK [Gathering Facts] ***************************************************************************************************************
ok: [192.168.184.142]
ok: [192.168.184.145] TASK [copy file to dbsrvs] ***********************************************************************************************************
changed: [192.168.184.142]
changed: [192.168.184.145] PLAY RECAP **************************//在所有任务都执行完成后,会有一个报告******************************************************************
192.168.184.142 : ok= changed= unreachable= failed= //比如1422主机上执行任务ok是的数量是5,其中包括changed和Gathering Facts,changed是3
192.168.184.143 : ok= changed= unreachable= failed= //unreached和failed都为0,表示没有执行失败的
192.168.184.145 : ok= changed= unreachable= failed=

# ansible-playbook nginx.yml    //在执行一边playbook与上面对比

PLAY [websrvs] ***********************************************************************************************************************

TASK [Gathering Facts] ***************************************************************************************************************
ok: [192.168.184.142]
ok: [192.168.184.143]
ok: [192.168.184.145] TASK [create nginx group] ************************************************************************************************************
ok: [192.168.184.145] //这里就显示ok,并不是创建nginx组ok,而是被管控主机所有的数据都存在,而且满足tasks定义的需要,就报告为ok
ok: [192.168.184.143]
ok: [192.168.184.142] TASK [create nginx user] *************************************************************************************************************
ok: [192.168.184.145]
ok: [192.168.184.143]
ok: [192.168.184.142] PLAY [dbsrvs] ************************************************************************************************************************ TASK [Gathering Facts] ***************************************************************************************************************
ok: [192.168.184.142]
ok: [192.168.184.145] TASK [copy file to dbsrvs] ***********************************************************************************************************
ok: [192.168.184.142]
ok: [192.168.184.145] PLAY RECAP ***************************************************************************************************************************
192.168.184.142 : ok= changed= unreachable= failed=
192.168.184.143 : ok= changed= unreachable= failed=
192.168.184.145 : ok= changed= unreachable= failed=

1.3 handlers 处理器

用于当关注的资源发生变化时采取一定的操作。

在一个服务的配置文件发生改变时,应该让程序重读配置文件或者重启程序。

默认情况下,多次执行一个任务的时候,如果那个任务已经执行过了,为了保持幂等性,它是不会再次执行的,所以就不可能重启。

handler就是为了解决这种问题的,它可以监控另外一个task,如果所监控的task做了某些修改,才执行指定的任务。

所以handler也是一个任务,这个任务不是上来就执行的,只有某个条件满足时才执行。

“notify”这个action可用于在每个play的最后被触发,这样可以避免多次有改变发生时每次都执行指定的操作,取而代之,仅在所有的变化发生完成后一次性地执行指定操作。

在notify中列出的操作称为handler,也即notify中调用handler中定义的操作。

- name: template configuration file      //定义的任务,配置文件

template: src=template.j2 dest=/etc/foo.conf

notify:   //如果定义的文件发生改变后就通知给另外一个任务

- restart memcached      //任务的名字,哪个任务呢?就是下面在handlers中定义的name的名字

- restart apache

handler是task列表,这些task与前述的task并没有本质上的不同。

handlers:

- name: restart memcached      //即上面notify下面任务的名字

service:  name=memcached state=restarted

- name: restart apache

service: name=apache state=restarted

上述的意思是某一个资源或配置文件发生改变后,必须要触发另外的操作时,就是用notify指明触发哪一个handler,事先把触发的操作定义好,每一个操作就叫一个handler。

示例演示

# yum install httpd -y   //确保管控主机安装了httpd

# mkdir conf

# cp /etc/httpd/conf/httpd.conf conf/    //把httpd的配置文件httpd.conf复制到创建的目录中

# vim conf/httpd.conf

Listen 8080   //让httpd监听在8080端口

# vim apache.yml

- hosts: websrvs
remote_user: root
tasks:
- name: install httpd package
yum: name=httpd state=latest
- name: install configuration file for httpd
copy: src=/root/conf/httpd.conf dest=/etc/httpd/conf/httpd.conf //把目标文件覆盖掉
- name: start httpd service
service: enabled=true name=httpd state=started

# ansible-playbook apahce.yml    //都可以执行成功

# netstat -tunlp   //在被管控主机上都可以查看到8080端口

那么问题来了,假如源配置文件src=/root/conf/httpd.conf 发生改变了,比如配置文件的监听端口改变为80,其他都不改变,那么再执行# ansible-playbook apahce.yml 后,httpd服务要不要重新启动呢?会不会根据配置文件httpd.conf的修改监听80端口呢?

# vim conf/httpd.conf    //修改配置文件,把端口修改为80

Listen 80          //让httpd监听在80端口

# ansible-playbook apache.yml     //再次执行此剧本

PLAY [websrvs] ***********************************************************************************************************************

TASK [Gathering Facts] ***************************************************************************************************************
ok: [192.168.184.143]
ok: [192.168.184.142] TASK [install httpd package] *********************************************************************************************************
ok: [192.168.184.143]
ok: [192.168.184.142] TASK [install configuration file for httpd] ******************************************************************************************
changed: [192.168.184.143] //这里的changed是因为发现httpd.conf文件中监听的端口从8080改为80,所以重新把配置文件从管控端复制到被管控端,所以发生了改变
changed: [192.168.184.142] TASK [start httpd service] ***********************************************************************************************************
ok: [192.168.184.142]
ok: [192.168.184.143] PLAY RECAP ***************************************************************************************************************************
192.168.184.142 : ok= changed= unreachable= failed=
192.168.184.143 : ok= changed= unreachable= failed=

再次查看被管控端的端口,可以看出监听的端口依然是8080端口,没有发生改变,即httpd并没有在配置文件更改后自动重启。

在一个服务的配置文件发生改变时,应该让程序重读配置文件或者重启程序。

默认情况下,多次执行一个任务的时候,如果那个任务已经执行过了,为了保持幂等性,它是不会再次执行的,所以就不可能重启。

handler就是为了解决这种问题的,它可以监控另外一个task,如果所监控的task做了某些修改,才执行指定的任务。

所以handler也是一个任务,这个任务不是上来就执行的,只有某个条件满足时才执行。

# vim apache.yml  //再次修改剧本,添加红色部分

- hosts: websrvs
remote_user: root
tasks:
- name: install httpd package
yum: name=httpd state=latest
- name: install configuration file for httpd
copy: src=/root/conf/httpd.conf dest=/etc/httpd/conf/httpd.conf
notify: //如果通知有多个,每一个要使用列表,这里虽然只有一个,但仍然使用列表进行描述。表示会触发一个事件,触发restart httpd这个处理器
- restart httpd
- name: start httpd service
service: name=httpd enabled=true state=started
handlers: //和tasks是同级别的,handlers可能有多个,每一个handler都用一个"-"来引导。handler定义方式和task是一样的,只不过handler不会直接上来就执行,只有在某个条件被触发时,才会执行
- name: restart httpd //这里要和notify定义的保持一致
service: name=httpd state=resarted

# ansible-playbook apache.yml    //再次运行此脚本,注意如果apache.yml中定义的源配置文件不发生改变,是不会触发handler的

PLAY [websrvs] ***********************************************************************************************************************

TASK [Gathering Facts] ***************************************************************************************************************
ok: [192.168.184.143]
ok: [192.168.184.142] TASK [install httpd package] *********************************************************************************************************
ok: [192.168.184.143]
ok: [192.168.184.142] TASK [install configuration file for httpd] ******************************************************************************************
changed: [192.168.184.143]
changed: [192.168.184.142] TASK [start httpd service] ***********************************************************************************************************
ok: [192.168.184.143]
ok: [192.168.184.142] RUNNING HANDLER [restart httpd] **********//这里handler已经执行*************************************************************************
changed: [192.168.184.143] //重新启动了被管控主机的httpd服务
changed: [192.168.184.142] PLAY RECAP ***************************************************************************************************************************
192.168.184.142 : ok= changed= unreachable= failed=
192.168.184.143 : ok= changed= unreachable= failed=

如何在playbook中使用变量

- hosts: webnodes

vars:   //在定义任何一个playbook的时候,可以使用vars定义变量,定义完之后可以直接引用变量

http_port: 80  //比如我们传递给playbook时的某个配置文件中来调用此变量的值即可

max_clients: 256

remote_user: root

1、示例:基于前面的修改进行演示

# vim apache.yml

- hosts: websrvs
remote_user: root
vars: //使用变量的化,在此处使用vars定义变量,变量是多个,肯定是一个序列,要用"-"来引导,
- package: httpd //pachage是变量名,httpd是变量的值,这里定义了一个报名
-
service: httpd //这里定义服务名。变量名只能包含数字、字母和下划线,而且只能以字母开头
tasks:
- name: install httpd package
yum: name={{ package }} state=latest //此处引用包名,即引用变量package的值httpd来替代
- name: install configuration file for httpd
copy: src=/root/conf/httpd.conf dest=/etc/httpd/conf/httpd.conf
notify:
- restart httpd
- name: start httpd service
service: name={{ service }} enabled=true state=started //这里同上,要用花括号{{}},注意空格
handlers:
- name: restart httpd
service: name=httpd state=restarted

# ansible-playbook apache.yml   //重新执行,毫无问题

PLAY [websrvs] ***********************************************************************************************************************

TASK [Gathering Facts] ***************************************************************************************************************
ok: [192.168.184.143]
ok: [192.168.184.142] TASK [install httpd package] *********************************************************************************************************
ok: [192.168.184.143]
ok: [192.168.184.142] TASK [install configuration file for httpd] ******************************************************************************************
ok: [192.168.184.143]
ok: [192.168.184.142] TASK [start httpd service] ***********************************************************************************************************
ok: [192.168.184.142]
ok: [192.168.184.143] PLAY RECAP ***************************************************************************************************************************
192.168.184.142 : ok= changed= unreachable= failed=
192.168.184.143 : ok= changed= unreachable= failed=

注意:在playbook中使用的变量,不仅仅有上述定义的变量,也可以是ansible中所定义的所有变量。

2、根据上述进行演示其他变量形式的使用:

# vim test.yml

- hosts: websrvs
remote_user: root
tasks:
- name: copy file
copy: content="{{ ansible_all_ipv4_addresses }}" dest=/tmp/vars.ans //copy模块在copy时指定内容有两种方式,一种是src指明,另一种是使用content直接生成。
//此时content调用的是ansible中的变量。

其中nsible_all_ipv4_addresses可以根据以下方式获得:

# ansible 192.168.184.141 -m setup | less

# ansible-playbook test.yml  //已经完成

PLAY [websrvs] ***********************************************************************************************************************

TASK [Gathering Facts] ***************************************************************************************************************
ok: [192.168.184.143]
ok: [192.168.184.142] TASK [copy file] *********************************************************************************************************************
changed: [192.168.184.143]
changed: [192.168.184.142] PLAY RECAP ***************************************************************************************************************************
192.168.184.142 : ok= changed= unreachable= failed=
192.168.184.143 : ok= changed= unreachable= failed=

# cat /tmp/vars.ans    //在被管控端的主机查看生成的内容

["192.168.184.142"]

所以有些变量不用定义就可以调用,这些变量就像ansible facts就可以实现

3、另外,在/etc/ansible/hosts的inventory中定义的主机变量也是可以直接引用的;示例如下

# vim /etc/ansible/hosts

[websrvs]
192.168.184.142 testvar=182.142
192.168.184.143 testvar=182.143

# vim test.yml

- hosts: websrvs
  remote_user: root
  tasks:
  - name: copy file
    copy: content="{{ ansible_all_ipv4_addresses }} {{ testvar }}" dest=/tmp/vars.ans

# ansible-playbook test.yml   //执行成功

PLAY [websrvs] ***********************************************************************************************************************

TASK [Gathering Facts] ***************************************************************************************************************
ok: [192.168.184.142]
ok: [192.168.184.143] TASK [copy file] *********************************************************************************************************************
changed: [192.168.184.142]
changed: [192.168.184.143] PLAY RECAP ***************************************************************************************************************************
192.168.184.142 : ok= changed= unreachable= failed=
192.168.184.143 : ok= changed= unreachable= failed=

# cat /tmp/vars.ans   //在被管控主机上查看内容

[u'192.168.184.142'] 182.142

4、ansible基于ssh连接inventory中指定的远程主机时,可以通过参数指定其交互方式,示例如下:

# vim /etc/ansible/hosts

[websrvs]
192.168.184.142 ansible_ssh_user=root ansible_ssh_pass=123456
192.168.184.143 ansible_ssh_user=root ansible_ssh_pass=dongshi

如何在playbook中使用条件测试

条件测试

如果需要根据变量、facts或此前任务的执行结果来做为某task执行与否的前提时要用到条件测试。

1.1 when语句

在task后添加when子句即可使用条件测试;when语句支持Jinja2表达式语法。例如:

tasks:

- name: "shutdown Debian flavored systems"

command: /sbin/shutdown -h now

when: ansible_os_family == "Debian"    //当ansible报告的os_family是Debian,那么就执行上面两行的任务即立刻关机

示例演示:假如被管控主机的ansible_fqdn为node2,那么就添加一个用户

# ansible 192.168.184.142 -m setup | less

# ansible 192.168.184.142 -m setup | grep fqdn

"ansible_fqdn": "node2",

# vim cond.yml  //定义yml文件

- hosts: all
remote_user: root
vars: //定义变量
- username: user1
tasks:
- name: create {{ username }} user //这里引用变量
user: name={{ username }}
when: ansible_fqdn == "node2"

# ansible-playbook cond.yml

PLAY [all] ***************************************************************************************************************************

TASK [Gathering Facts] ***************************************************************************************************************
ok: [192.168.184.143]
ok: [192.168.184.142]
ok: [192.168.184.141]
ok: [192.168.184.145] TASK [create user1 user] *************************************************************************************************************
skipping: [192.168.184.141]
skipping: [192.168.184.145]
skipping: [192.168.184.143] //凡是跳过的都不符合条件
changed: [192.168.184.142] //只有142符合条件,所以改变 PLAY RECAP ***************************************************************************************************************************
192.168.184.141 : ok= changed= unreachable= failed=
192.168.184.142 : ok= changed= unreachable= failed=
192.168.184.143 : ok= changed= unreachable= failed=
192.168.184.145 : ok= changed= unreachable= failed=

when语句中还可以使用Jinja2的大多"filter",例如要忽略此前某语句的错误并基于其结果(failed或者sucess)运行后面指定的语句,可使用类似如下形式:

tasks:

- command: /bin/false

register: result

ignore_errors: True

- command: /bin/something

when: result|failed

- command: /bin/something_else

when: result|success

- command: /bin/still/something_else

when: result|skipped

此外,when语句中还可以使用facts或playbook中定义的变量。

1.4 迭代

重复同类tasks时使用,当有需要重复性执行的任务时,可以使用迭代机制。其使用格式为将需要迭代的内容定义为item变量引用,并通过with_items语句来指明迭代的元素列表即可。例如:

- name: add several users

user: name={{ item }} state=present groups=wheel  //item是固定变量名,表示会循环的使用with_items定义的列表中的每一个元素

with_items:

- testuser1

- testuser2

上面语句的功能等同于下面的语句:

- name: add user testuser1

user: name=testuser1 state=present groups=wheel

- name: add user testuser2

user: name=testuser2 state=present groups=wheel

事实上,with_items中可以使用元素还可为hashes,例如:

- name: add several users

user: name={{ item.name }} state=present groups={{ item.groups }} //这里的item等于下文的{ name: 'testuser1', groups: 'wheel' }

with_items:

- { name: 'testuser1', groups: 'wheel' }  //item.name是引用此元素中的键name的值testuser1

- { name: 'testuser2', groups: 'root' }   //item.groups调用的是此元素中键groups的值root

ansible的循环机制还有更多的高级功能,具体请参见官方文档(http://docs.ansible.com/playbooks_loops.html)。

Templates详解

playbooks包括:

tasks

variables

templates:模板

handlers

roles

如果两个节点默认监听的端口不同,比如为websrvs组中被管控的主机安装httpd服务,在它们的配置文件中,192.168.184.142监听的是80端口,而143监听的是8080端口。另外142的配置文件中max_client=100,而143的配置文件中max_client=200,有两处不相同,因此就无法为存在多处不同的配置文件提供一次性ansible配置。这就需要配置两个ansible任务文件,但是这样管理起来很不让便。于师在这种情况下,可以尝试引用变量的方式来定义。

示例如下:

# mkdir templates   //先在根目录下创建一个存放模板的目录

# cp conf/httpd.conf templates/httpd.conf.j2   //把之前配置的httpd服务的复制到templates目录下,并以.j2结尾,表示jinja2的模板

# vim templates/httpd.conf.j2   //这个模板在复制到每一个节点时,都应该把定义在模板中的变量替换成对应的值。这种情况下,像调用的变量以及使用的jinjia2                       //的模板语言的语法,就称为模板。模板语言用的是jinjia2,支持条件判断、循环等格式,这里是把某个经常发生的变化的参数改成某个变量的值。

Listen {{ http_port }}   //把80改为变量http_port,变量会在/etc/ansible/hosts中定义,当调用httpd.conf.j2这个模板时,就会取得http_port的值

ServerName {{ ansible_fqdn }}  //定义主机名变量,每一个被管控主机在被管理事都会向管控主机报告自己的ansible facts,可以直接被调用,不需要另外定义

# vim /etc/ansible/hosts    //在此处定义模板httpd.conf.j2中的变量的值。此变量也可以在playbooks中定义,但是无法区别变量名相同而值不同。

[websrvs]
192.168.184.142 http_port=80
192.168.184.143 http_port=8080

# vim apache.yml

- hosts: websrvs
remote_user: root
vars:
- package: httpd
- service: httpd
tasks:
- name: install httpd package
yum: name={{ package }} state=latest
- name: install configuration file for httpd
template: src=/root/templates/httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf //此处是模板
notify:
- restart httpd
- name: start httpd service
service: name={{ service }} enabled=true state=started
handlers:
- name: restart httpd
service: name=httpd state=restarted

# ansible-playbook apache.yml

PLAY [websrvs] ***********************************************************************************************************************

TASK [Gathering Facts] ***************************************************************************************************************
ok: [192.168.184.143]
ok: [192.168.184.142] TASK [install httpd package] *********************************************************************************************************
ok: [192.168.184.143]
ok: [192.168.184.142] TASK [install configuration file for httpd] ******************************************************************************************
changed: [192.168.184.142] //这里被管控端的主机替换成了管控端的模板,并且把模板中的变量替换为定义的值
changed: [192.168.184.143] TASK [start httpd service] ***********************************************************************************************************
ok: [192.168.184.142]
ok: [192.168.184.143] RUNNING HANDLER [restart httpd] ******************************************************************************************************
changed: [192.168.184.142] //重启成功
changed: [192.168.184.143] PLAY RECAP ***************************************************************************************************************************
192.168.184.142 : ok= changed= unreachable= failed=
192.168.184.143 : ok= changed= unreachable= failed=

查看被管控主机的httpd配置文件,与配置模板要求的是一样的。

在一个模板文件中直接使用变量引用,它在复制到目标文件上之前会收集每一个变量,并把这个变量的值替换到模板文件中,而后把模板作为文件复制到目标主机上,所以就可以以一个文件为不同的主机提供不同的配置。

Jinja2相关

1 字面量

表达式最简单的形式就是字面量。字面量表示诸如字符串和数值的Python对象。下面的字面量是可用的:

"Hello World":

双引号或单引号中间的一切都是字符串。无论何时你需要在模板中使用一个字符串(比如函数调用、过滤器或只是包含或继承一个模板的参数),它们都是有用的。

42 / 42.23:

直接写下数值就可以创建整数和浮点数。如果有小数点,则为浮点数,否则为整数。记住在Python里,42和42.0是不一样的。

['list', 'of', 'objects']:

一对中括号括起来的东西是一个列表。列表用于存储和迭代序列化的数据。例如 你可以容易的在for循环中用列表和元组创建一个链接的列表:

<ul>

{% for href, caption in [('index.html', 'Index'), ('about.html', 'About'),

('downloads.html', 'Downloads')] %}

<li><a href="{{ href }}">{{ caption }}</a></li>

{% endfor %}

</ul>

('tuple', 'of', 'values'):

元组与列表类似,只是你不能修改元组。如果元组中只有一个项,你需要以逗号 结尾它。元组通常用于表示两个或更多元素的项。更多细节见上面的例子。

{'dict': 'of', 'key': 'and', 'value': 'pairs'}:

Python 中的字典是一种关联键和值的结构。键必须是唯一的,并且键必须只有一个 值。字典在模板中很少使用,罕用于诸如 xmlattr() 过滤器之类。

true / false:

true 永远是 true ,而 false 始终是 false 。

2 算术运算

Jinja 允许你用计算值。这在模板中很少用到,但是为了完整性允许其存在。支持下面的 运算符:

+    把两个对象加到一起。通常对象是素质,但是如果两者是字符串或列表,你可以用这 种方式来衔接它们。无论如何这不是首选的连接字符串的方式!连接字符串见 ~       运算符。 {{ 1 + 1 }} 等于 2 。

-    用第一个数减去第二个数。 {{ 3 - 2 }} 等于 1 。

/    对两个数做除法。返回值会是一个浮点数。 {{ 1 / 2 }} 等于 {{ 0.5 }} 。

//   对两个数做除法,返回整数商。 {{ 20 // 7 }} 等于 2 。

%    计算整数除法的余数。 {{ 11 % 7 }} 等于 4 。

*    用右边的数乘左边的操作数。 {{ 2 * 2 }} 会返回 4 。也可以用于重 复一个字符串多次。 {{ ‘=’ * 80 }} 会打印 80 个等号的横条。

**   取左操作数的右操作数次幂。 {{ 2**3 }} 会返回 8 。

3 比较操作符

==   比较两个对象是否相等。

!=   比较两个对象是否不等。

>    如果左边大于右边,返回 true 。

>=   如果左边大于等于右边,返回 true 。

<    如果左边小于右边,返回 true 。

<=   如果左边小于等于右边,返回 true 。

4 逻辑运算符

对于 if 语句,在 for 过滤或 if 表达式中,它可以用于联合多个表达式:

and    如果左操作数和右操作数同为真,返回 true 。

or     如果左操作数和右操作数有一个为真,返回 true 。

not    对一个表达式取反(见下)。

(expr) 表达式组。

3、Ansible playbooks(Hosts、Users、tasks、handlers、变量、条件测试(when、迭代)、templates)的更多相关文章

  1. Linuxshell脚本-格式-变量-条件测试

    1.Linuxshell脚本格式 脚本文件名称格式: 1.NAME.sh.脚本文件名称必须以 .sh 结尾 脚本编辑第一行必须包括shell声明序列:#! 添加注释,注释以#开头     2.加3执行 ...

  2. Ansible playbooks(任务、角色、模板、变色器、)

    playbooks配置文件: [root@ansible ~]# vim /etc/ansible/hosts [test01] 192.168.200.114 [test02] 192.168.20 ...

  3. Ansible Playbooks 介绍 和 使用 二

    目录 handlers playbook 案例 2 handlers vars 变量 setup facts 变量使用 案例 inventory 中定义变量 案例 条件测试 when 语句 案例 迭代 ...

  4. Ansible Playbooks 介绍 和 使用 一

    目录 Ansible Playbooks Playbooks 组成部分: YAML 介绍 YAML 语法 Ansible 基础元素 变量 facts registre 通过命令传递变量 通过roles ...

  5. Ansible 小手册系列 十一(变量)

    变量名约束 变量名称应为字母,数字和下划线. 变量应始终以字母开头. 变量名不应与python属性和方法名冲突. 变量使用 通过命令行传递变量(extra vars) ansible-playbook ...

  6. Ansible 小手册系列 十四(条件判断和循环)

    条件判断 When 语句 在when 后面使用Jinja2 表达式,结果为True则执行任务. tasks: - name: "shut down Debian flavored syste ...

  7. Ansible条件测试

    本节内容: Ansible条件测试 一.Ansible条件测试 在ansible中还可以进行条件测试.如果需要根据变量.facts或此前任务的执行结果来做为某task执行与否的前提时要用到条件测试. ...

  8. 【转】shell学习笔记(三)——引用变量、内部变量、条件测试、字符串比较、整数比较等

    1.env显示当前的环境变量 2.PS1='[\u@\h \w \A] \$' 可以设置bash的命令与提示符. 3.echo $$ 显示当前bash的PID号 4.echo $?显示上一条指令的回传 ...

  9. activiti7流程变量的测试(设置全局变量)

    package com.zcc.activiti03; import org.activiti.engine.*;import org.activiti.engine.repository.Deplo ...

随机推荐

  1. Symfony2 学习笔记之服务容器

    现在的PHP应用程序都是面向对象开发,所以主要是由对象构成.有的对象可以方便的分发邮件信息而有的可能帮你把信息写入到数据库中.在你的应用程序中,你可能创建一个对象用于管理你的产品库存,或者另外一个对象 ...

  2. [转载]Oracle 游标使用全解

    这个文档几乎包含了oracle游标使用的方方面面,全部通过了测试 -- 声明游标:CURSOR cursor_name IS select_statement --For 循环游标--(1)定义游标- ...

  3. linux 查找locate find

    1.locate locate指令和find找寻档案的功能类似,但locate是透过update程序将硬盘中的所有档案和目录资料先建立一个索引数据库,在 执行loacte时直接找该索引,查询速度会较快 ...

  4. flask框架----蓝图

    蓝图(flask中多py文件拆分都要用到蓝图) 如果代码非常多,要进行归类.不同的功能放在不同的文件,吧相关的视图函数也放进去.蓝图也就是对flask的目录结构进行分配(应用于小,中型的程序), 小中 ...

  5. 监控nginx服务

    转自:http://www.cnblogs.com/silent2012/p/5310500.html 在Nginx的插件模块中有一个模块stub_status可以监控Nginx的一些状态信息,默认安 ...

  6. ubuntu_python_environment

    参考:http://blog.csdn.net/kingppy/article/details/13080919 参考:http://blog.csdn.net/zhaobig/article/det ...

  7. Lucene的入门

    Lucene准备 Lucene可以在官网上下载,我这里已经下载好了,用的是4.10.3版本的, 解压以后的文件为: 如果没有使用maven管理的话,就需要引入这三个jar包,实现lucene功能. 我 ...

  8. ELK学习笔记之F5-HTTP-requesting-logging logstash filter

    input { tcp { port => 514 type => 'f5-request' } } filter { if [type] == "f5-request" ...

  9. K8S学习笔记之将Google的gcr.io、k8s.gcr.io 换为国内镜像

    0x00 添加docker官方的国内镜像 sudo tee /etc/docker/daemon.json <<-'EOF' { "registry-mirrors": ...

  10. Webstorm/Phpstorm中设置连接FTP,并快速进行文件比较,上传下载,同步等操作

    Phpstorm除了能直接打开localhost文件之外,还可以连接FTP,除了完成正常的数据传递任务之外,还可以进行本地文件与服务端文件的异同比较,同一文件自动匹配目录上传,下载,这些功能是平常ID ...