1. 概述

在 Ansible 中,记录 Playbook 的执行细节至关重要,特别是在跨多台服务器运行 Playbook 时。通过日志,我们可以了解执行过程、时间点以及是否成功。捕获任务输出,有助于追踪变更和排查问题

本文将介绍如何在 Ansible 中将任务输出日志记录到文件中,涵盖多种方式,包括全局配置、命令行重定向、模块操作、回调插件等。

2. 前提条件

在开始之前,请确保满足以下条件:

  • 控制机上已安装 Ansible ✅
  • 控制机与远程主机之间具备 SSH 连接 ✅
  • 存在列出目标主机的 inventory 文件 ✅

为了验证本文示例,建议搭建一个测试环境,例如使用 Vagrant 或本地虚拟机。

3. 使用 log_path 配置

Ansible 提供了 log_path 参数,用于将 Playbook 的执行事件记录到一个文件中。这种方式无需修改 Playbook 本身,只需修改配置文件即可。

3.1. 理解 ansible.cfg

Ansible 通过 ansible.cfg 文件控制运行时行为,查找顺序如下:

  1. 环境变量 ANSIBLE_CONFIG
  2. 当前目录下的 ansible.cfg
  3. 用户目录下的 ~/.ansible.cfg
  4. 系统级配置 /etc/ansible/ansible.cfg

我们通常在项目目录中使用自定义的 ansible.cfg

3.2. 启用全局日志路径

编辑 ansible.cfg 文件:

# ansible.cfg
[defaults]
log_path = ./logs/ansible-execution.log

⚠️ 注意:logs 目录必须存在,并且当前用户对该目录具有写权限。

3.3. 运行测试 Playbook

编写测试 Playbook:

# log_path.yml
---
- name: Test logging to file
  hosts: web
  gather_facts: false
  tasks:
    - name: Run a sample shell command
      shell: echo "This is a test run on {{ inventory_hostname }}"

执行命令:

ansible-playbook log_path.yml -i hosts.ini -v

输出将同时写入控制台和 logs/ansible-execution.log 文件中。

4. 使用命令行重定向

通过 Shell 重定向,可以将 Ansible Playbook 的完整输出写入文件。这种方式不会在控制台显示任何内容。

示例

ansible-playbook log_path.yml -i hosts.ini -v 1>logs/ansible.out 2>logs/ansible.err
  • 1> 表示标准输出重定向
  • 2> 表示标准错误输出重定向

执行后,日志将分别写入 ansible.outansible.err

5. 使用 copy 模块写入日志

Ansible 的 copy 模块不仅可以复制文件,还能通过 content 参数动态生成远程日志文件。

5.1. 单任务示例

# copy_module.yml
---
- name: Log message using copy module
  hosts: web
  gather_facts: false
  become: yes
  tasks:
    - name: Prepare log content
      shell: date
      register: datetime
    - name: Write to remote log file
      copy:
        content: |
          Log Entry:
          Host: {{ inventory_hostname }}
          Date: {{ datetime.stdout }}
          Status: Task completed successfully.
        dest: /tmp/ansible_custom_log.txt
        owner: root
        group: root
        mode: '0644'

执行后,远程主机 /tmp/ansible_custom_log.txt 中将包含日志内容。

5.2. 使用 Jinja2 模板

创建模板文件 log_template.j2

Log Entry:
Host: {{ inventory_hostname }}
Date: {{ datetime.stdout }}
Status: Task completed successfully.

更新 Playbook:

# copy_module.yml
---
- name: Log message using copy module
  hosts: web
  gather_facts: false
  become: yes
  tasks:
    - name: Get current date and time
      shell: date
      register: datetime
    - name: Write log entry using template
      template:
        src: log_template.j2
        dest: /tmp/ansible_custom_log.txt
        owner: root
        group: root
        mode: '0644'

这种方式将逻辑与内容分离,便于维护。

6. 使用 lineinfile 追加日志

对于需要在日志文件中追加内容的场景,可以使用 lineinfile 模块。

6.1. 示例 Playbook

# lineinfile.yml
- name: Run shell command and log output using lineinfile
  hosts: web
  become: yes
  tasks:
    - name: Get disk usage
      shell: df -h /
      register: disk_usage
    - name: Log output to file
      lineinfile:
        path: /var/log/custom_tasks.log
        line: "Disk Usage: {{ disk_usage.stdout }}"
        create: yes
        insertafter: EOF

该任务将磁盘使用情况追加写入 /var/log/custom_tasks.log

6.2. 执行 Playbook

ansible-playbook lineinfile.yml -i hosts.ini

查看日志文件内容:

cat /var/log/custom_tasks.log

✅ 适用于单行日志追加,若需写入多行,建议使用 blockinfile 模块。

7. 使用 Callback 插件记录日志

Callback 插件可以在任务执行过程中实时记录日志,并支持多种输出方式,包括写入文件、发送通知等。

7.1. 安装 log_plays 插件

ansible-galaxy collection install community.general

7.2. 配置 ansible.cfg

[defaults]
inventory = hosts.ini
callback_whitelist = community.general.log_plays
stdout_callback = default

7.3. 创建日志目录

sudo mkdir -p /var/log/ansible/hosts
sudo chown $(whoami) /var/log/ansible/hosts

7.4. 示例 Playbook

# test_play.yml
---
- name: Test Playbook for log_plays callback plugin
  hosts: web
  gather_facts: no
  tasks:
    - name: Create a file to test logging
      ansible.builtin.file:
        path: "/tmp/ansible_test_file"
        state: touch

7.5. 运行 Playbook

ANSIBLE_LOG_PLAYS_DIR=/var/log/ansible/hosts ansible-playbook -i hosts.ini test_play.yml

执行后,每台主机的日志将写入 /var/log/ansible/hosts/ 下的对应文件中。

8. 使用 debugtee 实现轻量日志

当 Ansible 的默认日志过于冗长时,可以结合 debug 模块与 tee 命令实现轻量级日志记录。

8.1. 使用 debug 模块输出变量

# debug_tee.yml
---
- name: Get CPU Information from web servers
  hosts: web
  gather_facts: false
  tasks:
    - name: Read CPU info from /proc/cpuinfo
      command: cat /proc/cpuinfo
      register: cpu_info_output
    - name: Display CPU info
      debug:
        msg: "{{ cpu_info_output.stdout }}"

8.2. 执行并写入日志文件

ansible-playbook debug_tee.yml | sudo tee /var/log/ansible/report.log

这样,控制台输出和日志文件将同时记录执行结果。

9. 总结

本文介绍了多种在 Ansible 中将任务输出记录到文件的方法,包括:

方法 适用场景 特点
log_path 全局日志记录 简单、集中、无需修改 Playbook
命令行重定向 快速保存完整输出 不影响 Playbook,适合调试
copy 模块 生成结构化日志 可写入远程主机,支持模板
lineinfile 日志追加 简单易用,适合单行记录
Callback 插件 实时日志 支持结构化输出,适合复杂场景
debug + tee 轻量日志 灵活、适合调试特定任务

根据实际需求选择合适的方式,可以更高效地管理 Ansible 的日志输出。


原始标题:Log Task Output to a File in Ansible