在使用ansible作自动化运维的时候,大多数状况下都执行某些任务的时候都须要依赖某个变量的值或者是上一个任务的执行结果。如,根据facts信息中的系统版本相关的信息来肯定使用哪一种包管理器安装软件。Ansible提供when语句,能够控制任务的执行流程。python
一个很简单的when语句的例子:web
tasks: - name: "shutdown Debian flavored systems" command: /sbin/shutdown -t now when: ansible_os_family == "Debian
表示当节点主机系统为Debian的时候,执行关机操做。
sql
在符合语句中也可使用小括号:shell
tasks: - name: "shutdown CentOS 6 and 7 systems" command: /sbin/shutdown -t now when: ansible_distribution == "CentOS" and (ansible_distribution_major_version == "6" or ansible_distribution_major_version == "7")
在`when`语句中也可使用过滤器。如,咱们想跳过一个语句执行中的错误,可是后续的任务的执行须要由该任务是否成功执行决定:运维
tasks: - command: /bin/false register: result ignore_errors: True - command: /bin/something when: result|failed - command: /bin/something_else when: result|success - command: /bin/still/something_else when: result|skipped
有时候须要将一个字符串的变量转换为整数来进行数字比较:ide
tasks: - shell: echo "only on Red Hat 6, derivatives, and later" when: ansible_os_family == "RedHat" and ansible_lsb.major_release|int >= 6
在playbooks和inventory中定义的变量均可以使用,如,须要根据一个变量的bool值决定是否执行该任务:测试
vars: epic: true
条件语句:
ui
tasks: - shell: echo "This certainly is epic!" when: epic
或:
this
tasks: - shell: echo "This certainly isn't epic!" when: not epic
若是引用的变量没有被定义,使用Jinja2的`defined`测试,能够跳过或者是抛出错误:spa
tasks: - shell: echo "I've got '{{ foo }}' and am not afraid to use it!" when: foo is defined - fail: msg="Bailing out. this play requires 'bar'" when: bar is not defined
当`when`和`with_items`一块儿使用的时候,每一个项都会单独被`when`语句处理:
tasks: - command: echo {{ item }} with_items: [ 0, 2, 4, 6, 8, 10 ] when: item > 5
示例:
[root@web1 ~]# cat /etc/ansible/when.yml --- - hosts: webservers remote_user: root tasks: - command: echo {{ item }} with_items: [ 1,2,3,4,5,6,8,10] when: item > 5 [root@web1 ~]# ansible-playbook /etc/ansible/when.yml PLAY [webservers] ************************************************************* GATHERING FACTS *************************************************************** ok: [192.168.1.65] TASK: [command echo {{ item }}] *********************************************** skipping: [192.168.1.65] => (item=1) skipping: [192.168.1.65] => (item=2) skipping: [192.168.1.65] => (item=3) skipping: [192.168.1.65] => (item=4) skipping: [192.168.1.65] => (item=5) changed: [192.168.1.65] => (item=6) changed: [192.168.1.65] => (item=8) changed: [192.168.1.65] => (item=10) PLAY RECAP ******************************************************************** 192.168.1.65 : ok=2 changed=1 unreachable=0 failed=0
若是须要的话,也能够返回自定义的facts给控制节点。返回的自定义的facts变量也能够用做下个任务的执行条件:
tasks: - name: gather site specific fact data action: site_facts - command: /usr/bin/thingy when: my_custom_fact_just_retrieved_from_the_remote_system == '1234'
在角色和包含中使用when
若是有多个任务都须要使用同一个条件语句控制。能够将这些任务打包到一个单独的任务文件中,而后使用`include`包含和`when`条件语句。条件语句只对包含任务文件起做用,对包含playbook文件不起做用。指定的条件语句会做用到所包含的每一个任务上:
- include: tasks/sometasks.yml when: "'reticulating splines' in output"
角色中使用when
- hosts: webservers roles: - { role: debian_stock_config, when: ansible_os_family == 'Debian' }
注册变量
在playbook中将某个命令运行的结果保存起来,提供给后续任务使用。如,经过command模块来判断远程节点上某个文件是否存在或者经过执行某个命令的获取其返回结果,并保存起来,下个任务根据获取的变量值来决定执行的具体操做。
register关键字能够将任务执行结果保存到一个变量中,该变量能够在模板或者playbooks文件中使用:
- name: test play hosts: all tasks: - shell: cat /etc/motd register: motd_contents - shell: echo "motd contains the word hi" when: motd_contents.stdout.find('hi') != -1
上边中的例子中,经过注册变量访问返回的内容,`stdout`里面保存了命令的标准输出内容。注册变量还可使用在`with_items`中,若是其保存的内容能够转换为列表,或者内容自己就是个列表。若是命令的输出自己就是列表,能够经过`stdout_lines`访问:
- name: registered variable usage as a with_items list hosts: all tasks: - name: retrieve the list of home directories command: ls /home register: home_dirs - name: add home dirs to the backup spooler file: path=/mnt/bkspool/{{ item }} src=/home/{{ item }} state=link with_items: home_dirs.stdout_lines # same as with_items: home_dirs.stdout.split()
示例:
[root@web1 ~]# cat /etc/ansible/rewith.yml --- - hosts: webservers remote_user: root tasks: - name: list of home dir command: ls /home register: home_dirs - name: add home dirs to the backup file: path=/tmp/back/{{ item }} src=/home/{{ item }} state=link with_items: home_dirs.stdout_lines [root@web1 ~]# ansible-playbook /etc/ansible/rewith.yml PLAY [webservers] ************************************************************* GATHERING FACTS *************************************************************** ok: [192.168.1.65] TASK: [list of home dir] ****************************************************** changed: [192.168.1.65] TASK: [add home dirs to the backup] ******************************************* changed: [192.168.1.65] => (item=1.sql) changed: [192.168.1.65] => (item=1youku.sql) changed: [192.168.1.65] => (item=liuzhenwei) changed: [192.168.1.65] => (item=tom) PLAY RECAP ******************************************************************** 192.168.1.65 : ok=3 changed=2 unreachable=0 failed=0 ###远程节点 [root@db2 ~]# ll /tmp/back total 0 lrwxrwxrwx. 1 root root 11 Aug 4 14:37 1.sql -> /home/1.sql lrwxrwxrwx. 1 root root 16 Aug 4 14:37 1youku.sql -> /home/1youku.sql lrwxrwxrwx. 1 root root 16 Aug 4 14:37 liuzhenwei -> /home/liuzhenwei lrwxrwxrwx. 1 root root 9 Aug 4 14:37 tom -> /home/tom
在ansible中when语句的使用仍是比较多的,它能够用来控制playbooks中任务的执行流程。相似于程序中的条件语句同样,使得ansible能够更好的按照运维人员的意愿来对远程节点执行特定的操做。