You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

寻求Ansible高效定位备份目录并生成格式化清单的最佳实践

优化Ansible备份清单生成Playbook的最佳实践

当前实现

我有一个Ansible Playbook,通过SSH访问远程主机,生成可插入邮件正文的远程主机文件系统备份清单文本文件。当前用于生成备份清单的任务如下:

- name: Create backup log from Remote Host
  shell: |
    cd /mnt/bntestmnt; echo -e "Backup server: [ipv4 address goes here] 
Backup directory: /export
/Backups/ESG 

Confluence Backups:" > BackupStatus.txt
    ls -td Confluence/daily/* | xargs du -sh >> BackupStatus.txt; echo " " >> BackupStatus.txt; 
    ls -td Confluence/weekly/* | xargs du -sh >> BackupStatus.txt; echo -e "
Gitlab Backups:" >> 
BackupStatus.txt
    ls -td GitLab/daily/* | xargs du -sh >> BackupStatus.txt; echo " " >> BackupStatus.txt
    ls -td GitLab/weekly/* | xargs du -sh >> BackupStatus.txt; echo -e "
Jira Backups:" >> 
BackupStatus.txt
    ls -td Jira/daily/* | xargs du -sh >> BackupStatus.txt; echo " " >> BackupStatus.txt
    ls -td Jira/weekly/* | xargs du -sh >> BackupStatus.txt; cat BackupStatus.txt
  register: Backup_Status
  delegate_to: [remote host name goes here]

由于使用>>重定向输出到文件,Ansible无法直接获取结果,所以最后用cat读取文件内容并注册为变量,用于后续插入邮件正文。

预期输出

Backup server: [ipv4 address goes here] 
Backup directory: /export/Backups/ESG 

Confluence Backups:
4.1G    Confluence/daily/Thu-23Mar23
4.0G    Confluence/daily/Wed-22Mar23
4.0G    Confluence/daily/Tue-21Mar23
4.0G    Confluence/daily/Mon-20Mar23
4.0G    Confluence/daily/Sun-19Mar23
3.9G    Confluence/daily/Sat-18Mar23
3.9G    Confluence/daily/Fri-17Mar23
 
3.7G    Confluence/weekly/Fri-10Mar23
3.5G    Confluence/weekly/Fri-03Mar23
3.4G    Confluence/weekly/Fri-24Feb23
3.3G    Confluence/weekly/Sat-18Feb23

Gitlab Backups:
2.5G    GitLab/daily/Thu-23Mar23
2.5G    GitLab/daily/Wed-22Mar23
2.4G    GitLab/daily/Tue-21Mar23
2.4G    GitLab/daily/Mon-20Mar23
2.4G    GitLab/daily/Sun-19Mar23
2.3G    GitLab/daily/Sat-18Mar23
2.3G    GitLab/daily/Fri-17Mar23
 
2.2G    GitLab/weekly/Fri-10Mar23
2.1G    GitLab/weekly/Fri-03Mar23
2.2G    GitLab/weekly/Fri-24Feb23

Jira Backups:
2.6G    Jira/daily/Thu-23Mar23
2.6G    Jira/daily/Wed-22Mar23
2.6G    Jira/daily/Tue-21Mar23
2.6G    Jira/daily/Mon-20Mar23
2.6G    Jira/daily/Sun-19Mar23
2.6G    Jira/daily/Sat-18Mar23
2.6G    Jira/daily/Fri-17Mar23
 
2.6G    Jira/weekly/Fri-10Mar23
2.6G    Jira/weekly/Fri-03Mar23
2.6G    Jira/weekly/Fri-24Feb23
2.6G    Jira/weekly/Fri-17Feb23

每个应用的清单中,最后一个daily备份与第一个weekly备份之间有换行。

尝试过的替代方案

试过以下命令,但无法实现预期输出:

ls -td Confluence/{daily,weekly}/* | xargs du -sh

或者:

find Confluence -mindepth 2 -type d -exec du -sh {} \;

这个版本排序有问题,大小和日期顺序混乱。

也尝试过用Jinja2模板,但不太熟悉,任务格式如下:

- name: Create backup log from Remote Host
  template:
    src: backup_report.j2
    dest: /mnt/bntestmnt/BackupStatus.txt
  vars:
    confluence_backups: [variable goes here]
    gitlab_backups: [variable goes here]
    jira_backups: [variable goes here]

目前模板backup_report.j2内容:

Backup server: [ipv4 address]
Backup directory: /export/Backups/ESG

Confluence Backups: 
{% for backup in confluence_backups %}
{{ backup }}
{% endfor %}

Gitlab Backups: 
{% for backup in gitlab_backups %}
{{ backup }}
{% endfor %}

Jira Backups: 
{% for backup in jira_backups %}
{{ backup }}
{% endfor %}

优化方案与最佳实践

1. 用Ansible原生逻辑替代Shell临时文件

直接在远程主机上执行命令并收集结果,不需要生成临时文件后再cat。可以用循环简化重复代码,直接组装报告内容:

- name: Collect backup server info
  set_fact:
    backup_server_ip: "{{ ansible_default_ipv4.address }}"
    backup_dir: "/export/Backups/ESG"
  delegate_to: [remote host name goes here]

- name: Define backup applications
  set_fact:
    backup_apps:
      - name: "Confluence"
        path: "Confluence"
      - name: "GitLab"
        path: "GitLab"
      - name: "Jira"
        path: "Jira"

- name: Collect backup details for each app
  shell: |
    echo -e "{{ app.name }} Backups:"
    ls -td {{ app.path }}/daily/* | xargs du -sh
    echo " "
    ls -td {{ app.path }}/weekly/* | xargs du -sh
  register: app_backups
  loop: "{{ backup_apps }}"
  delegate_to: [remote host name goes here]

- name: Assemble final backup report content
  set_fact:
    backup_report_content: |
      Backup server: {{ backup_server_ip }}
      Backup directory: {{ backup_dir }}

      {% for result in app_backups.results %}
      {{ result.stdout }}

      {% endfor %}

后续直接用{{ backup_report_content }}插入邮件正文即可,无需临时文件。

2. 完善Jinja2模板实现

如果倾向用模板,先分模块收集备份数据,再传入模板生成报告:

数据收集任务

- name: Collect Confluence daily backups
  shell: ls -td Confluence/daily/* | xargs du -sh
  register: confluence_daily_backups
  delegate_to: [remote host name goes here]

- name: Collect Confluence weekly backups
  shell: ls -td Confluence/weekly/* | xargs du -sh
  register: confluence_weekly_backups
  delegate_to: [remote host name goes here]

# 同理收集GitLab和Jira的备份数据...

- name: Generate backup report via template
  template:
    src: backup_report.j2
    dest: /mnt/bntestmnt/BackupStatus.txt
  vars:
    backup_server_ip: "{{ ansible_default_ipv4.address }}"
    backup_dir: "/export/Backups/ESG"
    confluence_daily: "{{ confluence_daily_backups.stdout_lines }}"
    confluence_weekly: "{{ confluence_weekly_backups.stdout_lines }}"
    gitlab_daily: "{{ gitlab_daily_backups.stdout_lines }}"
    gitlab_weekly: "{{ gitlab_weekly_backups.stdout_lines }}"
    jira_daily: "{{ jira_daily_backups.stdout_lines }}"
    jira_weekly: "{{ jira_weekly_backups.stdout_lines }}"
  delegate_to: [remote host name goes here]

完善后的backup_report.j2模板

Backup server: {{ backup_server_ip }}
Backup directory: {{ backup_dir }}

Confluence Backups:
{% for item in confluence_daily %}
{{ item }}
{% endfor %}
 
{% for item in confluence_weekly %}
{{ item }}
{% endfor %}

GitLab Backups:
{% for item in gitlab_daily %}
{{ item }}
{% endfor %}
 
{% for item in gitlab_weekly %}
{{ item }}
{% endfor %}

Jira Backups:
{% for item in jira_daily %}
{{ item }}
{% endfor %}
 
{% for item in jira_weekly %}
{{ item }}
{% endfor %}

3. 简化Shell命令,避免重复

可以在Shell中定义函数减少重复代码,让逻辑更清晰:

generate_backup_list() {
  app_name=$1
  app_path=$2
  echo -e "\n${app_name} Backups:"
  ls -td ${app_path}/daily/* | xargs du -sh
  echo " "
  ls -td ${app_path}/weekly/* | xargs du -sh
}

echo -e "Backup server: $(hostname -i)
Backup directory: /export/Backups/ESG"
generate_backup_list "Confluence" "Confluence"
generate_backup_list "GitLab" "GitLab"
generate_backup_list "Jira" "Jira"

将这段代码放入Ansible的shell任务中执行,即可生成符合要求的输出。

4. 处理特殊目录名,避免xargs问题

如果备份目录名称包含空格,xargs会出错,改用循环读取目录:

ls -td Confluence/daily/* | while read dir; do du -sh "$dir"; done

或者用find保证排序正确性:

find Confluence/daily -mindepth 1 -maxdepth 1 -type d -printf "%T@ %p\n" | sort -nr | cut -d' ' -f2- | while read dir; do du -sh "$dir"; done

这个写法既支持带空格的目录名,又能保证按修改时间倒序排序,和ls -td效果一致。

内容的提问来源于stack exchange,提问作者Eridith

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 05:55:12