Linux jinja2模板的使用

Linux jinja2模板的使用

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

Session lifetime based on X11 requested, but X11 initialization failed.
[blab@rh1 ~]$ mkdir demo4
[blab@rh1 ~]$ cp ansible.cfg hosts demo4/
[blab@rh1 ~]$ cd demo4/
[blab@rh1 demo4]$ 

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

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

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

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

写一个 playbook,内容如下。

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

运行此playbook,命令如下。

[blab@rh1 demo4]$ ansible-playbook 1.yaml 

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

TASK [Gathering Facts] ********************************************************************************
ok: [rh2]
ok: [rh3]

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

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

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

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

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

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

修改1.yaml的内容如下。

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

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

[blab@rh1 demo4]$ ansible-playbook 1.yaml 

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

TASK [Gathering Facts] ********************************************************************************
ok: [rh3]
ok: [rh2]

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

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

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

[blab@rh1 demo4]$ ansible db -m shell -a "cat /opt/aa.txt"
rh3 | CHANGED | rc=0 >>
+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+
| 我的 IP 地址是: 192.168.25.172
+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+
rh2 | CHANGED | rc=0 >>
+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+
| 我的 IP 地址是: 192.168.25.171
+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+

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

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

所以,需要修改aa.txt的文件为aa.j2

[blab@rh1 demo4]$ mv aa.txt aa.j2

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

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

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

验证,命令如下。

[blab@rh1 demo4]$ mkdir templates

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

[blab@rh1 templates]$ cat aa.j2 
+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+
| 我的 IP 地址是: {{ansibe_fqdn}}
+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+

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

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

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

[blab@rh1 demo4]$ ansible db -m shell -a "cat /opt/aa.txt"
rh3 | CHANGED | rc=0 >>
+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+
| 我的主机名是: rh3
+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+
rh2 | CHANGED | rc=0 >>
+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+
| 我的主机名是: rh2
+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+

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

if判断

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

{% if 判断1 %}
 内容1
 {% elif 判断2 %}
 内容2
 ...多个elif...
 {% else %}
 内容3
 {% endif %}

注意:

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

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

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

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

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

[blab@rh1 templates]$ cat bb.j2 
111111
{% if ansible_fqdn=="rh2" %}
{{ansible_fqdn}}
{% else %}
aaaa
{% endif %}
33333

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

写一个playbook,内容如下。

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

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

[blab@rh1 demo4]$ ansible-playbook 2.yaml 

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

TASK [Gathering Facts] ********************************************************************************
ok: [rh2]
ok: [rh3]

TASK [拷贝一个文件] *****************************************************************************************
changed: [rh3]
changed: [rh2]

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

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

[blab@rh1 demo4]$ ansible db -m shell -a "cat /opt/bb.conf" 
rh3 | CHANGED | rc=0 >>
111111
aaaa
33333
rh2 | CHANGED | rc=0 >>
111111
rh2
33333

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

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

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

查看下面的 jinja2模板文件。

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

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

写一个playbook,内容如下。

[blab@rh1 demo4]$ cat 3.yaml 
---
- hosts: db
  tasks:
  - name: 拷贝一个文件
    template: src=cc.j2 dest=/opt/cc.conf


运行此playbook。命令如下。

[blab@rh1 demo4]$ ansible-playbook 3.yaml 

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

TASK [Gathering Facts] ********************************************************************************
ok: [rh3]
ok: [rh2]

TASK [拷贝一个文件] *****************************************************************************************
changed: [rh2]
changed: [rh3]

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

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

[blab@rh1 demo4]$ ansible db -m shell -a "cat /opt/cc.conf"
rh3 | CHANGED | rc=0 >>
1111
  aaaa
 3333
rh2 | CHANGED | rc=0 >>
1111
  aaaa
 3333

你可能感兴趣的:(linux,服务器,运维,ansible)