编程技术分享平台

网站首页 > 技术教程 正文

Ansible-playbook的循环和条件判断

xnh888 2024-10-16 17:52:57 技术教程 21 ℃ 0 评论

playbook的循环

学过编程的同学知道在编程过程中经常会用到for 循环、while循环来处理数据。在ansible-playbook中也有循环,虽然没有那么复杂,但是用起来很方便。

细心的同学马上想起在讲变量的用到过循环。不记得也没关系,我们再来看一下

---
- hosts: 192.168.233.167
  remote_user: root
  vars:
    ip: "{{ ansible_default_ipv4['address'] }}"
    family: "{{ ansible_os_family }}"
    vers: "{{ ansible_distribution_version }}"
  tasks:
  - name: show ansible vars 
    debug:
      msg: "{{ item }}"
    loop:
      - "{{ ip }}"
      - "{{ family }}"
      - "{{ vers }}"

通过关键字loop 对 ip、family、vers三个变量进行循环,除了loop还可以使用with_items达到同样的循环效果。只要把上的loop改成with_items。

返回的结果也是分别显示出来

[root@localhost ~]# ansible-playbook loop.yaml 

PLAY [192.168.233.167] *********************************************************************************************************

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

TASK [show ansible vars] *********************************************************************************************************
ok: [192.168.233.167] => (item=192.168.233.167) => {
    "msg": "192.168.233.167"
}
ok: [192.168.233.167] => (item=Debian) => {
    "msg": "Debian"
}
ok: [192.168.233.167] => (item=16.04) => {
    "msg": "16.04"
}

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

再来一个应用场景,需要删除多个文件

如果不使用循环,那么删除3个文件就要写3个任务,使用循环的话一个任务就可以了

示例如下:

---
- hosts: 192.168.233.167
  remote_user: root
  tasks:
  - name: remove install file
    file:
      path: "{{ item.filepath }}"
      state: absent
    with_items:
      - { filepath: "/root/test_one" }
      - { filepath: "/root/test_two" }

再来一个更复杂一点的场景,需要拷贝多个文件,但是文件在本地路径不一样,拷到远程机器的目录也不一样。

比如:本地文件/root/A 拷贝到远程机器/home目录下,本地文件/var/B拷贝到远程机器的/tmp目录下,yaml文件示例如下:

---
- hosts: 192.168.233.167
  remote_user: root
  tasks:
  - name: copy file
    copy:
      src: "{{ item.src }}"
      dest: "{{ item.dest}}"
    with_items:
      - { src: "/root/A", dest: "/home/A" }
      - { src: "/var/B", dest: "/tmp/B" }

上面的playbook还可以用另一个关键字with_together来实现,写法有所区别,

示例如下:

---
- hosts: 192.168.233.167
  remote_user: root
  tasks:
  - name: copy file 
    copy:
      src: "{{ item.0 }}"
      dest: "{{ item.1}}"
    with_together:
      - ["/root/A", "/var/B" ]
      - ["/home/A", "/tmp/B" ]

以上两种方法都可以,根据自己喜好即可。

还有一种虽然使用了循环,但是没有用到loopwith_items关键字,我们先来看一下

---
- hosts: 192.168.233.167
  remote_user: root
  tasks:
  - name: remove install file
    apt:
      name: ['vim', 'lrzsz']
      state: present

虽然没有循环的关键字,但是name的值是一个列表,ansible在执行的时候会自动循环


条件判断when

在编程的过程经常会看到用if做条件判断,但是在ansible-playbook中用关键字when来做判断,而它的用法也很简单,先看一个小例子

---
- hosts: 192.168.233.167
  remote_user: root
  tasks: 
  - name: yum install nginx
    yum: 
      name: nginx
      state: present
    when: ansible_distribution == "CentOS"
  - name: apt install nginx
    apt:
      name: nginx
      state: present
    when: ansible_distribution == "Ubuntu"

上面yaml的意思很简单,当远程机器是CentOS的时候使用yum安装nginx,当远程机器是Ubuntu使用apt安装nginx

执行结果如下:

[root@localhost ~]# ansible-playbook when.yaml 

PLAY [192.168.233.167] ********************************************************************************************************************

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

TASK [yum install nginx] ******************************************************************************************************************
skipping: [192.168.233.167]

TASK [apt install nginx] ******************************************************************************************************************
ok: [192.168.233.167]

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

可以看到TASK [yum install nginx]状态的skipping,因为远程机器的系统是Ubuntu的。

这个是最简单的用法用来区分远程机器的不同发行版本。

如果远程机器是CentOS6和CentOS7或者Ubuntu14,16,18的版本我们就需要组合条件来判断了

示例如下:

---
- hosts: 192.168.233.167
  remote_user: root
  tasks: 
  - name: apt install nginx
    apt:
      name: nginx
      state: present
    when: ansible_distribution == "Ubuntu" && ansible_distribution_major_version == "16"

或者换成列表的方式书写条件

---
- hosts: 192.168.233.167
  remote_user: root
  tasks: 
  - name: apt install nginx
    apt:
      name: nginx
      state: present
    when: 
      - ansible_distribution == "Ubuntu" 
      - ansible_distribution_major_version == "16"

以上两种方式都可以

条件判断常用的就这些,当然还有其他的。感兴趣的同学可以去网上找找

条件判断和block

试想,如果每个任务都写一个when去判断,这种做法是不是很麻烦呢。一个两个任务还行,十个八个呢?

先不管写那么多的when判断语句累不累,一下子写那么多判断语句,自己估计看着的都傻了吧。

还好ansible的开发者已经帮忙我们想好解决方案了,就是用block关键字把符合条件的任务当作"块"

只要条件符合,"块"内的所有任务都会执行,而不需要每个任务都去写个判断

且看示例:

---
- hosts: 192.168.233.167
  remote_user: root
  tasks:
  - block:
    - name: yum install nginx
      yum: 
        name: nginx
        state: present
    - name: yum install vim
      yum:
        name: vim
        state: present
    when: ansible_distribution == "CentOS" #注意when的层级,是和block同一层级
  - block:
    - name: apt install nginx
      apt:
        name: nginx
        state: present
    - name: apt install vim
      apt:
        name: vim
        state: present
    when:  == "Ubuntu"  #注意when的层级,是和block同一层级

这个playbook相信你可以很轻松的看明白是什么意思。

唯一需要注意的就是when和block的层级,他们是相同层级的

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表