1、jinja2簡介解python
Jinja2是Python下一個被普遍應用的模版引擎,他的設計思想來源於Djanjo的模板引擎,並擴展了其語法和一系列強大的功能。ansible的模板配置文件就是用jinja2這種模板編程語言寫的,其中jinja2使用字面量有以下形式nginx
1)字符串:使用單引號或雙引號引發來的部分web
2)數字:支持整數,浮點數(小數)shell
3)列表:和python裏的列表同樣,用中括號括起來,每一個元素之間用逗號隔開,如[item1,item2,....]編程
4)元組:和python裏的元組同樣,小括號括起來,每一個元素之間用逗號隔開,如(item1,item2,....)vim
5)字典:同python裏的字典同樣,大括號括起來,每一個k/v(鍵值對)用逗號隔開,鍵和值用":"冒號隔開,如{key1:value1,key2:value2,....}centos
6)布爾型:同其餘語言布爾型同樣,ture/falsebash
7)支持算數運算:+,-,*,/,//(整除,地板除),%(取模,取餘數),**(冪運算)dom
8)支持比較操做:==(比較兩個值是否相等),!=(不等),>,>=(大於等於),<,<=(小於等於)編程語言
9)支持邏輯運算:and(與),or(或),not(非)
10)支持for(循環) ,if(判斷),when(當某一條件知足纔開始執行when所在的代碼塊,做用相似if)
除此之外,jinja2還支持「test」測試語句,好比咱們要判斷某個變量是否認義,可使用defined來判斷,如 vars is defined ,若是vars定義則表達式返回true,相反返回false。相似的還有undefined(與defined相反),equalto(與「==」做用等效),even(判斷對象是不是偶數),iterable(判斷對象是否可迭代)
2、jinja2語法
jinja2有以下語法:
1)控制結構,它和咱們寫別的語言的控制結構相似,惟一不一樣的是它的for循環要用」{%%}「給括起來,且必須寫在兩個百分號之間,後面結束有一個{%endfor$}來表示for循環的結束,一樣if語句也是,必須寫在"{%%}" 兩個百分號之間,後面結束也有個{%endif%}來表示if語句的結束,固然if語句支持elif ,else 這個同python裏的if用法同樣。
2)變量引用,jinja2的變量引用同ansible的變量應用相似,都是用"{{}}" 雙大括號來表示中間括起來的內容表示變量
3)註釋用"{#"開始,中間部分表示註釋,以"#}"結束表示註釋結束,支持多行註釋和當行註釋
示例:
1)for循環使用
{% for vhost in nginx_vhosts %} server { listen {{ vhost.listen }} } {% endfor %}
說明:以上模板表示,從nginx_vhosts列表裏去循環,nginx_vhosts裏有幾個元素,它將循環幾回,每次循環取的值用vhost變量代替,它的用法類型shell裏的for循環和python裏的for循環
2)if單分支選擇使用
{% if vhost.server_name is defined %} server_name {{ vhost.server_name }} {% endif %}
3)if多分支選擇使用
{%if vhost.port is undefined %} http_port=80 {%elif vhost.port == 81%} http_port=81 {%else%} http_port = 83 {%endif%}
4)單行註釋
{#% for i in list %#}
5)多行註釋
{# {% for i in list %} i+=i {% endfor %} #}
3、playbook中使用模板
templates是ansible的一個模塊,其功能是根據模板文件動態生成配置文件,templates文件必須存放於templates目錄下,且命名爲".j2"結尾,yaml/yml文件須要和templates目錄平級,這樣咱們在yml文件中調用模板的時候,就不須要寫模板文件的路徑,不然須要描述模板文件的路徑,由於template模塊會自動去找templates目錄下的模板文件。目錄結構以下
. ├── temnginx.yml └── templates └── nginx.conf.j2
示例:playbook中template變量替換
利用tamplates同步nginx配置文件,其中修改nginx.conf.j2(worker_processes {{ ansible_processor_vcpus }};)指定其worker進程的個數由遠程主機的cpu個數決定
[root@test ~]#ll 總用量 4 -rw-r--r-- 1 root root 212 11月 18 14:08 temnginx.yml drwxr-xr-x 2 root root 27 11月 18 14:05 templates [root@test ~]#tree . ├── temnginx.yml └── templates └── nginx.conf.j2 1 directory, 2 files [root@test ~]#head templates/nginx.conf.j2 # For more information on configuration, see: # * Official English Documentation: http://nginx.org/en/docs/ # * Official Russian Documentation: http://nginx.org/ru/docs/ user nginx; worker_processes {{ ansible_processor_vcpus }}; error_log /var/log/nginx/error.log; pid /run/nginx.pid; # Load dynamic modules. See /usr/share/nginx/README.dynamic. [root@test ~]#cat temnginx.yml --- - hosts: websers remote_user: root tasks: - name: install nginx yum: name=nginx - name: template config to remote hosts template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf [root@test ~]#
說明:以上playbook裏是使用template模板去動態生成的配置文件,不是拷貝,拷貝是將文件原封不動的拷貝過去,還須要注意的是template模塊不能在ad-hoc命令行裏使用,只能在playbook裏使用,且模板文件必須是".j2"結尾的
示例:playbook中template算數運算
仍是以上的示例,咱們能夠這樣寫
vim nginx.conf.j2 worker_processes {{ ansible_processor_vcpus**2 }};
說明:咱們能夠用ansible內置變量作算術運算後的值做爲模板文件的值,在playbook中仍是用template模塊去調用就行了
示例:模板文件中 for循環的用法
[root@test ~]#tree . ├── temnginx.yml └── templates └── nginx.conf.j2 1 directory, 2 files [root@test ~]#cat templates/nginx.conf.j2 {% for vhost in nginx_vhosts %} server { listen {{ vhost.listen }} } {% endfor %} [root@test ~]#cat temnginx.yml --- - hosts: websers remote_user: root vars: nginx_vhosts: - listen: 8080 tasks: - name: install nginx yum: name=nginx - name: template config to remote hosts template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf [root@test ~]#
生成結果:
[root@test ~]#ansible-playbook temnginx.yml PLAY [websers] ****************************************************************************************************** TASK [Gathering Facts] ********************************************************************************************** ok: [192.168.0.128] ok: [192.168.0.218] TASK [install nginx] ************************************************************************************************ changed: [192.168.0.128] changed: [192.168.0.218] TASK [template config to remote hosts] ****************************************************************************** changed: [192.168.0.128] changed: [192.168.0.218] PLAY RECAP ********************************************************************************************************** 192.168.0.128 : ok=3 changed=2 unreachable=0 failed=0 192.168.0.218 : ok=3 changed=2 unreachable=0 failed=0 [root@test ~]#ansible websers -m shell -a 'cat /etc/nginx/nginx.conf' 192.168.0.128 | SUCCESS | rc=0 >> server { listen 8080 } 192.168.0.218 | SUCCESS | rc=0 >> server { listen 8080 } [root@test ~]#
示例:模板文件中if的用法
[root@test ~]#tree . ├── temnginx.yml └── templates └── nginx.conf.j2 1 directory, 2 files [root@test ~]#cat temnginx.yml --- - hosts: websers remote_user: root vars: nginx_vhosts: - web1: listen: 8080 server_name: "web1.test.com" root: "/var/www/nginx/web1/" - web2: listen: 8080 root: "/var/www/nginx/web2/" - web3: listen: 8080 server_name: "web2.test.com" root: "var/www/nginx/web3/" tasks: - name: template config to remote hosts template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf [root@test ~]#cat templates/nginx.conf.j2 {% for vhost in nginx_vhosts %} server { listen {{ vhost.listen }} {% if vhost.server_name is defined %} server_name {{ vhost.server_name }} {% endif %} root {{ vhost.root }} } {% endfor %} [root@test ~]#
生成結果:
[root@test ~]#ansible-playbook temnginx.yml PLAY [websers] ****************************************************************************************************** TASK [Gathering Facts] ********************************************************************************************** ok: [192.168.0.128] ok: [192.168.0.218] TASK [template config to remote hosts] ****************************************************************************** changed: [192.168.0.128] changed: [192.168.0.218] PLAY RECAP ********************************************************************************************************** 192.168.0.128 : ok=2 changed=1 unreachable=0 failed=0 192.168.0.218 : ok=2 changed=1 unreachable=0 failed=0 [root@test ~]#ansible websers -m shell -a 'cat /etc/nginx/nginx.conf' 192.168.0.128 | SUCCESS | rc=0 >> server { listen 8080 server_name web1.test.com root /var/www/nginx/web1/ } server { listen 8080 root /var/www/nginx/web2/ } server { listen 8080 server_name web2.test.com root var/www/nginx/web3/ } 192.168.0.218 | SUCCESS | rc=0 >> server { listen 8080 server_name web1.test.com root /var/www/nginx/web1/ } server { listen 8080 root /var/www/nginx/web2/ } server { listen 8080 server_name web2.test.com root var/www/nginx/web3/ } [root@test ~]#
說明:能夠看到第二個server裏是沒有server_name,由於定義的變量列表裏web2沒有定義server_name
4、playbook中使用when條件測試
條件測試:若是須要根據變量、facts或此前任務的執行結果來做爲某task執行與否的前提時須要用到條件測試,經過when語句實現,在task中使用jinja2的語法格式,when語句支持jinja2表達式語法;
示例:
[root@test ~]#cat test.yml --- - hosts: all remote_user: root tasks: - name: set hostname centos6 hostname: name=ansible_centos6 when: ansible_distribution_major_version == "6" - name: set hostname centos7 hostname: name=ansible_centos7 when: ansible_distribution_major_version == "7" [root@test ~]#ansible all -m shell -a 'hostname' 192.168.0.128 | SUCCESS | rc=0 >> localhost 192.168.0.218 | SUCCESS | rc=0 >> localhost.localdomain 192.168.0.217 | SUCCESS | rc=0 >> centos7 [root@test ~]#ansible-playbook test.yml PLAY [all] ********************************************************************************************************** TASK [Gathering Facts] ********************************************************************************************** ok: [192.168.0.128] ok: [192.168.0.218] ok: [192.168.0.217] TASK [set hostname centos6] ***************************************************************************************** skipping: [192.168.0.217] changed: [192.168.0.218] changed: [192.168.0.128] TASK [set hostname centos7] ***************************************************************************************** skipping: [192.168.0.128] skipping: [192.168.0.218] changed: [192.168.0.217] PLAY RECAP ********************************************************************************************************** 192.168.0.128 : ok=2 changed=1 unreachable=0 failed=0 192.168.0.217 : ok=2 changed=1 unreachable=0 failed=0 192.168.0.218 : ok=2 changed=1 unreachable=0 failed=0 [root@test ~]#ansible all -m shell -a 'hostname' 192.168.0.128 | SUCCESS | rc=0 >> ansible_centos6 192.168.0.218 | SUCCESS | rc=0 >> ansible_centos6 192.168.0.217 | SUCCESS | rc=0 >> ansible_centos7 [root@test ~]#
說明:以上playbook利用when語句判斷系統版本號,實現了經過不一樣的系統版本號,設置不一樣的主機名。
5、playbook迭代with_items
迭代:當有須要重複性執行的任務時,可以使用迭代機制;對迭代項的引用,ansible有固定不變的變量,名爲「item」;要在task中使用with_items給定要迭代的元素列表,列表格式能夠爲字符串、字典。
示例:批量建立用戶
[root@test ~]#cat adduser.yml --- - hosts: websers remote_user: root tasks: - name: add users user: name={{ item }} state=present home=/home/{{ item }} groups=root,bin,wheel with_items: - user1 - user2 - user3 [root@test ~]#ansible-playbook adduser.yml PLAY [websers] ****************************************************************************************************** TASK [Gathering Facts] ********************************************************************************************** ok: [192.168.0.128] ok: [192.168.0.218] TASK [add users] **************************************************************************************************** changed: [192.168.0.128] => (item=user1) changed: [192.168.0.218] => (item=user1) changed: [192.168.0.128] => (item=user2) changed: [192.168.0.218] => (item=user2) changed: [192.168.0.128] => (item=user3) changed: [192.168.0.218] => (item=user3) PLAY RECAP ********************************************************************************************************** 192.168.0.128 : ok=2 changed=1 unreachable=0 failed=0 192.168.0.218 : ok=2 changed=1 unreachable=0 failed=0 [root@test ~]#ansible websers -m shell -a 'tail -3 /etc/passwd' 192.168.0.128 | SUCCESS | rc=0 >> user1:x:503:503::/home/user1:/bin/bash user2:x:504:504::/home/user2:/bin/bash user3:x:505:505::/home/user3:/bin/bash 192.168.0.218 | SUCCESS | rc=0 >> user1:x:1213:1213::/home/user1:/bin/bash user2:x:1214:1214::/home/user2:/bin/bash user3:x:1215:1215::/home/user3:/bin/bash [root@test ~]#ansible websers -m shell -a 'id user1' 192.168.0.218 | SUCCESS | rc=0 >> uid=1213(user1) gid=1213(user1) 組=1213(user1),0(root),1(bin),10(wheel) 192.168.0.128 | SUCCESS | rc=0 >> uid=503(user1) gid=503(user1) 組=503(user1),0(root),1(bin),10(wheel) [root@test ~]#
示例:迭代嵌套子變量
[root@test ~]#cat adduser2.yml --- - hosts: websers remote_user: root tasks: - name: create groups group: name={{ item }} with_items: - group1 - group2 - group3 - name: create users user: name={{ item.name }} group={{ item.group }} state=present with_items: - {name: 'test1',group: 'group1'} - {name: 'test2',group: 'group2'} - {name: 'test3',group: 'group3'} [root@test ~]#ansible-playbook adduser2.yml PLAY [websers] ****************************************************************************************************** TASK [Gathering Facts] ********************************************************************************************** ok: [192.168.0.128] ok: [192.168.0.218] TASK [create groups] ************************************************************************************************ changed: [192.168.0.128] => (item=group1) changed: [192.168.0.218] => (item=group1) changed: [192.168.0.128] => (item=group2) changed: [192.168.0.218] => (item=group2) changed: [192.168.0.128] => (item=group3) changed: [192.168.0.218] => (item=group3) TASK [create users] ************************************************************************************************* changed: [192.168.0.128] => (item={u'group': u'group1', u'name': u'test1'}) changed: [192.168.0.218] => (item={u'group': u'group1', u'name': u'test1'}) changed: [192.168.0.128] => (item={u'group': u'group2', u'name': u'test2'}) changed: [192.168.0.218] => (item={u'group': u'group2', u'name': u'test2'}) changed: [192.168.0.128] => (item={u'group': u'group3', u'name': u'test3'}) changed: [192.168.0.218] => (item={u'group': u'group3', u'name': u'test3'}) PLAY RECAP ********************************************************************************************************** 192.168.0.128 : ok=3 changed=2 unreachable=0 failed=0 192.168.0.218 : ok=3 changed=2 unreachable=0 failed=0 [root@test ~]#ansible websers -m shell -a 'tail -3 /etc/passwd' 192.168.0.128 | SUCCESS | rc=0 >> test1:x:506:506::/home/test1:/bin/bash test2:x:507:507::/home/test2:/bin/bash test3:x:508:508::/home/test3:/bin/bash 192.168.0.218 | SUCCESS | rc=0 >> test1:x:1216:1216::/home/test1:/bin/bash test2:x:1217:1217::/home/test2:/bin/bash test3:x:1218:1218::/home/test3:/bin/bash [root@test ~]#ansible websers -m shell -a 'id test1' 192.168.0.218 | SUCCESS | rc=0 >> uid=1216(test1) gid=1216(group1) 組=1216(group1) 192.168.0.128 | SUCCESS | rc=0 >> uid=506(test1) gid=506(group1) 組=506(group1) [root@test ~]#ansible websers -m shell -a 'id test2' 192.168.0.128 | SUCCESS | rc=0 >> uid=507(test2) gid=507(group2) 組=507(group2) 192.168.0.218 | SUCCESS | rc=0 >> uid=1217(test2) gid=1217(group2) 組=1217(group2) [root@test ~]#ansible websers -m shell -a 'id test3' 192.168.0.128 | SUCCESS | rc=0 >> uid=508(test3) gid=508(group3) 組=508(group3) 192.168.0.218 | SUCCESS | rc=0 >> uid=1218(test3) gid=1218(group3) 組=1218(group3) [root@test ~]#
說明:以上playbook實現了對應用戶建立時加入對應的組裏