RHCE8 资料整理
第 33 章 jinja2模板的使用
详细参考
https://blog.csdn.net/u010230019/article/details/128561872
https://blog.csdn.net/u010230019/article/details/128477679
假设目前Nginx的配置文件在所有的服务器上都是相同的,但我希望能根据每一台服务器的性能去定制服务的启动进程。 同时定制每一台Nginx服务的响应头,以便于当某台服务出现问题时能快速定位到具体的服务器。
要做这样的定制势必会导致一个问题,Nginx 在每台物理服务器上的配置文件都不一样,这样的配置文件如何管理呢? 再使用copy 模块去做管理显然已经不合适。此时使用Ansible 提供的另一个模块(template
) 功能,它可以帮助我们完美的解决问题。
template
模块使用了Jinjia2格式作为文件模版,可以进行文档内变量的替换。 它的每次使用都会被ansible标记为”changed”状态。文件以 .j2 结尾,模块常用参数如下:
backup 创建一个包含时间戳信息的备份文件,这样如果您以某种方式错误地破坏了原始文件,就可以将其恢复原状。yes/no
force 默认值是yes,当内容与源不同时,它将替换远程文件。如果no,仅在目标不存在时才传输文件。
src 指定 Ansible 控制端的文件路径
dest 指定 Ansible 被控端的文件路径
owner 指定文件的属主
group 指定文件的属组
mode 指定文件的权限
newline_sequence 指定新文件的换行符; \n,\r, 或 \r\n
Jiaja2是Flask
默认支持的模板引擎,它的主要作用是渲染模板
- jinja2 文件以 .j2 为后缀, 也可以不写后缀。
- jinja2 中存在三种定界符
注释: {
# 注释内容 #}
变量引用: {
{
var }}
逻辑表达: {
% %}
示例,
[root@node-137 ansible]# cat templates/aa.j2
myIP: {
{
ansible_default_ipv4.address}}
[root@node-137 ansible]# cat jinja2-1.yml
---
- hosts: db1
gather_facts: true
tasks:
- template: src=aa.j2 dest=/home/yurq/aa.txt
[root@node-137 ansible]# ansible-playbook jinja2-1.yml
PLAY [db1] ****************************************************************************************************************************
TASK [Gathering Facts] ****************************************************************************************************************
ok: [node-138]
TASK [template] ***********************************************************************************************************************
ok: [node-138]
PLAY RECAP ****************************************************************************************************************************
node-138 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[root@node-137 ansible]# ansible db1 -m shell -a "cat /home/yurq/aa.txt"
node-138 | CHANGED | rc=0 >>
myIP: 192.168.81.138
如果jinja2模板文件中没有写路径,则会优先
在当前目录的templates
中查找
31.1 if 判断
{
# 如果定义了 idc 变量, 则输出 #}
{
% if 判断1 %}
内容1
{
% elif 判断2 %}
内容2
{
% else %}
内容3
{
% endif %}
注意:
%
两边有没有空格都可以,不过所有的%
前后空格要保持一致if
或elif
中的内容过多,可以另起一行elif
和else
不是必需的- 如果
判断1
成立,则打印内容1
,后面的条件不再执行,直接跳到endif
后面的内容;如果判断1
不成立,则执行elif
后面的判断2
,成功则跳到endif
后面的内容,如果判断2
不成立,则执行else
后面内容3
。如果if
或elif
都不成立,则打印else
后面内容3
。
示例,
[root@node-137 ansible]# cat templates/if-1.j2
{
% if ansible_default_ipv4.address=='192.168.17.138' %}
{
{
ansible_default_ipv4.address }}
{
% elif ansible_fqdn=="node-138" %}
{
{
ansible_fqdn }}
{
% else %}
{
{
ansible_distribution_major_version }}
{
% endif %}
"end"
[root@node-137 ansible]# cat if-1.yml
---
- hosts: db1
gather_facts: true
tasks:
- template: src=if-1.j2 dest=/home/yurq/if.txt
[root@node-137 ansible]# ansible-playbook if-1.yml
PLAY [db1] ****************************************************************************************************************************
TASK [template] ***********************************************************************************************************************
fatal: [node-138]: FAILED! => {
"changed": false, "msg": "AnsibleUndefinedVariable: 'ansible_default_ipv4' is undefined"}
PLAY RECAP ****************************************************************************************************************************
node-138 : ok=0 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
[root@node-137 ansible]# ansible db1 -m shell -a "cat /home/yurq/if.txt"
node-138 | CHANGED | rc=0 >>
node-138
"end"
33.2 for循环
一个列表中有多个元素,如果需要依次对列表中的每个元素操作,则可以使用for
循环来实现,语法,
{
% for i in 列表名%}
{
{
i}}
{
% endfor %}
示例,
[root@node-137 ansible]# cat templates/for-1.j2
{
% set list1=['aa','bb','cc'] %}
111
{
% for i in list1 %}
{
{
i}}
{
% endfor %}
222
[root@node-137 ansible]# cat for-1.yml
---
- hosts: db1
gather_facts: false
tasks:
- template: src=for-1.j2 dest=/home/yurq/for-1.txt
[root@node-137 ansible]# ansible-playbook for-1.yml
PLAY [db1] ****************************************************************************************************************************
TASK [template] ***********************************************************************************************************************
changed: [node-138]
PLAY RECAP ****************************************************************************************************************************
node-138 : ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[root@node-137 ansible]# ansible db1 -m shell -a "cat /home/yurq/for-1.txt"
node-138 | CHANGED | rc=0 >>
111
aa
bb
cc
222
除了jinja2模板中手动定义的列表,一般情况下,我们会在playbook中定义列表,然后对列表中的元素进行循环
[root@node-137 ansible]# cat templates/ee.j2
{
% for i in users %}
{
{
i.uname}}
{
% endfor %}
[root@node-137 ansible]# cat user_list.txt
users:
- uname: "tom"
age: 18
- uname: "jerry"
age: 19
- uname: "jacky"
age: 18
[root@node-137 ansible]# cat for-2.yml
---
- hosts: db1
gather_facts: false
vars_files:
- user_list.txt
tasks:
- template: src=ee.j2 dest=/home/yurq/for-2.txt
[root@node-137 ansible]# ansible-playbook for-2.yml
PLAY [db1] ****************************************************************************************************************************
TASK [template] ***********************************************************************************************************************
ok: [node-138]
PLAY RECAP ****************************************************************************************************************************
node-138 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[root@node-137 ansible]# ansible db1 -m shell -a "cat /home/yurq/for-2.txt"
node-138 | CHANGED | rc=0 >>
tom
jerry
jacky
33.3 handlers
Handlers是Ansible Playbooks中的一种特殊任务类型。它们类似于事件处理程序,用于在特定条件下触发和执行任务。Handlers通常与任务关联,当任务的状态发生变化时,Handlers会被触发执行。Handlers可以用于执行各种操作,如重启服务、重新加载配置文件等。
1.handlers是ansible提供的条件机制之一,handlers和tasks很类似,但是只在被tasks通知的时候才会触发执行;
2.handlers只会在任务执行完成后执行。即使被通知了很多次,也只会执行一次。
3.当一个tasks中有多个notify,只会执行最后一个。
4.当tasks所有需要执行的任务执行完毕,才会执行handlers中的任务,并非跳转执行
[root@node-137 ansible]# cat hand-1.yml
---
- hosts: db1
gather_facts: false
vars:
myport: 8080
tasks:
- template: src=httpd.conf1.j2 dest=/etc/httpd/conf/httpd.conf
notify: stop httpd1
- shell: "systemctl is-active httpd"
ignore_errors: true
register: a
- debug: msg={
{
a.rc}}
- service: name=httpd state=started
- shell: "systemctl is-active httpd"
register: b
- debug: msg={
{
b.rc}}
handlers:
- name: stop httpd1
service: name=httpd state=stopped
- hosts: db1
gather_facts: false
tasks:
- shell: "systemctl is-active httpd"
ignore_errors: true
register: a
- debug: msg={
{
a.rc}}
[root@node-137 ansible]# ansible-playbook hand-1.yml
PLAY [db1] ****************************************************************************************************************************
TASK [template] ***********************************************************************************************************************
changed: [node-138]
TASK [shell] **************************************************************************************************************************
fatal: [node-138]: FAILED! => {
"changed": true, "cmd": "systemctl is-active httpd", "delta": "0:00:00.037178", "end": "2023-12-21 16:20:43.782274", "msg": "non-zero return code", "rc": 3, "start": "2023-12-21 16:20:43.745096", "stderr": "", "stderr_lines": [], "stdout": "unknown", "stdout_lines": ["unknown"]}
...ignoring
TASK [debug] **************************************************************************************************************************
ok: [node-138] => {
"msg": "3"
}
TASK [service] ************************************************************************************************************************
changed: [node-138]
TASK [shell] **************************************************************************************************************************
changed: [node-138]
TASK [debug] **************************************************************************************************************************
ok: [node-138] => {
"msg": "0"
}
RUNNING HANDLER [stop httpd1] *********************************************************************************************************
changed: [node-138]
PLAY [db1] ****************************************************************************************************************************
TASK [shell] **************************************************************************************************************************
fatal: [node-138]: FAILED! => {
"changed": true, "cmd": "systemctl is-active httpd", "delta": "0:00:00.034846", "end": "2023-12-21 16:20:48.079788", "msg": "non-zero return code", "rc": 3, "start": "2023-12-21 16:20:48.044942", "stderr": "", "stderr_lines": [], "stdout": "unknown", "stdout_lines": ["unknown"]}
...ignoring
TASK [debug] **************************************************************************************************************************
ok: [node-138] => {
"msg": "3"
}
PLAY RECAP ****************************************************************************************************************************
node-138 : ok=9 changed=6 unreachable=0 failed=0 skipped=0 rescued=0 ignored=2