Ansible流程控制-条件_循环_错误处置处罚_包罗导入_块非常处置处罚

[复制链接]
发表于 2026-1-19 01:00:44 | 显示全部楼层 |阅读模式
Ansible流程控制先容

1. 条件判断

when
when用于根据条件决定是否实行使命。
  1. - hosts: all
  2.   tasks:
  3.     - name: Install package only on RedHat
  4.       package:
  5.         name: httpd
  6.         state: present
  7.       when: ansible_os_family == "RedHat"
复制代码
2. 循环

loop
loop用于遍历列表或聚集。
  1. - hosts: all
  2.   tasks:
  3.     - name: Install multiple packages
  4.       package:
  5.         name: "{{ item }}"
  6.         state: present
  7.       loop:
  8.         - vim
  9.         - git
  10.         - curl
复制代码
with_items
较老的循环方式,遍历列表。
  1. - hosts: all
  2.   tasks:
  3.     - name: Install packages using with_items
  4.       package:
  5.         name: "{{ item }}"
  6.         state: present
  7.       with_items:
  8.         - vim
  9.         - git
复制代码
with_dict
用于遍历字典。
  1. - hosts: all
  2.   tasks:
  3.     - name: Print dictionary items
  4.       debug:
  5.         msg: "Key: {{ item.key }}, Value: {{ item.value }}"
  6.       with_dict:
  7.         item1: value1
  8.         item2: value2
复制代码
with_sequence
天生序列并遍历。
  1. - hosts: all
  2.   tasks:
  3.     - name: Create files using with_sequence
  4.       file:
  5.         path: "/tmp/file{{ item }}"
  6.         state: touch
  7.       with_sequence: start=1 end=5
复制代码
with_fileglob
遍历匹配文件名的文件。
  1. - hosts: all
  2.   tasks:
  3.     - name: Read files from directory
  4.       debug:
  5.         msg: "Found file: {{ item }}"
  6.       with_fileglob:
  7.         - /tmp/*.txt
复制代码
with_together
并行遍历多个列表。
  1. - hosts: all
  2.   tasks:
  3.     - name: Combine items from two lists
  4.       debug:
  5.         msg: "Item from list1: {{ item.0 }}, Item from list2: {{ item.1 }}"
  6.       with_together:
  7.         - ['a', 'b', 'c']
  8.         - [1, 2, 3]
复制代码
3. 循环控制

loop_control
提供更细粒度控制。
  1. - hosts: all
  2.   tasks:
  3.     - name: Custom loop variable
  4.       debug:
  5.         msg: "Current item: {{ custom_item }}"
  6.       loop:
  7.         - a
  8.         - b
  9.       loop_control:
  10.         loop_var: custom_item
复制代码
在Ansible中,loop_control是一个用于提供循环过程中更细粒度控制的选项。它允许你自界说循环变量名、设置循环的标签、限定循环的并行实行数量等。这使得在处置处罚循环时可以更加机动和精确。
下面是一个使用loop_control的示例,展示了怎样自界说循环变量名:
  1. - hosts: all
  2.   tasks:
  3.     - name: Custom loop variable
  4.       debug:
  5.         msg: "Current item: {{ custom_item }}"
  6.       loop:
  7.         - a
  8.         - b
  9.       loop_control:
  10.         loop_var: custom_item
复制代码
在这个例子中,loop_control用于指定循环变量的名称。默认情况下,Ansible中的循环变量名为item,但通过loop_control,你可以将其更改为任何你想要的名称,比如这里的custom_item。如许,在循环体内部,就可以使用{{ custom_item }}来引用当前迭代的元素。
这种自界说循环变量的功能在必要在循环内部引用多个循环变量或在复杂的脚本中进步代码的可读性时非常有效。通过loop_control,你可以更精确地控制循环的举动,使其更符合你的特定需求。
4. 错误处置处罚

ignore_errors
在使命失败时继承实行后续使命。
  1. - hosts: all
  2.   tasks:
  3.     - name: Failing task
  4.       command: /bin/false
  5.       ignore_errors: yes
  6.     - name: This will run despite the previous failure
  7.       debug:
  8.         msg: "The previous task failed, but this still runs."
复制代码
failed_when
自界说使命失败的条件。
  1. - hosts: all
  2.   tasks:
  3.     - name: Custom failure condition
  4.       command: /bin/true
  5.       register: result
  6.     - name: Check the result
  7.       debug:
  8.         msg: "This task will fail if the command did not return 0."
  9.       failed_when: result.rc != 0
复制代码
5. 包罗和导入

include_tasks
动态包罗使命文件。
  1. - hosts: all
  2.   tasks:
  3.     - name: Include tasks based on a condition
  4.       include_tasks: my_tasks.yml
  5.       when: ansible_os_family == "Debian"
复制代码
import_tasks
静态导入使命文件。
  1. - hosts: all
  2.   tasks:
  3.     - import_tasks: my_imported_tasks.yml
复制代码
6. 块和非常处置处罚

block
将一组使命组合在一起,便于管理和错误处置处罚。
  1. - hosts: all
  2.   tasks:
  3.     - block:
  4.         - name: Task 1
  5.           command: /bin/true
  6.         - name: Task 2
  7.           command: /bin/false
  8.       rescue:
  9.         - name: Handle failure
  10.           debug:
  11.             msg: "One of the tasks failed, handling the error."
  12.      # 当block中的任务错误时,会执行rescue中的任务
复制代码
7. 脚色的流程控制

在脚色中构造和控制使命实行。
  1. # roles/myrole/tasks/main.yml
  2. - name: Task in role
  3.   command: /bin/echo "This is a task in a role"
  4. - include_tasks: another_tasks.yml
复制代码
这些示例展示了Ansible中的各种流程控制功能,资助你在主动化使命和设置管理中实现更复杂的逻辑。


*include_tasks、import_tasks_include之间的区别

   在Ansible中,include_tasks、import_tasks和include指令都是用来构造和重用代码的,但它们在用法和上下文中有一些区别:
  

  • include_tasks

    • 动态包罗使命文件:include_tasks可以根据条件动态地包罗一个使命列表文件。
    • 使用场景:当你必要基于某些条件(如使用体系、情况变量等)来决定是否实行一组使命时,可以使用include_tasks。

  

  • 示例
    1. - hosts: all
    2.   tasks:
    3.     - name: Include tasks based on a condition
    4.       include_tasks: my_tasks.yml
    5.       when: ansible_os_family == "Debian"
    复制代码
   

  • import_tasks

    • 静态导入使命文件:import_tasks用于静态地导入一个使命列表文件,它不会根据条件来决定是否导入。
    • 使用场景:当你必要在当前使命列表中静态地包罗一组使命时,可以使用import_tasks。
    • 示例

  1. ```yaml
  2. - hosts: all
  3.    tasks:
  4.      - import_tasks: my_imported_tasks.yml
  5. ```
复制代码
  

  • include

    • 包罗变量或文件:include用于包罗变量文件或脚色文件。
    • 使用场景:当你必要在当前脚本中包罗一个变量文件或脚色文件时,可以使用include。
    • 示例

  1. ```yaml
  2. - hosts: all
  3.    vars_files:
  4.      - vars.yml
  5. ```
复制代码

   这些指令在Ansible中提供了机动的代码构造和重用机制,使得脚本更加模块化和可维护。
  include指令在Ansible中重要用于包罗变量文件、使命文件、模板文件等,它的作用不但限于使命列表,还包罗其他资源范例。以下是include指令的一些额外阐明:
  

  • 变量文件

    • include_vars:用于包罗变量文件,这些变量可以在使掷中使用。
    • 示例:

  1. ```yaml
  2. - hosts: all
  3.    vars_files:
  4.      - vars.yml
  5. ```
复制代码
  

  • 使命文件

    • 固然include_tasks用于动态包罗使命文件,但include也可以用于静态包罗使命文件,这通常用于脚色中。
    • 示例:

  1. ```yaml
  2. - include: tasks/main.yml
  3. ```
复制代码
  

  • 模板文件

    • include可以用于包罗模板文件,这些文件可以用于天生设置文件等。
    • 示例:

  1. ```yaml
  2. - name: Include a template file
  3.    include: my_template.j2
  4. ```
复制代码
  

  • 文件路径

    • include指令支持相对路径和绝对路径。
    • 相对路径是相对于当前脚本文件的路径。
    • 绝对路径是从文件体系的根目次开始的路径。

  • 条件包罗

    • 固然include自己不支持条件包罗,但可以通过在包罗的文件中使用条件语句来实现条件包罗的结果。

  • 循环包罗

    • include指令可以与loop一起使用,实现循环包罗文件。
    • 示例:
      1. - hosts: all
      2.   tasks:
      3.     - name: Include tasks from a list
      4.       include: "{{ item }}"
      5.       with_first_found:
      6.         - "tasks/{{ ansible_os_family }}.yml"
      7.         - "tasks/default.yml"
      复制代码

  • 错误处置处罚

    • 如果include指定的文件不存在,Ansible会报错。

  • 脚色中的使用

    • 在Ansible脚色中,include指令通常用于包罗使命文件、变量文件或模板文件。

  • 静态与动态

    • include通常是静态的,意味着它在脚本剖析时就确定了要包罗的文件。
    • 与include_tasks相比,include不提供动态包罗的本事。

  • 与import的区别

    • import指令在Ansible的早期版本中用于包罗使命,但现在保举使用import_tasks。

  include指令是Ansible脚本编写中非常机动和强大的工具,可以有效地构造和管理代码。
  条件语句再细说

使用when指令
且、或、非、是

且:and
或:or
非:!=
是:==

含糊条件

使用is match
  1. ...
  2. yum:
  3.   name:
  4.     - xxx
  5.     - xxx
  6. when: ansible_hostname is match 'web*'
  7. ...
复制代码
when指令的具体使用方法

在Ansible中,when指令用于条件判断,允许你根据特定条件决定是否实行某个使命。它可以根据变量的值、注册的结果或其他条件举行判断。

  • 根本语法
    1. - name: Task name
    2.   command: your_command
    3.   when: condition
    复制代码
  • 条件可以是

    • 变量比力:when: variable_name == 'value'
    • 布尔值:when: some_boolean_variable
    • 列表查抄:when: item in my_list
    • 注册变量结果:when: result_variable is succeeded

以下是一个简朴示例,展示怎样使用when指令:
  1. ---
  2. - hosts: all
  3.   tasks:
  4.     - name: Check if a file exists
  5.       stat:
  6.         path: /tmp/myfile.txt
  7.       register: file_stat
  8.     - name: Create a file if it does not exist
  9.       file:
  10.         path: /tmp/myfile.txt
  11.         state: touch
  12.       when: not file_stat.stat.exists
  13.     - name: Notify if the file was created
  14.       debug:
  15.         msg: "The file was created!"
  16.       when: file_stat.stat.exists == false
复制代码
上面是示例的表明:

  • stat模块:查抄/tmp/myfile.txt是否存在,并将结果注册到file_stat。
  • 创建文件使命:仅在文件不存在时实行(when: not file_stat.stat.exists)。
  • 调试使命:如果文件被创建,输出一条消息。


变量比力
假设你有一个变量my_os,它存储了目的呆板的使用体系范例。你只想在使用体系为Ubuntu时实行某个使命。
  1. - name: Install package if OS is Ubuntu
  2.   apt: name=nginx state=present
  3.   when: my_os == 'Ubuntu'
复制代码
布尔值
如果你有一个布尔变量install_nginx,你想根据这个变量的值来决定是否安装Nginx。
  1. - name: Install Nginx if the condition is true
  2.   command: apt-get install nginx
  3.   when: install_nginx
复制代码
列表查抄
如果你有一个列表packages_to_install,而且你只想在列表中包罗nginx时安装它。
  1. - name: Install nginx if it is in the list
  2.   command: apt-get install nginx
  3.   when: 'nginx' in packages_to_install
复制代码
注册变量结果
假设你已经运行了一个使命来安装某些软件包,而且你将结果注册到了变量install_result中。只有当安装乐成时,你才想实行下一个使命。
  1. - name: Install some software
  2.   command: apt-get install some_software
  3.   register: install_result
  4. - name: Run configuration script if software installed successfully
  5.   command: ./configure_software.sh
  6.   when: install_result is succeeded
复制代码
组合条件
你也可以组合多个条件来创建更复杂的逻辑。
  1. - name: Install nginx only if it's not installed and the OS is Ubuntu
  2.   command: apt-get install nginx
  3.   when: nginx_not_installed and my_os == 'Ubuntu'
复制代码
在这个例子中,nginx_not_installed是一个布尔变量,表现Nginx是否已经安装。只有当Nginx未安装而且使用体系是Ubuntu时,才会实行安装Nginx的下令。


再探究一下Ansible中的“列表查抄”和“注册变量”的条件:
一、 列表查抄(List Checking)
在Ansible中,你可以使用in关键字来查抄一个值是否存在于一个列表中。这在你必要基于一组预界说的值来决定是否实行某个使命时非常有效。
比方,假设你有一个变量my_list,它是一个包罗多个元素的列表,你想查抄某个特定的值item是否在这个列表中:
  1. - name: Check if item is in the list
  2.   command: echo "Item is in the list"
  3.   when: item in my_list
复制代码
在这个例子中,如果变量item的值存在于变量my_list中,那么echo "Item is in the list"下令将被实行。

二、 注册变量(Registered Variables)
在Ansible中,你可以使用register关键字来生存使命的输出,如许你就可以在后续的使掷中引用这个输出。注册的变量通常用于条件判断,以决定是否实行后续的使命。
比方,你有一个使命,它实行一个下令并注册了其结果:
  1. - name: Run a command and register the result
  2.   command: ls /nonexistent
  3.   register: command_result
  4.   ignore_errors: yes
复制代码
在这个例子中,ignore_errors: yes告诉Ansible纵然命令失败也继承实行。register: command_result将下令的输出生存到变量command_result中。
然后,你可以使用when语句来查抄这个注册变量的状态,并决定是否实行后续的使命:
  1. - name: Check if the command was successful
  2.   command: echo "Command was successful"
  3.   when: command_result is succeeded
复制代码
在这个例子中,如果ls /nonexistent下令乐成实行(纵然它现实上没有找到任何文件,由于我们使用了ignore_errors: yes),那么echo "Command was successful"下令将被实行。
注册变量可以包罗多种信息,包罗下令的退出状态、尺度输出和尺度错误输出等。你可以根据这些信息来构建复杂的条件判断。比方,你可以查抄下令是否失败:
  1. - name: Check if the command failed
  2.   command: echo "Command failed"
  3.   when: command_result is failed
复制代码
在这个例子中,如果ls /nonexistent下令失败(这是预期的,由于/nonexistent目次不存在),那么echo "Command failed"下令将被实行。


更多的例子:
例 1:根据使用体系范例实行使命
  1. ---
  2. - hosts: all
  3.   tasks:
  4.     - name: Install packages based on OS
  5.       package:
  6.         name:
  7.           - "{{ item }}"
  8.         state: present
  9.       loop:
  10.         - vim
  11.         - wget
  12.       when: ansible_os_family == 'Debian'
复制代码
表明:
这个使命会在Debian家属的使用体系(如Ubuntu)上安装vim和wget,只在when条件满足时实行。

例 2:根据变量值举行条件判断
  1. ---
  2. - hosts: all
  3.   vars:
  4.     environment: production
  5.   tasks:
  6.     - name: Deploy application only in production
  7.       shell: deploy_script.sh
  8.       when: environment == 'production'
复制代码
表明:
此使命仅在environment变量即是production时实行,确保应用步伐只在生产情况中摆设。

例 3:根据注册变量的结果实行使命
  1. ---
  2. - hosts: all
  3.   tasks:
  4.     - name: Check if a service is running
  5.       shell: systemctl is-active my_service
  6.       register: service_status
  7.       ignore_errors: yes
  8.     - name: Start the service if it is not running
  9.       service:
  10.         name: my_service
  11.         state: started
  12.       when: service_status.stdout != 'active'
复制代码
表明:
这个示例起首查抄服务my_service是否正在运行。如果服务未运行(即service_status.stdout不是active),则会启动该服务。

例 4:使用多条件判断
  1. ---
  2. - hosts: all
  3.   vars:
  4.     app_installed: true
  5.     app_version: '1.0.0'
  6.   tasks:
  7.     - name: Run upgrade if app is installed and version is less than 2.0.0
  8.       shell: upgrade_script.sh
  9.       when: app_installed == true and app_version | version_compare('2.0.0', '<')
复制代码
表明:
这个使命在应用步伐已安装且版本低于2.0.0时实行升级脚本。使用version_compare函数举行版本比力。
循环语句再细说

怎样使用

使用item变量团结with_items或loop指令

   在Ansible中,with_items和loop都是用来迭代列表或聚集的指令,但它们有一些具体的区别和使用场景。以下是这两者的具体比力:
  一、 1. 根本概念
  

  • with_items:是Ansible的一个古老的循环结构,用于遍历列表。它的语法较为简朴,但功能较为有限。
  • loop:是Ansible中更当代的循环语法,提供了更强大的功能和机动性。它是with_items的保举更换品。
  二、 2. 语法比力
  with_items 示例
  1. - name: Install packages using with_items
  2.   yum:
  3.     name: "{{ item }}"
  4.     state: present
  5.   with_items:
  6.     - vim
  7.     - wget
  8.     - curl
复制代码
loop 示例
  1. - name: Install packages using loop
  2.   yum:
  3.     name: "{{ item }}"
  4.     state: present
  5.   loop:
  6.     - vim
  7.     - wget
  8.     - curl
复制代码
  三、 3. 功能区别
  

  • 可嵌套

    • loop支持嵌套循环,可以与其他循环指令团结使用,而with_items则不支持。

  1. - name: Loop over a list of lists
  2.   debug:
  3.     msg: "{{ item }}"
  4.   loop:
  5.     - [1, 2, 3]
  6.     - [4, 5, 6]
  7.   loop_control:
  8.     subelements: 0
复制代码
  

  • 更好的变量支持

    • loop可以与其他的控制指令(如loop_control)团结使用,可以更机动地控制迭代过程。

  四、 4. 性能和可读性
  

  • 性能

    • 在某些情况下,loop的性能大概会稍好,特殊是在处置处罚大型数据集时。

  • 可读性

    • loop的语法更划一,易于明确,尤其是在复杂的场景下。保举在新项目中使用loop。

  五、 5. 使用发起
  

  • 保举使用loop:由于loop是Ansible的当代循环方式,功能更强大且机动性更高,因此在新项目中应优先选择loop。
  • with_items的使用:对于一些简朴的使命,可以继承使用with_items,但应留意其在未来大概会被弃用。
  六、 总结
  只管with_items和loop都可以实现相似的功能,loop在机动性、功能和可读性方面具有显着的上风。因此,发起在编写Ansible脚本时优先选择使用loop。
  loop需在安装Ansible2X版本后才气使用
item变量有固定子元素?

   在Ansible中,item变量通常用于循环(如with_items或loop)来表现当前迭代的元素。具体来说,item可以用来访问循环中每个元素的子元素,特殊是在处置处罚字典或列表时。
  

  • 列表中的字典
  1. - name: Example with list of dictionaries
  2.   debug:
  3.     msg: "Name is {{ item.name }}, Age is {{ item.age }}"
  4.   loop:
  5.     - { name: 'Alice', age: 30 }
  6.     - { name: 'Bob', age: 25 }
复制代码
  在这个例子中,item是每个字典,可以通过item.name和item.age访问它的子元素。
  

  • 字典中的列表
  1. - name: Example with dictionary containing a list
  2.   debug:
  3.     msg: "Fruit is {{ item }} and Price is {{ prices[item] }}"
  4.   vars:
  5.     prices:
  6.       apple: 1.2
  7.       banana: 0.5
  8.   loop:
  9.     - apple
  10.     - banana
复制代码
  这里,item是循环中的水果名,使用prices[item]来获取对应代价。
  

  • item是动态的,具体内容取决于当前循环的上下文
  • 可以在循环中使用item的子元素访问来处置处罚复杂数据结构,比方列表和字典的组合。
  • 团结with_items或loop使用,可以使设置和使命更加机动和可重复。
  实例-服务器安装根本情况优化

需求

优化一台刚安装完的捏造机:


  • 改网卡信息
  • 换新堆栈
  • 安装根本软件包(包罗时间同步软件)
  • 优化文件形貌符
  • *防火墙设置
部门实现

换指定新堆栈

  1. ---
  2. - name: the play1
  3.   hosts: all
  4.   become: no
  5.   tasks:
  6.         - name: task:备份原来的仓库
  7.           include: /path/to/task_backup_old_repos.yaml       
  8.     - name: task:安装新仓库
  9.       include: /path/to/task_install_new_repos.yaml
复制代码
可使用get_url加此中的列表循环的方式安装新堆栈:

固然也可以使用shell模块,内里使用wget下令





安装根本软件包

  1. ---
  2. - name: the play1
  3.   hosts: all
  4.   tasks:
  5.     - name: 安装好些个基础软件包
  6.       yum:
  7.         name: {{item}}
  8.         state: present
  9.       loop:
  10.         - chrony
  11.         - aaa
  12.         - bbb
  13.         - ccc
  14.         - ddd
  15.         ...
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!qidao123.com:ToB企服之家,中国第一个企服评测及软件市场,开放入驻,技术点评得现金

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表