setup模块常用自带变量:
匹配完整主机名变量
ansible_hostname  <主机名变量>
ansible_distribution_major_version <版本号变量> 
ansible_all_ipv4_addresses 

变量名:仅能由字母、数字和下划线组成,且只能以字母开头 
变量来源: 
    1 ansible setup facts 远程主机的所有变量都可直接调用  
    2 在/etc/ansible/hosts中定义        
    普通变量:主机组中主机单独定义,优先级高于公共变量        
    公共(组)变量:针对主机组中所有主机定义统一变量 
    3 通过命令行指定变量,优先级最高      
    ansible-playbook –e varname=value 
    4 在playbook中定义 
    vars: 
    - var1: value1 
    - var2: value2 
    5 在role中定义 

变量命名:  
    变量名仅能由字母、数字和下划线组成,且只能以字母开头 
    变量定义:key=value 
    示例:http_port=80 
    变量调用方式: 
    1)通过{{ variable_name }} 调用变量,且变量名前后必须有 空格,有时用“{{ variable_name }}”才生效 
    2)ansible-playbook –e 选项指定   
    示例:
    ansible-playbook test.yml -e "hosts=www user=mageedu" 

在palybook里面使用变量能让playboot更加灵活

(一):在playbook里定义变量
看下面的例子:

---
- hosts: web
  remote_user: root

  tasks: 
    - name: remove package
      yum: name={{ pkname }} state=absent
    - name: initall package
      yum: name={{ pkname }}
    - name: start service
      service: name={{ pkname }} state=started
[root@ansiblehost ansible.yaml]#ansible-playbook -e "pkname=httpd " install.ym

上面这个playbook分为三步,
第一步:卸包,
第二步:装包,
第三步:重启服务
"但是注意到没有,而这三步我用的是一个变量,也就是我只要在命令行定义一个变量就可以完成这三个动作"
但是这个还是需要自己手工制定变量,

(二):将变量名与变量名内容直接定义到playboot里
看下面的例子:

    ---
    - hosts: web
      remote_user: root
      "#vars是专门用于在playboot定义变量的关键词"
      vars:  
        "#username,gropname就是变量名冒号":"后面的就是变量内容"
        - username: user1
        - groupname: root

      tasks:
        #任务一创建组
        - name: create group
          group: name={{ groupname }}
        "#创建用户并把该用户加入上面创建的组里面,再创键家目录到/app下"
        - name: create user
              user: name={{ username }} group={{   groupname }} home=/app/{{ username }}
执行playbook的方法:"而这时候调用playboot就不需要用-e指定变量内容了"

    [root@ansiblehost 16:15:27  ansible.yaml]#"ansible-playbook useradd.yml"
        PLAY [web] *************************************************************************************************************************************

        TASK [Gathering Facts] *************************************************************************************************************************
        ok: [192.168.136.5]
        ok: [192.168.136.6]

        TASK [create group] ****************************************************************************************************************************
        ok: [192.168.136.6]
        ok: [192.168.136.5]

        TASK [create user] *****************************************************************************************************************************
        ok: [192.168.136.6]
        changed: [192.168.136.5]

        PLAY RECAP *************************************************************************************************************************************
        192.168.136.5              : ok=3    changed=1    unreachable=0    failed=0   
        192.168.136.6              : ok=3    changed=0    unreachable=0    failed=0   

(三):使用setup中自带的变量
看下面的例子:

---
- hosts: web
  remote_user: root

  tasks:
    - name: create file
      file: name=/app/{{ ansible_hostname }}.txt state=touch
   [root@ansiblehost 16:27:44  ansible.yaml]#ansible web -a 'ls -l /app/'
    192.168.136.5 | SUCCESS | rc=0 >>
    total 0
    -rw-r--r-- 1 root  root  0 Jan 18 16:26 "localhost.txt" #利用变量创建的变量
    drwxr-xr-x 2 user1 root 62 Jan 18 07:05 user1

    192.168.136.6 | SUCCESS | rc=0 >>
    total 4
    -rw-r--r-- 1 root  root    0 Jan 14 09:40 "centos6-102.txt" #利用变量创建出的文件  
    -rw-r--r-- 1 root  root    0 Jan 14 01:49 testsrv
    drwx------ 4 user1 root 4096 Jan 14 09:15 user1

playbook中使用的变量ansible_hostname就是setpu模块中过滤出来的变量,这种方法让我们可以不用定义变量,直接所使用setup模块里自带的变量。

(四):/etc/ansible/hosts主机清单配置文件中定义变量

1)定义普通变量;普通变量就是对每一个主机单独定义一个变量只能这个主机使用
请看下面的例子:

[web]
192.168.136.6 hostname="httpd"
这个可以在命令行调用  
#这个例子就是利用在主机清单中定义的变量修改主机名
[root@ansiblehost 17:06:29  ansible.yaml]#ansible 192.168.136.6 -m hostname  -a 'name={{ hostname }}'
192.168.136.6 | SUCCESS => {
    "ansible_facts": {
    "ansible_domain": "magedu.com", 
    "ansible_fqdn": "centos6-102.magedu.com", 
    "ansible_hostname": "httpd", 
    "ansible_nodename": "httpd"
}, 
"changed": true, 
"name": "httpd"

}

2)在/etc/ansible/hosts文件中定义公共变量;公共变量就是一个主机组定义一个共有的变量

看下面的例子:

[web]
192.168.136.6
192.168.136.5

"#中括号里的【web】表示上面的web组,重点是冒号后面的vars加上这个关键次就表示对上面的web组创建共有变量。变量可以有多个"
[web:vars] 
hostname=websrvs
port=80

利用变量更改主机名:

[root@ansiblehost 17:24:39  ansible.yaml]#ansible web -m hostname -C -a 'name="{{ hostname }}-{{ port }}"'
192.168.136.6 | SUCCESS => {
    "ansible_facts": {
        "ansible_domain": "", 
        "ansible_fqdn": "httpd", 
        "ansible_hostname": "websrvs-80", 
        "ansible_nodename": "websrvs-80"
    }, 
    "changed": true, 
    "name": "websrvs-80"
}
192.168.136.5 | SUCCESS => {
    "ansible_facts": {
        "ansible_domain": "localdomain", 
        "ansible_fqdn": "localhost.localdomain", 
        "ansible_hostname": "websrvs-80", 
        "ansible_nodename": "websrvs-80"
    }, 
    "changed": true, 
    "name": "websrvs-80"
}

4)在playbook里面调用在/etc/ansible/hosts文件中定义的变量

看下面的例子:

    [web]
    192.168.136.6
    192.168.136.5

    [web:vars]
    host=websrvs
    port=8080

    ---
    - hosts: web
      remote_user: root

      tasks:
        - name: set hostname
          hostname: name={{ host }}-{{ port }}

5),在一个单独的文件存放playbok变量与值
创建一个文件:

   touch var.txt
    vim var.txt
      文件格式:
        var1: xiaoming
        var2: xiaohang

6)在playbook调用文件var.txt里的变量

    #变量文件内容
     var1: xiaoming
     var2: httpd

    playboot内容
    ---
    - hosts: web
      remote_user: root
      vars_files:
        - var.yml

      tasks:
        - name: create user
          user: name={{ var1 }} shell=/bin/bash home=/app/{{ var1 }}
        - name: create file
          file: name=/app/{{ var2 }}.txt  state=touch mode=644 owner=wang

    #最后命令执行结果
      1)创建用户结果
      [root@ansiblehost 19:10:36  ansible.yaml]#ansible web -a 'tail -n1 /etc/passwd'
        192.168.136.6 | SUCCESS | rc=0 >>
        xiaoming2:x:503:503::/app/xiaoming:/bin/bash

        192.168.136.5 | SUCCESS | rc=0 >>
        xiaoming2:x:1002:1002::/app/xiaoming:/bin/bash

      2)创建文件的结果
      [root@ansiblehost 18:45:55  ansible.yaml]#ansible web -a 'ls -l /app' 
        192.168.136.5 | SUCCESS | rc=0 >>
        total 0
        -rw------- 1 root     root      0 Jan 18 18:45 httpd.txt
        drwxr-xr-x 2 xiaoming xiaoming 62 Jan 18 07:05 xiaoming

        192.168.136.6 | SUCCESS | rc=0 >>
        total 4
        -rw------- 1 root     root        0 Jan 14 11:59 httpd.txt
        drwxr-xr-x 4 xiaoming xiaoming 4096 Dec 17 17:40 xiaoming

template模板模块

1)文本文件,嵌套有脚本(使用模板编程语言编写)  2)Jinja2语言,使用字面量,有下面形式 
    ①:字符串:使用单引号或双引号 
    ②:数字:整数,浮点数 
    ③:列表:[item1, item2, ...] 
    ④:元组:(item1, item2, ...) 
    ⑤:字典:{key1:value1, key2:value2, ...} ⑥:布尔型:true/false  
3)算术运算:+, -, *, /, //<整除>, %, **<次方> 
4)比较操作:==, !=, >, >=, <, <= 
5)逻辑运算:and, or, not  
6)流表达式:For If  When 

功能:

templates功能:根据模块文件动态生成对应的配置文件
templates文件必须存放于templates目录下,且命名为 .j2 结尾

yaml/yml 文件需和templates目录平级,目录结构如下:

./     
├── temnginx.yml #调用temnginx模块的文件必须跟真正存放模板的文件属于平级关系
└── templates         
    └── nginx.conf.j2 #模板文件

使用templates模块功能需要创建一个目录名为templates,然后在这个目录下存放模板文件,而文件名推荐改下后缀<.j2>

示例:利用templates同步nginx配置文件
1)准备templates/nginx.conf.j2文件

2)编辑playbook文件
vim temnginx.yml
    ---
    - hosts: web
      remote_user: root

      tasks:
        - name: install nginx
          yum: name=nginx
        #调用template模块,src表示本机的template目录下的某一个文件 ,dest表示远程被控主机的存放路径,做用类似copy模块,但是template模板文件里可以支持变量以及算数运算
        "- name: templates
          template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf"
        - name: start nginx
          service: name=nginx state=started
这个例子作用就是:
 第一步:在远程被控主机安装nginx
 第二步:将本机template模板文件复制到远程被控主机上
 第三步:启动nginx服务

可能有时候我们需要判断某一个版本,在复制某一个文件到对应的机器上,这时候可以加上when这个关键词,就可以帮我们来解决这个问题,

"when关键字的用法,作用类似一判断当满足某一个条件时就执行这个动作"

看下面的例子

[root@ansiblehost 19:36:47  ansible.yaml]#ls templates/
nginx-6.conf.j2  nginx-7.conf.j2

[root@ansiblehost 19:36:54  ansible.yaml]#cat temnginx.yml 
---
- hosts: web
  remote_user: root

  tasks:
    - name: install nginx
      yum: name=nginx

    - name: templates 6
      template: src=nginx-6.conf.j2 dest=/etc/nginx/nginx.conf
      #这是setup模块里的一个存放主版本的变量"ansible_distribution_major_version" 而"=="就表示判断的意思,作用就是判断如果主版本号是否等于6
      when: ansible_distribution_major_version=="6"

    - name: templates 7
      template: src=nginx-7.conf.j2 dest=/etc/nginx/nginx.conf
      #同上面的when作用相同
      when: ansible_distribution_major_version=="7"

    - name: start nginx    
      service: name=nginx state=started
上面这个例子:作用是在web这个主机组里面的所有主机上都安装nginx服务,并把判断如果系统是centos6是复制本机上的6的nginx配置文件,同时7也是一样,然后在启动nginx服务

迭代 with_item

迭代的作用就类似与shell里的for循环的作用,with_item会把它里面定义的所有值,每次都传递一个给item这个特殊的变量里面,而with_item理由几个值item就循环几次知道没有才会停止

    请看下面的例子

    [root@ansiblehost 19:44:12  ansible.yaml]#cat user_with_items.yml 
    ---
    - hosts: web 
      remote_user: root 

      tasks:
        - name: add several users
          #item特殊变量代表的就是with_items里面的每一个值
          user: name={{ "item" }} group=root
          #with_items下面的所有值都属于被循环的值
          "with_items":
             - xiaohong
             - xiaolan
执行结果:

        [root@ansiblehost 19:43:59  ansible.yaml]#ansible web -a 'tail -n2 /etc/passwd'
        192.168.136.6 | SUCCESS | rc=0 >>
        xiaohong:x:504:0::/home/xiaohong:/bin/bash
        xiaolan:x:505:0::/home/xiaolan:/bin/bash

        192.168.136.5 | SUCCESS | rc=0 >>
        xiaohong:x:1003:0::/home/xiaohong:/bin/bash
        xiaolan:x:1004:0::/home/xiaolan:/bin/bash
上面的例子作用就是创建两个普通用户,但是使用with_items关键词来完成的

迭代嵌套子变量

看下面的例子:

   [root@ansiblehost 20:34:28  ansible.yaml]#cat user_with_items.yml 
    ---
    - hosts: web 
      remote_user: root 

      tasks:
        - name: add group
          group: name={{ item }} 
          with_items:
             - group1
             - group2
             - group3

        - name: add users
          #item.name <.>后面的name以及group都属于item的自变量
          user: name={{ item.name }} group={{ item.group }}
          #这个写法,迭代里面嵌套了另外的子变量(name)(group)
          with_items:
             - { name: 'laifu3',group: group1 }
             - { name: 'laifu2',group: group2 }
             - { name: 'laifu3',group: group3 }

      [root@ansiblehost 20:38:10  ansible.yaml]#ansible web -m shell -a 'id laifu3'
    192.168.136.6 | SUCCESS | rc=0 >>
    uid=506(laifu3) gid=506(group3) groups=506(group3)

    192.168.136.5 | SUCCESS | rc=0 >>
    uid=1005(laifu3) gid=1005(group3) groups=1005(group3)

    [root@ansiblehost 20:34:01  ansible.yaml]#ansible web -a 'tail -n3 /etc/group'
    192.168.136.6 | SUCCESS | rc=0 >>
    group1:x:504:   
    group2:x:505:
    group3:x:506:

    192.168.136.5 | SUCCESS | rc=0 >>
    group1:x:1003:
    group2:x:1004:
    group3:x:1005:
这个playbook作用就是创建组,再创键新用户,然后再把用户加到创建好的组里面去

playbook中使用template模板文件的for循环 if判断

例子一:for循环

  模板文件  

    [root@ansiblehost 09:26:20  ansible.yaml]#cat templates/for1.conf.j2
    "#for循环的列表ports来自下面的文件中定义的vaes变量中的ports变量的值。而每一次循环都会把ports里的值赋给port这个 变量,因为ports只有3个值所以只会循环3三遍"
    语法要求:
        开头:双{%里面的格式与shell里的格式基本相同%}
        中间:循环内容
        结尾:双{%endfor%}
    {%for port in ports%} 
    server {
        listen {{ port }}
    }
    {%endfor%}

    playbook文件
    [root@ansiblehost 09:26:31  ansible.yaml]#cat for.yml 
    ---
    - hosts: web
      remote_user: root
      vars:
       ports:
         - 81
         - 82
         - 83

      tasks: 
        - name: tesk for
          template: src=for1.conf.j2 dest=/app/for1.conf

    执行结果:

        [root@ansiblehost 09:25:48  ansible.yaml]#ansible web -a 'cat /app/for1.conf'
        192.168.136.6 | SUCCESS | rc=0 >>
        server {
            listen 81
        }
        server {
            listen 82
        }
        server {
            listen 83
        }

        192.168.136.5 | SUCCESS | rc=0 >>
        server {
            listen 81
        }
        server {
            listen 82
        }
        server {
            listen 83
        }

例子二:for循环嵌套子变量

template模板文件
    [root@ansiblehost 09:51:47  ansible.yaml]#cat templates/for2.conf.j2 
    {%for port in ports%}
    server {
        listen {{ port.listen_port }}
    }
    {%endfor%}

playbook文件
    [root@ansiblehost 09:52:07  ansible.yaml]#cat for2.yml 
    ---
    - hosts: web
      remote_user: root
      vars:
       ports:
         - listen_port: 81
         - listen_port: 82
         - listen_port: 83

      tasks: 
        - name: tesk for
          template: src=for2.conf.j2 dest=/app/for2.conf

执行结果:
    [root@ansiblehost 09:51:11  ansible.yaml]#ansible web -a 'cat /app/for2.conf'
    192.168.136.6 | SUCCESS | rc=0 >>
    server {
        listen 81
    }
    server {
        listen 82
    }
    server {
        listen 83
    }

    192.168.136.5 | SUCCESS | rc=0 >>
    server {
        listen 81
    }
    server {
        listen 82
    }
    server {
        listen 83
    }

例子三:for循环嵌套多个元素

template模板文件
    [root@ansiblehost 10:13:41  ansible.yaml]#cat templates/for3.conf.j2 
    {%for vhost in vhosts%}
    server {
        port {{ vhost.port }}
        webserver {{ vhost.name }}
        webdir {{ vhost.root }}
    }
    {%endfor%}

playbook文件
    [root@ansiblehost 10:13:43  ansible.yaml]#cat for3.yml 
    ---
    - hosts: web
      remote_user: root
      vars:
        vhosts:
          - web1:
            port: 81
            name: web1.magedu.com
            root: /app/webroot1
          - web2:
            port: 82
            name: web1.magedu.com
            root: /app/webroot2
          - web3: 
            port: 83
            name: web1.magedu.com
            root: /app/webroot3
      tasks: 
        - name: tesk for
          template: src=for3.conf.j2 dest=/app/for3.conf
执行结果
    [root@ansiblehost 10:12:15  ansible.yaml]#ansible web -a 'cat /app/for3.conf'
    192.168.136.6 | SUCCESS | rc=0 >>
    server {
        port 81
        webserver web1.magedu.com
        webdir /app/webroot1
    }
    server {
        port 82
        webserver web1.magedu.com
        webdir /app/webroot2
    }
    server {
        port 83
        webserver web1.magedu.com
        webdir /app/webroot3
    }

    192.168.136.5 | SUCCESS | rc=0 >>
    server {
        port 81
        webserver web1.magedu.com
        webdir /app/webroot1
    }
    server {
        port 82
        webserver web1.magedu.com
        webdir /app/webroot2
    }
    server {
        port 83
        webserver web1.magedu.com
        webdir /app/webroot3
    }

例子四:for循环嵌套if判断

template模板文件

[root@ansiblehost 10:23:29  ansible.yaml]#cat templates/for4.conf.j2 
{%for vhost in vhosts%}
server {
    port {{ vhost.port }}

#判断循环列表中变量"vhost.name"是否定义,如果定义了就把它的值复制到目标主机,
"语法要求:
开头:{%前面可以任意变量,后面必须写"is defined关键词"%}
中间:执行的任务
结尾:{%endif%}"
"{%if vhost.name is defined %}"
webserver {{ vhost.name }}
"{%endif%}"
webdir {{ vhost.root }}
}
{%endfor%}

playbook文件
[root@ansiblehost 10:23:50 ansible.yaml]#cat for4.yml

- hosts: web
  remote_user: root
  vars:
    vhosts:
      - web1:
        port: 81
        root: /app/webroot1

      - web2:
        port: 82
        name: web1.magedu.com
        root: /app/webroot2

      - web3: 
        port: 83
        root: /app/webroot3
  tasks: 
    - name: tesk for
      template: src=for4.conf.j2 dest=/app/for4.conf

执行结果:
[root@ansiblehost 10:23:04 ansible.yaml]#ansible web -a 'cat /app/for4.conf'
192.168.136.6 | SUCCESS | rc=0 >>
server {
port 81
webdir /app/webroot1
}
server {
port 82
webserver web1.magedu.com
webdir /app/webroot2
}
server {
port 83
webdir /app/webroot3
}

192.168.136.5 | SUCCESS | rc=0 >>
server {
    port 81
    webdir /app/webroot1
}
server {
    port 82
    webserver web1.magedu.com
    webdir /app/webroot2
}
server {
    port 83
    webdir /app/webroot3
}

```