Ansible 使用playbook文件运行

本文介绍了如何使用Ansible的playbook进行配置管理和部署。详细阐述了yaml语法规范,包括name、tasks、hosts、variables、templates、handlers和roles等元素,并讲解了执行playbook的命令及其相关选项,如指定主机、用户、传入变量等。示例中展示了使用playbook安装并启动httpd服务的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 ansible playbooks 是使用ansible简单的配置管理部署系统的基础,使用YAML语法格式的配置文件。每一个playbook中包含一系列的任务。使用ansible playbook可以更方便的管理、维护多态主机。

1、yaml语法

    yaml是”YAML Ain't a Markup Language”的缩写,即不是一种标记性语言,它是一种直观的能够被电脑识别的数据序列化格式,是一个可读性高并且容易被人类阅读,容易和脚本语言交互,用来表达资料序列的编程语言。

yaml编写playbook配置文件的规范:

(1)首行以”---”(3个减号)开始,且需顶行首写。

(2)使用#号注释代码。

(3)缩进必须是统一的,不能空格和tab混用

(4)缩进的级别也必须是一致的,同样的缩进代表同样的级别,程序判别配置的级别是通过缩进结合换行来实现的。

(5)YAML文件内容和Linux系统大小写判断方式保持一致,是区别大小写的,k/v的值均需大小写敏感。

(6)k/v的值可同行写也可换行写。同行使用:分隔,换行写需要以”-”分隔。

(7)一个完整的代码块功能需最少元素需包括 name: task。

(8)一个name只能包括一个task

设置设置在.yml文件中Tab键为两个空格

[ansible@server1 ~]$ vim .vimrc
[ansible@server1 ~]$ cat .vimrc 
autocmd filetype yaml setlocal ai ts=2 sw=2 et

2、编写执行ansible playbook

(1)Playbook的主要组成元素

    Hosts: 运行指定任务的目标主机,可以是主机,也可以是主机组,支持正则表达式。

    Tasks: 任务列表,一个playbook配置文件中只能有一个tasks,一个tasks下可以编排多个任务。

    Varniables: 变量

   Templates: 模板,使用templates可以针对不同的主机定制不同参数。

   Handlers: 由特定条件触发的任务,监控资源改变时才会触发,需要配合notify使用。

   Roles: Playbook的按固定目录结构组成

(2)执行playbook

    playbook执行时使用”ansible-playbook”命令后跟写好的yaml格式的playbook文件即可,

但在执行前最好检查下playbook文件语法是否正确 -C

(3)playbook在执行时还可以跟其他的一些选项:

    1)指定执行的主机或主机组:

      playbook在执行时默认会在据配置文件在”hosts”中定义的主机及主机组上去执行,如果不想在配置文件中指定的主机上去执行,可以使用”--limit”指定主机。

2)指定执行playbook的用户

      playbook在执行时默认会使用配置文件中”remote_user”指定的用户去执行,如果想使用别的用户去执行,可以使用参数”--remote-user”指定用户去执行。如果使用参数指定的用户没有做ssh安全认证,则可以使用参数”--ask-sudo-pass”在执行命令时根据提示输入密码即可正常执行。

3)执行playbook时传入变量

   执行playbook时,如果在”hosts”配置文件中及playbook中定义了变量并在执行时参入变量,则优先使用执行时用参数传入的变量,其次使用playbook中的变量,最后使用”inventory”文件中定义的变量。

   在执行playbook时可以使用”-e”选项后跟”key1=value1,key2=value2”的方式传入变量。

)其他可使用的选项

          -i(--inventory=PATH):指定inventory文件,默认文件是/etc/ansible/hosts

         -v(--verbose):显示详细的输出,也可使用-vvvv显示精确到每分钟的输出

         -f(--forks=NUM):指定并发执行的任务数,默认为5,可根据服务器的性能进行调节

         -C(--check):检测模式,playbook中定义的所有任务将在每台远程主机上进行检测,但不执行。


使用ansible playbook安装启动httpd服务

编写playbook.yml文件

---
- hosts: db
  tasks:
    - name: install httpd
      yum:
        name: httpd
        state: present

    - name: copy index.html
      copy:
        src: files/index.html
        dest: /var/www/html/index.html

    - name: configure httpd
      copy:
        src: files/httpd.conf
        dest: /etc/httpd/conf/httpd.conf
        owner: root
        group: root
        mode: 644
      notify: restart httpd

    - name: start httpd  and firewalld
      service:
        name: "{{ item }}"
        state: started
      loop:
        - httpd
        - firewalld

    - name: configure firewalld
      firewalld:
        service: httpd
        permanent: yes
        immediate: yes
        state: enabled

  handlers:
    - name: restart httpd
      service:
        name: httpd
        state: restarted

复制httpd配置文件模板

写入发布页面

检测文件 并 运行

 

server3服务开启

80端口开启

修改files中的配置文件模板端口

重新运行后,server3 端口变为8080

 

<think>我们正在处理用户关于AnsiblePlaybook提取文件中特定字段的问题。根据用户需求,我们需要从文件中提取某个字段。常见的方法包括使用lineinfile模块、shell模块结合grep/awk等命令、或者使用register和set_fact来捕获并处理输出。考虑到用户可能希望避免使用shell模块(以保持Playbook的幂等性),我们可以考虑使用ansible.builtin.shell或ansible.builtin.command模块执行命令来提取字段,然后使用register捕获输出,再通过set_fact来设置变量。另一种方法是使用ansible.utils中的grep或使用模板处理,但比较直接的方式还是用shell命令。然而,Ansible本身并没有直接提供从文件中提取任意字段的模块,因此我们通常需要借助命令。但要注意,如果文件结构固定,我们可以使用lineinfile模块来匹配行,然后使用正则表达式提取,但lineinfile主要用于修改文件,不适用于提取信息。因此,我们推荐使用以下步骤:1.使用shell模块运行grep/awk/sed等命令来提取所需字段,并将结果注册为变量。2.使用set_fact模块将提取的结果保存为变量,以便后续使用。3.注意处理可能的多行情况(如果字段在多行出现)以及错误处理。示例Playbook:假设我们要从一个配置文件(比如/etc/foo.conf)中提取一个字段,例如字段名为“bar”的值,该文件中有行如:bar=value我们可以这样写:```-name:Extractfieldfromfilehosts:alltasks:-name:Runcommandtoextractthefieldansible.builtin.shell:|grep'^bar'/etc/foo.conf|awk-F'=''{print$2}'|tr-d''register:extracted_valuechanged_when:false#因为这个命令只是读取,不会改变系统状态-name:Settheextractedvalueasafactansible.builtin.set_fact:my_field:"{{extracted_value.stdout}}"-name:Debugtheextractedvalueansible.builtin.debug:var:my_field```但是,这种方法可能会因为文件不存在或匹配不到而出错。我们可以添加错误处理,比如忽略错误,但需要确保后续任务不依赖这个值。另外,如果文件可能不存在,我们可以先检查文件是否存在:```-name:Checkiffileexistsansible.builtin.stat:path:/etc/foo.confregister:file_stat-name:Extractfieldfromfileifexistsansible.builtin.shell:|grep'^bar'/etc/foo.conf|awk-F'=''{print$2}'|tr-d''register:extracted_valuewhen:file_stat.stat.existschanged_when:false-name:Settheextractedvalueasafactansible.builtin.set_fact:my_field:"{{extracted_value.stdout}}"when:file_stat.stat.exists-name:Setdefaultvalueiffiledoesnotexistansible.builtin.set_fact:my_field:"default_value"when:notfile_stat.stat.exists```注意:上面的命令使用了管道,我们也可以简化,例如直接用awk:awk-F'=''/^bar/{print$2}'/etc/foo.conf|tr-d''另外,如果字段可能出现在多行,而我们只需要第一个匹配,可以加上`head-1`。如果用户希望避免使用shell模块(为了可移植性和安全性),可以考虑使用Ansible的slurp模块将文件内容读入变量,然后使用Jinja2模板的过滤器进行处理。但是,Jinja2的字符串处理能力有限,对于复杂的情况可能不如awk方便。使用slurp和Jinja2的示例:```-name:Readthefileansible.builtin.slurp:src:/etc/foo.confregister:file_contentwhen:file_stat.stat.exists-name:Setthecontentasafact(decodefrombase64)ansible.builtin.set_fact:content:"{{file_content.content|b64decode}}"when:file_stat.stat.exists-name:Extractthelinecontainingthefieldansible.builtin.set_fact:my_field:"{{content.split('\n')|select('match','^bar')|list|first|regex_replace('^bar\\s*=\\s*(.*)$','\\1')|trim}}"when:file_stat.stat.exists```这种方法更符合Ansible的风格,但处理多行匹配和提取可能比较复杂。根据用户需求,我们提供两种方案,并说明各自的优缺点。考虑到用户的问题是如何提取文件中的某个字段,我们推荐第一种方法(使用shell命令)因为它简单直接,且在处理大文件时效率较高。但是,用户可能希望更“Ansible”的方式,因此我们也可以介绍第二种方法。另外,注意用户提到的站内引用[1]和[2]是关于变量和用户密码管理的,与当前问题不直接相关,但我们可以参考其中使用变量的方式。因此,我们给出两种方法的完整示例,并让用户根据情况选择。最后,生成相关问题。注意:我们的回答要使用中文。</think>### 如何使用 Ansible Playbook 提取文件中的特定字段 在 Ansible Playbook 中提取文件中的特定字段,可以通过以下两种核心方法实现: #### 方法 1:使用 `shell`/`command` 模块 + 文本处理工具(推荐) 通过 Linux 文本处理命令(如 `grep`/`awk`/`cut`)直接提取字段,并用 `register` 捕获结果: ```yaml - name: 提取文件中的字段 hosts: all tasks: # 示例:从 config.txt 提取 "version=" 后的值 - name: 执行提取命令 ansible.builtin.shell: | grep 'version=' /path/to/file | cut -d'=' -f2 register: extracted_value # 捕获输出结果 changed_when: false # 标记为只读操作 # 使用提取结果 - name: 显示提取的值 ansible.builtin.debug: msg: "提取的字段值: {{ extracted_value.stdout }}" ``` #### 方法 2:使用 `slurp` + Jinja2 过滤器 将文件内容读入变量,通过 Jinja2 模板引擎处理: ```yaml - name: 通过变量解析提取字段 hosts: all tasks: # 读取文件内容到变量 - name: 加载文件内容 ansible.builtin.slurp: src: /path/to/file register: file_content # 将 base64 内容解码为文本 - name: 解码文件内容 ansible.builtin.set_fact: file_text: "{{ file_content.content | b64decode }}" # 使用正则表达式提取字段 - name: 提取目标字段 ansible.builtin.set_fact: target_field: "{{ file_text | regex_search('version=(\\S+)') | regex_replace('.*=', '') }}" # 使用结果 - name: 输出字段值 ansible.builtin.debug: var: target_field ``` #### 关键技巧说明 1. **字段定位** - 结构化文件(如 INI/JSON):使用 `ini_file` 或 `community.general.json_query` 模块 - 非结构化文本:结合正则表达式(如 `regex_search`)或字符串分割(如 `split`) 2. **错误处理** ```yaml - name: 检查字段是否存在 ansible.builtin.fail: msg: "目标字段不存在" when: extracted_value.stdout == "" ``` 3. **多行处理** ```yaml # 提取多行日志中的时间戳 shell: awk '/Error/{print $1, $2}' /var/log/app.log ``` #### 典型应用场景 - 从配置文件中提取版本号、IP 地址等参数 - 解析日志文件中的错误代码 - 读取应用状态文件的关键指标 > **最佳实践**:优先使用 `shell`/`command` 处理复杂文本,简单字段可用 Jinja2 过滤器;涉及敏感数据时,通过 `no_log: true` 隐藏输出[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值