jinja2模板的使用

news2024/9/25 9:39:15

本章主要介绍在playbook中如何使用jinja2模板。

  • 什么是jinja2模板
  • 在jinja2模板文件中写if判断语句
  • 在jinja2模板文件中写for循环语句
  • handlers的使用

jinja2模板

可以使用copy模块把本地的一个文件拷贝到远端机器,下面再次复习一下。

本章实验都在/home/bdqn/demo4下操作,先把demo4目录创建出来并把ansible.cfg 和hosts拷贝进去,命令如下。 

[bdqn@rhel01 ~]$ mkdir demo4
[bdqn@rhel01 ~]$ cp ansible.cfg hosts demo4/
[bdqn@rhel01 ~]$ cd demo4/
[bdqn@rhel01 demo4]$ ls
ansible.cfg  hosts
[bdqn@rhel01 demo4]$ 

用copy拷贝一个文件到db主机组。

有一个文件aa.txt,内容如下。

[bdqn@rhel01 demo4]$ cat aa.txt 
+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+
| 我的 IP 地址是: {{ansible_default_ipv4.address}}
+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+
[bdqn@rhel01 demo4]$ 

这个文件中包含一个fact变量ansible_default_ipv4.address。 

写一个 playbook,内容如下。

[bdqn@rhel01 demo4]$ cat 1.yaml 
---
- hosts: db
  tasks:
  - name: 拷贝一个文件到远端主机
    copy: src=aa.txt dest=/opt/aa.txt
[bdqn@rhel01 demo4]$ 

运行此playbook,命令如下。 

[bdqn@rhel01 demo4]$ ansible-playbook 1.yaml 

PLAY [db] ***************************************************************************************************************************************************

TASK [Gathering Facts] **************************************************************************************************************************************
ok: [server3]
ok: [server2]

TASK [拷贝一个文件到远端主机] ******************************************************************************************************************************************
ok: [server2]
changed: [server3]

PLAY RECAP **************************************************************************************************************************************************
server2                    : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
server3                    : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

[bdqn@rhel01 demo4]$ 

现在已经把本地的aa.,txt拷贝到server2和server3的/opt目录中了。下面查看这两台主机上 /opt/aa.txt的内容,命令如下。 

[bdqn@rhel01 demo4]$ ansible db -m shell -a "cat /opt/aa.txt"
server3 | CHANGED | rc=0 >>
+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+
| 我的 IP 地址是: {{ansible_default_ipv4.address}}
+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+
server2 | CHANGED | rc=0 >>
+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+
| 我的 IP 地址是: {{ansible_default_ipv4.address}}
+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+
[bdqn@rhel01 demo4]$

可以看到,当用copy铂贝一个文件到远端机器时,如果这个文件中有变量,铂贝过去的文件中的变量并不会变成具体的值。 

如果希望文件考别过去之后,文件中的变量变成具体的值,那么就不能使用copy模块,而是要使用template模块了。 

修改1.yaml的内容如下。 

[bdqn@rhel01 demo4]$ cat 1.yaml 
---
- hosts: db
  tasks:
  - name: 拷贝一个文件到远端主机
    template: src=aa.txt dest=/opt/aa.txt
[bdqn@rhel01 demo4]$

与刚才相比,只是把copy换成了template。template模块的用法与copy模块一致,所以这里选项并没有变。运行此 playbook,命令如下。 

[bdqn@rhel01 demo4]$ ansible-playbook 1.yaml 

PLAY [db] ***************************************************************************************************************************************************

TASK [Gathering Facts] **************************************************************************************************************************************
ok: [server2]
ok: [server3]

TASK [拷贝一个文件到远端主机] ******************************************************************************************************************************************
changed: [server2]
changed: [server3]

PLAY RECAP **************************************************************************************************************************************************
server2                    : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
server3                    : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

[bdqn@rhel01 demo4]$

再次查看两台主机上/opt/aa.txt的内容,命令如下。 

[bdqn@rhel01 demo4]$ ansible db -m shell -a "cat /opt/aa.txt"
server2 | CHANGED | rc=0 >>
+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+
| 我的 IP 地址是: 192.168.23.32
+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+
server3 | CHANGED | rc=0 >>
+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+
| 我的 IP 地址是: 192.168.23.33
+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+
[bdqn@rhel01 demo4]$

可以看到,通过template拷贝含有变量的文件时,拷贝到远端机器之后,文件中的变量会变成具体的值。 

这个通过template拷贝的、含有变量的文件我们称为jinja2模板,jinja2模板文件的后缀一般使用j2,这不是必需的,但是建议使用j2作为后缀。 

修改aa.txt的文件为aa.j2 

[bdqn@rhel01 demo4]$ mv aa.txt aa.j2
[bdqn@rhel01 demo4]$

同时修改1.yaml中对应的内容,如下所示。 

[bdqn@rhel01 demo4]$ cat 1.yaml 
---
- hosts: db
  tasks:
  - name: 拷贝一个文件到远端主机
    template: src=aa.j2 dest=/opt/aa.txt
[bdqn@rhel01 demo4]$

这里如果jinja2模板文件没有写路径,例如,例子中 src=aa.j2的aa.j2没有写路径,则优先到当前目录的templates 中找aa.j2,如果没有,则到当前目录中找aa.j2. 

验证,命令如下。 

[bdqn@rhel01 demo4]$ mkdir templates
[bdqn@rhel01 demo4]$

在templates目录中创建aa.j2,内容如下。 

[bdqn@rhel01 demo4]$ cat templates/aa.j2 
+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+
| 我的主机名是: {{ansible_fqdn}}
+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+
[bdqn@rhel01 demo4]$ 

这样我们就有两个aa.j2了,还有一个是当前目录下的aa.j2,如下所示。 

[bdqn@rhel01 demo4]$ cat aa.j2 
+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+
| 我的 IP 地址是: {{ansible_default_ipv4.address}}
+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+
[bdqn@rhel01 demo4]$ 

再次运行此playbook,命令如下。 

[bdqn@rhel01 demo4]$ ansible-playbook 1.yaml 

PLAY [db] ***************************************************************************************************************************************************

TASK [Gathering Facts] **************************************************************************************************************************************
ok: [server2]
ok: [server3]

TASK [拷贝一个文件到远端主机] ******************************************************************************************************************************************
changed: [server3]
changed: [server2]

PLAY RECAP **************************************************************************************************************************************************
server2                    : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
server3                    : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

[bdqn@rhel01 demo4]$

查看两台主机上/opt/aa.txt 的内容,命令如下。 

[bdqn@rhel01 demo4]$ ansible db -m shell -a "cat /opt/aa.txt"
server2 | CHANGED | rc=0 >>
+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+
| 我的主机名是: rhel02
+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+
server3 | CHANGED | rc=0 >>
+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+
| 我的主机名是: rhel03
+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+
[bdqn@rhel01 demo4]$

这里可以看到显示的主机名,所以是 templates目录中的aa.j2生效了。 


if 判断 

在jinja2模板文件中,我们也是可以使用if判断语句的,语法格式如下。 

{% if 判断1 %} 

内容1

{% elif 判断2 %}

内容2

...多个elif...

{% else %}

内容3

{% endif %}

注意:

(1)“%”两边有没有空格都可以,不过所有的“%”前后空格要保持一致,即要有都 有,要没有都没有。

(2)if和elif中的内容如果太长了,可以另起一行写。

(3)elif和 else不是必需的。

如果判断1成立,则打印内容1,后面的条件不再判断,直接跳转到endif后面的内容;如果判断1不成立,则执行elif后面的判断2,如果成立则打印内容2,后面的条件不再判断,直接跳转到endif后面的内容。以此类推,如果所有的if和elif都不成立,则打印else中的内容。

写一个 jinja2模板文件,内容如下。 

[bdqn@rhel01 demo4]$ cat templates/bb.j2 
11111
{% if ansible_fqdn=="rhel02" %}
   {{ansible_fqdn}}
{% else %}
   aaaaa
{% endif %}
33333

[bdqn@rhel01 demo4]$

这里jinja2模板所生成的文件一共会产生3行内容,第一行的1111和最后一行的3333是必打印出来的,第二行的内容具体是什么要看情况。如果在server2上执行则显示主机名,如果在其他机器上执行则显示aaaa。 

写一个playbook,内容如下。 

[bdqn@rhel01 demo4]$ cat 2.yaml 
---
- hosts: db
  tasks:
  - name: 拷贝一个文件过去
    template: src=bb.j2 dest=/opt/bb.conf
[bdqn@rhel01 demo4]$

这里是把templates/bb.j2拷贝到两台机器的/opt中并命名为bb.conf。运行此 playbook,命令如下。

[bdqn@rhel01 demo4]$ ansible-playbook 2.yaml 

PLAY [db] *************************************************************************************************************************************************

TASK [Gathering Facts] ************************************************************************************************************************************
ok: [server2]
ok: [server3]

TASK [拷贝一个文件过去] *******************************************************************************************************************************************
changed: [server2]
changed: [server3]

PLAY RECAP ************************************************************************************************************************************************
server2                    : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
server3                    : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

[bdqn@rhel01 demo4]$ 

查看两台机器上/opt/bb.conf的内容,命令如下。 

[bdqn@rhel01 demo4]$ ansible db -m shell -a "cat /opt/bb.conf"
server3 | CHANGED | rc=0 >>
11111
   aaaaa
33333
server2 | CHANGED | rc=0 >>
11111
   rhel02
33333
[bdqn@rhel01 demo4]$

可以看到,server2的/opt/bb.conf的第二行显示的是主机名,server3的/opt/bb.conf 的第二行显示的是 aaaa。 

在if和elif后面是可以写多个判断的,用or或and作为连接符,语法如下。 

判断1 or 判断2:判断1和判断2只要有一个成立就算成立,只有全部不成立才算不成立。

判断1 and 判断2:判断1和判断2只有全部成立才算成立,只要有一个不成立就算不成立。 

查看下面的 jinja2模板文件。 

[bdqn@rhel01 demo4]$ cat templates/cc.j2 
11111
{% if ansible_fqdn=="rhel02"
and
ansible_distribution_major_version=="7" %}
{{ansible_fqdn}}
{% else %}
aaaaa
{% endif %}
33333
[bdqn@rhel01 demo4]$

这里jinja2模板会打印3行内容,第一行和最后一行的内容是固定的,为1111和3333。第二行的内容是什么,要看是否满足条件,这里判断被管理主机名为rhel02及系统主版本号为7,二者都要满足,第二行才会显示主机名,否则显示aaaa。需要注意的是,这里if判断语句太长,特意写成了3行也是没问题的 。

写一个playbook,内容如下。

[bdqn@rhel01 demo4]$ cat 3.yaml 
---
- hosts: db
  tasks:
  - name: 我要拷贝一个文件过去
    template: src=cc.j2 dest=/opt/cc.conf
[bdqn@rhel01 demo4]$

运行此playbook。命令如下。 

[bdqn@rhel01 demo4]$ ansible-playbook 3.yaml 

PLAY [db] *************************************************************************************************************************************************

TASK [Gathering Facts] ************************************************************************************************************************************
ok: [server2]
ok: [server3]

TASK [我要拷贝一个文件过去] *****************************************************************************************************************************************
changed: [server3]
changed: [server2]

PLAY RECAP ************************************************************************************************************************************************
server2                    : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
server3                    : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

[bdqn@rhel01 demo4]$

查看两台机器上/opt/cc.conf的内容,命令如下。 

[bdqn@rhel01 demo4]$ ansible db -m shell -a "cat /opt/cc.conf"
server2 | CHANGED | rc=0 >>
11111
aaaaa
33333
server3 | CHANGED | rc=0 >>
11111
aaaaa
33333
[bdqn@rhel01 demo4]$ 

for循环 

一个列表中有多个元素,如果需要依次对列表中的每个元素操作,则可以使用for循环来实现,for 循环的语法如下。 

{% for i in 列表名 %}

{{i}}

{% endfor %} 

这里首先把列表中的第一个元素赋值给i,执行中间的操作;然后把第二个元素赋值给i执行中间的操作,以此类推,直到把最后一个元素赋值给i。看下面的例子。 

[bdqn@rhel01 demo4]$ cat templates/dd.conf.j2 
{% set list1=['aa','bb','cc'] %}
11111
{% for i in list1 %}
{{i}}
{% endfor %}
55555
[bdqn@rhel01 demo4]$ 

这里手动在jinja2模板中定义了一个列表(注意定义列表的方式)list1,里面有3个元素,分别为aa、bb、cc。然后对这个列表的内容进行循环。 

这里jinja2模板生成的文件有5行内容,第1行和第5行的内容是固定的,为1111和5555。 第2~4行是循环列表list1 中的值,为aa、bb、cc. 

写一个 playbook,内容如下。 

[bdqn@rhel01 demo4]$ cat 4.yaml 
---
- hosts: server2
  tasks:
  - name: 拷贝一个文件到远端主机
    template: src=dd.conf.j2 dest=/opt/dd.conf
[bdqn@rhel01 demo4]$

运行此playbook,内容如下。 

[bdqn@rhel01 demo4]$ ansible-playbook 4.yaml 

PLAY [server2] ********************************************************************************************************************************************

TASK [Gathering Facts] ************************************************************************************************************************************
ok: [server2]

TASK [拷贝一个文件到远端主机] ****************************************************************************************************************************************
changed: [server2]

PLAY RECAP ************************************************************************************************************************************************
server2                    : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

[bdqn@rhel01 demo4]$

查看server2 上/opt/dd.conf的内容,命令如下。 

[bdqn@rhel01 demo4]$ ansible server2 -m shell -a "cat /opt/dd.conf"
server2 | CHANGED | rc=0 >>
11111
aa
bb
cc
55555
[bdqn@rhel01 demo4]$

除了jinja2模板中手动定义的列表,一般情况下,我们会在playbook中定义列表,然后对列表中的元素进行循环。 

写一个变量文件users_list.txt,里面包含一个名称为users的列表,命令如下。

[bdqn@rhel01 demo4]$ cat users_list.txt 
users:
- uname: tom
  age: 20
  sex: man
- uname: bob
  age: 21
  sex:	man
- uname: mary
  age: 22
  sex: woman
- uname: wangwu
  age: 23
  sex: man

[bdqn@rhel01 demo4]$

在 templates目录下写一个ee.j2,里面写一个 for 语句循环users列表,内容如下。 

[bdqn@rhel01 demo4]$ cat templates/ee.j2 
现在公司中所有员工姓名是:
{% for i in users %}
{{i.uname}}
{% endfor %}

[bdqn@rhel01 demo4]$

循环每个元素时,只打印元素中的uname变量。写一个名称为5.yaml的playbook,加载变量文件 users list.txt,命令如下。 

[bdqn@rhel01 demo4]$ cat 5.yaml 
---
- hosts: server2
  vars_files:
  - users_list.txt
  tasks:
  - name: 拷贝一个文件到远端主机
    template: src=ee.j2 dest=/opt/ee.conf
[bdqn@rhel01 demo4]$ 

这里通过template模块把ee.j2拷贝到被管理主机的/opt 中并命名为ee.conf。查看 server2上/opt/ee.conf的内容,命令如下。 

[bdqn@rhel01 demo4]$ ansible-playbook 5.yaml 

PLAY [server2] ********************************************************************************************************************************************

TASK [Gathering Facts] ************************************************************************************************************************************
ok: [server2]

TASK [拷贝一个文件到远端主机] ****************************************************************************************************************************************
changed: [server2]

PLAY RECAP ************************************************************************************************************************************************
server2                    : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

[bdqn@rhel01 demo4]$

查看被管理主机的/opt/ee.conf,里面包括users列表中所有的用户名。

[bdqn@rhel01 demo4]$ ansible server2 -m shell -a "cat /opt/ee.conf"
server2 | CHANGED | rc=0 >>
现在公司中所有员工姓名是:
tom
bob
mary
wangwu
[bdqn@rhel01 demo4]$

handlers 

前面讲了模板的使用,但是后期我们可能需要修改模板的内容,然后重新拷贝到各个机 器,此时需要重启httpd服务才会生效,先看下面的例子。 

先获取 httpd.conf的配置文件,获取的httpd.conf中没有任何空白行和注释行。 

[bdqn@rhel01 demo4]$ egrep -v '#|^#' /etc/httpd/conf/httpd.conf > httpd.conf.j2
[bdqn@rhel01 demo4]$ 

修改此httpd.conf.j2的第三行,把原来Listen后面的端口80换成{{myport}},让 httpd.confj2引用myport变量,内容如下。 

[bdqn@rhel01 demo4]$ head -5 httpd.conf.j2 

ServerRoot "/etc/httpd"

Listen {{myport}}

[bdqn@rhel01 demo4]$

为了不让例子变得太复杂,先临时关闭server2上的 SELinux,命令如下。 

[root@rhel01 ~]# setenforce 0
[root@rhel01 ~]# getenforce 0
Permissive
[root@rhel01 ~]# 
[root@rhel01 ~]# exit
注销
[bdqn@rhel01 demo4]$ 

写一个名称为hand-1.yaml的playbook,命令如下。 

[bdqn@rhel01 demo4]$ cat hand-1.yaml 
---
- hosts: server2
  vars:
    myport: 80
  tasks:
  - name: task1安装httpd
    yum: name=httpd state=installed
  - name: task2拷贝配置文件
    template: src=httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf
  - name: task3启动httpd服务
    service: name=httpd state=started
[bdqn@rhel01 demo4]$ 

第一个task用于安装 httpd,第二个task用于把模板httpd.conf.j2拷贝到被管理机器,第三个 task用于启动httpd服务,第一次是可以正常运行的。 

下面修改myport的值为808,内容如下。 

[bdqn@rhel01 demo4]$ ansible-playbook hand-1.yaml 

PLAY [server2] ********************************************************************************************************************************************

TASK [Gathering Facts] ************************************************************************************************************************************
ok: [server2]

TASK [task1安装httpd] ***************************************************************************************************************************************
changed: [server2]

TASK [task2拷贝配置文件] ****************************************************************************************************************************************
changed: [server2]

TASK [task3启动httpd服务] *************************************************************************************************************************************
changed: [server2]

PLAY RECAP ************************************************************************************************************************************************
server2                    : ok=4    changed=3    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

[bdqn@rhel01 demo4]$ 

第一个task用于安装httpd,第二个task用于把模板httpd.conf.2拷贝到被管理机器,第 三个 task用于启动httpd服务,第一次是可以正常运行的。 

下面修改myport 的值为808,内容如下。 

[bdqn@rhel01 demo4]$ cat hand-1.yaml 
---
- hosts: server2
  vars:
    myport: 808
  tasks:
  - name: task1安装httpd
    yum: name=httpd state=installed
  - name: task2拷贝配置文件
    template: src=httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf
  - name: task3启动httpd服务
    service: name=httpd state=started
[bdqn@rhel01 demo4]$ 

再次运行此playbook,因为 httpd已经安装过了,状态并没有发生任何改变,所以这次 第一个task不会执行。因为改变了myport的值,httpd.conf.j2中的端口也就发生了变化, 第二个task再次把模板文件拷贝到被管理机器。因为httpd已经处于启动状态,所以第三个 task也不会执行,从而导致第二个task铂贝过去的新模板文件并不会生效,因为httpd并没有重启。 

修改hand-1.yaml的内容如下。

[bdqn@rhel01 demo4]$ cat hand-1.yaml 
---
- hosts: server2
  vars:
    myport: 808
  tasks:
  - name: task1安装httpd
    yum: name=httpd state=installed
  - name: task2拷贝配置文件
    template: src=httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf
  - name: task3启动httpd服务
    service: name=httpd state=restarted
[bdqn@rhel01 demo4]$

这里把第三个task中的 started改成了restarted,如果我们修改了myport的值之后运行此playbook,第二个task 会正常执行,因为 httpd.conf,j2中的端口发生了变化。第三个task总是会执行,因为第三个task中state 的值为restarted,这样所做的修改会生效。 

但是如果什么都不修改,只是重复运行playbook,第三个task也会重启。所以,这里就 有一个问题了,第三个task中的state不论写started还是 restarted,都不正确。 

写started,配置文件修改了不会重启,所以不会生效。 

写restarted,配置文件不修改也会重启。

但我们想要的是,只有第二个 task 发生了变化才会重启 httpd服务,否则是 不需要重启的,这种情况下,就需要使用handler了。 

handler的用法如下图所示。

 

注意,这里handlers和 tasks是同级的。

在 tasks中定义了3个 task,在 handlers中定义了2个handler。当运行 playbook时,handlers中定义的handler并不会运行,它们只是在被触发时才会运行。在某个 task中写了一个notify,其后面的值要与handlers中的某个 handler 的name进行匹配。例如,上图中,编号2中 notify后面的值是 aaa,这个值与第一个 handler(编号4)的name值一样,这样当运行playbook时,如果编 号2这个task执行了,则会触发编号4这个 handler。 

修改hand-1.yaml 的内容如下。 

[bdqn@rhel01 demo4]$ cat hand-1.yaml 
---
- hosts: server2
  vars:
    myport: 808
  tasks:
  - name: task1安装httpd
    yum: name=httpd state=installed
  - name: task2拷贝配置文件
    template: src=httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf
    notify: restart httpd1
  - name: task3启动httpd服务
    serice: name=httpd state=restarted
  handlers:
  - name: restart httpd1
    service: name=httpd state=restarted
  - name: restart httpd2
    service: name=httpd state=restarted
[bdqn@rhel01 demo4]$

第三个task的state仍然设置为started,只要 httpd是启动的,第三个task就不会执行。 这里定义了两个handler,名称分别为restart httpd1和restart httpd2。在第二个task中, 通过notify指定了第一个 handler,即 restart httpd1。

如果不修改myport 的值,则第二个task不会执行,从而不会触发restart httpdl。如果 myport 的值发生了变化,则第二个task 会执行,从而会触发restart httpdl,重启 httpd服 务使得我们所做的修改生效。 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1334751.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【svn】win11最新svn每天自动化定时update、commit,隐藏窗口,定时脚本编写

本文使用schtasks结合bat脚本实现全自动svn update以及commit操作。执行时隐藏cmd窗口,全自动后台执行。 执行脚本 写脚本参考了网上很多文章,但是这些文章的方法都有问题或者已经失效,比如: 老版本的bat脚本,使用v…

【K8S 基本概念】Kurbernetes的架构和核心概念

目录 一、Kurbernetes 1.1 简介 1.2、K8S的特性: 1.3、docker和K8S: 1.4、K8S的作用: 1.5、K8S的特性: 二、K8S集群架构与组件: 三、K8S的核心组件: 一、master组件: 1、kube-apiserve…

“关爱长者 托起夕阳无限美好”清峰公益开展寒冬暖心慰问活动

2023年12月23日,陆丰市清峰公益服务中心在陆丰市潭西镇党群服务中心开展爱老敬老寒冬暖心慰问活动。此次活动是陆丰市清峰公益服务中心自11月中下旬“清峰公益 凝聚慈善力量 共创美好生活”项目启动仪式后开展的首次暖心慰问活动,活动还特意为老人们准备…

无经验如何开始开发家具商城小程序

如果你没有开发经验,但是想要创建一个家具商城小程序,那么你可以选择使用一个专业成熟的小程序商城制作平台,例如乔拓云平台。通过这个平台,你可以轻松地创建一个功能完善、外观美观的家具商城小程序。 首先,你需要登录…

【毕业快刊】IF12分,中科院2区,仅50天录用,17天见刊!国人占比第一!

计算机类 • 好刊解读 今天小编带来Springer旗下计算机领域高分快刊,如您有投稿需求,可作为重点关注!后文有相关领域真实发表案例,供您投稿参考~ 01 期刊简介 Artificial Intelligence Review ✅出版社:Springer ✅…

BUUCTF——Reverse——xor

1、题目 2、工具 Exeinfo PE:查壳工具。IDA:是一款功能强大的反汇编工具,用于分析和逆向工程二进制文件。python:编写自动化脚本。 3、方法 下载压缩包并解压,得到一个没有后缀的文件。 用Exeinfo PE查询该文件是否…

ASP.Net实现商品照片显示(三层架构)

演示功能: 点击启动生成页面 步骤: 1、建文件 下图是三层架构列表,Models里面有模拟数据库中列的类,DAL中有DBHelper和service,BLL中有BllManager文件用于ui界面直接调用,其中img文件用户储存照片,数据库…

代码随想录刷题题Day22

刷题的第二十二天,希望自己能够不断坚持下去,迎来蜕变。😀😀😀 刷题语言:C Day22 任务 ● 39. 组合总和 ● 40.组合总和II ● 131.分割回文串 1 组合总和 39. 组合总和 思路: 本题没有组合数…

视频剪辑去哪里找素材,全部正版高清~

做视频剪辑的小伙伴们经常会用到视频素材,所以,今天给大家推荐几个我常用的高清视频素材网站: 1、制片帮素材 网址:https://stock.zhipianbang.com/ 制片帮素材是一个专业视频素材的网站,站内有超多高清视频模板、实…

效率必备神器

在这个快节奏的工作环境中,使用一些强大的工作软件来提高工作效率和组织工作流程变得异常重要。无论是个人任务管理还是团队协作,合适的工作软件都能极大地改善工作质量和生产力。让我们深入了解一些我个人强力推荐的工作软件,希望能给你带来…

【Spring】SpringBoot 配置文件

文章目录 什么是配置文件SpringBoot配置文件配置文件快速入手配置文件的格式properties 配置文件说明properties 基本语法读取配置文件信息properties 配置格式缺点 yml 配置文件说明yml 基本语法使用 yml 连接数据库 yml 使用进阶yml 配置不同数据类型配置对象配置集合配置Map…

redis 从0到1完整学习 (八):QuickList 数据结构

文章目录 1. 引言2. redis 源码下载3. quickList 数据结构3.1 整体3.2 数据结构 4. 参考 1. 引言 前情提要: 《redis 从0到1完整学习 (一):安装&初识 redis》 《redis 从0到1完整学习 (二)&#xff1a…

强化学习_06_pytorch-TD3实践(CarRacing-v2)

0、TD3算法原理简介 详见笔者前一篇实践强化学习_06_pytorch-TD3实践(BipedalWalkerHardcore-v3) 1、CarRacing环境观察及调整 Action SpaceBox([-1. 0. 0.], 1.0, (3,), float32)Observation SpaceBox(0, 255, (96, 96, 3), uint8) 动作空间是[-1~1, 0~1, 0~1]&#xff0c…

巅峰画师Midjourney:新时代的独角兽

介绍 AI绘画领域中,Midjourney处于绝对地位,并且一年时间就登顶。 Midjourney是一家独立的AI研究实验室,探索新的思维媒介,拓展人类的想象力。 它由一个小型的自筹资金团队组成,专注于设计、人类基础设施和AI。 在AI绘画领域,Midjourney取得了非常突出…

LAMP集中式搭建+LNMP分布式搭建(新版)

LAMP搭建LNMP搭建 LAMP搭建LNMP搭建一、LAMP搭建(集中式)1、LAMP简介2、LAMP组件及作用3、编译安装Apache httpd服务4、编译安装mysqld 服务5、编译安装PHP解析环境6、安装论坛7、安装博客 二、LNMP搭建(分布式)1、LNMP工作原理2、安装nginx3、安装mysql4、安装php5、在浏览器测…

【网络安全/CTF】easyphp 江苏工匠杯

本题考察PHP语言相关绕过知识 正文 开门见山给代码 <?php highlight_file(__FILE__); $key1 0; $key2 0;$a $_GET[a]; $b $_GET[b];if(isset($a) && intval($a) > 6000000 && strlen($a) < 3){if(isset($b) && 8b184b substr(md5($b),…

Centos安装Composer

今天分享下如何在centos系统里安装composer 一、下载composer curl -sS https://getcomposer.org/installer | php二、移动或复制composer到环境下可执行 cp composer.phar /usr/local/bin/composer三、测试看是否安装成功 composer -V四、全局安装 curl -sS https://getc…

zabbix-邮件告警与钉钉机器人告警

zabbix-邮件告警 在部署邮件告警前需要先将zabbix部署成功 邮件告警需要得到邮箱的授权码&#xff0c;这里将以qq邮箱为例。 1.获取邮箱的授权码 2.编辑Email的相关信息 3.测试Email是否配置成功 测试成功。 4.为用户添加邮箱报警服务 5.创建主机群组、主机、监视项、触…

Kylin-Desktop-V10-SP1-General-Release-2303-X86_64-海光版(hygon c86)下载

csdn下载 【免费】Kylin-Desktop-V10-SP1-General-Release-2303-X86-64-海光版-001资源-CSDN文库 【免费】Kylin-Desktop-V10-SP1-General-Release-2303-X86-64-海光版-002资源-CSDN文库 【免费】Kylin-Desktop-V10-SP1-General-Release-2303-X86-64-海光版003资源-CSDN文库…

【k8s源码分析-Apiserver-2】kube-apiserver 结构概览以及主体部分源码分析

参考 Kubernetes 源码剖析&#xff08;书籍&#xff09;kube-apiserver的设计与实现 - 自记小屋 kube-apiserver 核心思想 APIGroupInfo 记录 GVK 与 Storage 的对应关系 将 GVK 转换成&#xff0c;Restful HTTP Path将 Storage 封装成 HTTP Handler将上面两个形成映射&#…