百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

Ansible-playbook的循环和条件判断

wxin55 2024-11-24 22:42 8 浏览 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的层级,他们是相同层级的

相关推荐

ES6中 Promise的使用场景?(es6promise用法例子)

一、介绍Promise,译为承诺,是异步编程的一种解决方案,比传统的解决方案(回调函数)更加合理和更加强大在以往我们如果处理多层异步操作,我们往往会像下面那样编写我们的代码doSomething(f...

JavaScript 对 Promise 并发的处理方法

Promise对象代表一个未来的值,它有三种状态:pending待定,这是Promise的初始状态,它可能成功,也可能失败,前途未卜fulfilled已完成,这是一种成功的状态,此时可以获取...

Promise的九大方法(promise的实例方法)

1、promise.resolv静态方法Promise.resolve(value)可以认为是newPromise方法的语法糖,比如Promise.resolve(42)可以认为是以下代码的语...

360前端一面~面试题解析(360前端开发面试题)

1.组件库按需加载怎么做的,具体打包配了什么-按需加载实现:借助打包工具(如Webpack的require.context或ES模块动态导入),在使用组件时才引入对应的代码。例如在V...

前端面试-Promise 的 finally 怎么实现的?如何在工作中使用?

Promise的finally方法是一个非常有用的工具,它无论Promise是成功(fulfilled)还是失败(rejected)都会执行,且不改变Promise的最终结果。它的实现原...

最简单手写Promise,30行代码理解Promise核心原理和发布订阅模式

看了全网手写Promise的,大部分对于新手还是比较难理解的,其中几个比较难的点:状态还未改变时通过发布订阅模式去收集事件实例化的时候通过调用构造函数里传出来的方法去修改类里面的状态,这个叫Re...

前端分享-Promise可以中途取消啦(promise可以取消吗)

传统Promise就像一台需要手动组装的设备,每次使用都要重新接线。而Promise.withResolvers的出现,相当于给开发者发了一个智能遥控器,可以随时随地控制异步操作。它解决了三大...

手写 Promise(手写输入法 中文)

前言都2020年了,Promise大家肯定都在用了,但是估计很多人对其原理还是一知半解,今天就让我们一起实现一个符合PromiseA+规范的Promise。附PromiseA+规范地址...

什么是 Promise.allSettled()!新手老手都要会?

Promise.allSettled()方法返回一个在所有给定的promise都已经fulfilled或rejected后的promise,并带有一个对象数组,每个对象表示对应的pr...

前端面试-关于Promise解析与高频面试题示范

Promise是啥,直接上图:Promise就是处理异步函数的API,它可以包裹一个异步函数,在异步函数完成时抛出完成状态,让代码结束远古时无限回掉的窘境。配合async/await语法糖,可...

宇宙厂:为什么前端离不开 Promise.withResolvers() ?

大家好,很高兴又见面了,我是"高级前端进阶",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发。1.为什么需要Promise.with...

Promise 新增了一个超实用的 API!

在JavaScript的世界里,Promise一直是处理异步操作的神器。而现在,随着ES2025的发布,Promise又迎来了一个超实用的新成员——Promise.try()!这个新方法简...

一次搞懂 Promise 异步处理(promise 异步顺序执行)

PromisePromise就像这个词的表面意识一样,表示一种承诺、许诺,会在后面给出一个结果,成功或者失败。现在已经成为了主流的异步编程的操作方式,写进了标准里面。状态Promise有且仅有...

Promise 核心机制详解(promise机制的实现原理)

一、Promise的核心状态机Promise本质上是一个状态机,其行为由内部状态严格管控。每个Promise实例在创建时处于Pending(等待)状态,此时异步操作尚未完成。当异步操作成功...

javascript——Promise(js实现promise)

1.PromiseES6开始支持,Promise对象用于一个异步操作的最终完成(包括成功和失败)及结果值的表示。简单说就是处理异步请求的。之所以叫Promise,就是我承诺,如果成功则怎么处理,失败怎...

取消回复欢迎 发表评论: