Ansible中的备份配置文件更改,如果文件未更改,则自动删除备份

Ansible中的备份配置文件更改,如果文件未更改,则自动删除备份,ansible,Ansible,这是我想要的剧本流程: 对我打算(可能)备份的远程Linux配置文件进行备份 修改备份应持久化到磁盘(在远程服务器上) 在运行我的主要更改任务之前(以防playbook崩溃 中途) 执行几个可能会更改文件的任务。例如 2个LINEINFLE和3个BLOCKINFLE任务 如果文件已被(2)中的任务更改,我希望保留 备份文件。否则,应删除该文件 此外,我希望对多个配置文件(大约10个)执行相同的操作,例如/etc/ssh/sshd\u config和/etc/ntp.conf等。我希望备份代码尽可

这是我想要的剧本流程:

  • 对我打算(可能)备份的远程Linux配置文件进行备份 修改备份应持久化到磁盘(在远程服务器上) 在运行我的主要更改任务之前(以防playbook崩溃 中途)

  • 执行几个可能会更改文件的任务。例如 2个LINEINFLE和3个BLOCKINFLE任务

  • 如果文件已被(2)中的任务更改,我希望保留 备份文件。否则,应删除该文件

  • 此外,我希望对多个配置文件(大约10个)执行相同的操作,例如
    /etc/ssh/sshd\u config
    /etc/ntp.conf
    等。我希望备份代码尽可能简洁。如何以最佳方式执行步骤(1)和(3)

    我尝试/调查的内容:

    • 存在于许多文件中的参数 模块(lineinfle、blockinfle等)不是最佳的,因为它会 每个任务调用创建一个备份
    • 我宁愿避免后期任务,因为我希望我的主要任务在一个角色中执行,而角色没有任何好的方式来执行后期任务(?)
    • 我已经查阅了开发文档并考虑了 编写模块、动作插件或回调插件。但我没有 找到任何现有的API钩子来很好地将所有内容绑定在一起
    下面是一个简单而详细的示例,介绍如何仅对1个配置文件执行此操作。对于9个以上的配置文件,代码将变得更大

    ---
    - hosts: all
      gather_facts: False
      become: yes
    
      tasks:
        - name: Create temporary backup of /etc/ssh/sshd_config
          copy:
            src: "/etc/ssh/sshd_config"
            remote_src: yes
            dest: "/etc/ssh/sshd_config_{{ now().strftime('%Y-%m-%d_%H_%M_%S') }}.bak"
          register: "sshd_config_backup"
          changed_when: false
    
        - name: Change sshd ciphers
          lineinfile:
            dest: /etc/ssh/sshd_config
            regexp: '^Ciphers '
            line: "Ciphers aes192-ctr"
          notify: "sshd config changed"
    
        # 3 more lineinfile/blockinfile tasks that (may) change the same file
        # name: ...
        # name: ...
        # name: ...
    
        # Removing backup file if not changed
        - name: Get checksum of /etc/ssh/sshd_config
          stat:
            path: "/etc/ssh/sshd_config"
            get_checksum: yes    
          register: sshd_config_stat
    
        - name: Remove backup of /etc/ssh/sshd_config if there are no changes
          file:
            path: "{{ sshd_config_backup.dest }}"
            state: absent
          changed_when: false
          when: sshd_config_stat.stat.checksum == sshd_config_backup.checksum
    
      handlers:
        - name: Reload sshd service
          listen: sshd config changed
          service:
            name: sshd
            state: reloaded
    
    

    下面的剧本可能正是你所描述的

    -名称:conf_light
    主持人:全部
    收集事实:不
    变成:是的
    vars_文件:
    -data1.yml
    变量:
    cl_备份:是
    任务:
    -名称:创建时间戳
    时间:cl_备份
    设定事实:
    cl_时间戳:{{{'%Y-%m-%d_%H_%m_%S'| strftime}}”
    -名称:创建备份文件
    时间:cl_备份
    副本:
    遥控器:是的
    src:{{item.value.path}}
    dest:{item.value.path}}{{cl_timestamp}}}.bak”
    循环:{{cl_confs}dict2items}”
    -名称:配置文件中的行
    线条填充:
    路径:“{item.0.path}}”
    regexp:“{{item.1.regexp}}”
    行:“{item.1.line}”
    循环:{{cl_confs}子元素('line')}
    通知:“{item.0.handler | default(omit)}”
    寄存器:cl_结果_行
    -名称:配置文件中的块
    区块填充:
    路径:“{item.0.path}}”
    标记:“#{mark}ANSIBLE托管块{{item.1.marker}”
    块:“{item.1.block}”
    循环:{{cl_confs}子元素('blocks')}
    通知:“{item.0.handler | default(omit)}”
    寄存器:cl_结果块
    -名称:删除未更改的备份文件
    时间:cl_备份
    文件:
    国家:缺席
    路径:“{item}}{{cl_timestamp}}}.bak”
    循环:“{{cl_confs|
    json_查询('*.path')|
    差异(cl_结果_行。结果|默认值([]))|
    json_查询('[?changed=='true`].invocation.module_args.path'))|
    差异(cl_结果_块。结果|默认值([]))|
    json_查询('[?changed=='true`].invocation.module_args.path'))
    }}"
    处理程序:
    -名称:ssh重新加载
    服务:
    姓名:ssh
    状态:重新加载
    
    我已经在Ubuntu18.04中用下面的数据对它进行了测试。(将数据适配到任何其他Linux应该不会有问题)

    shell>cat data1.yml
    cl_会议:
    sshd_配置:
    路径:/etc/ssh/sshd\u config
    处理程序:ssh重新加载
    线:
    -regexp:“^Ciphers”
    行:“密码aes192 ctr”
    区块:[]
    ssh_配置:
    路径:/etc/ssh/ssh\u config
    行:[]
    阻碍:
    -标记:“srv1.example.com”
    块:| 2
    主机srv1.example.com
    议定书2
    货运代理人编号
    

    对于一个简单的游戏来说,这似乎是个好主意。

    下面的剧本可能正是你所描述的

    -名称:conf_light
    主持人:全部
    收集事实:不
    变成:是的
    vars_文件:
    -data1.yml
    变量:
    cl_备份:是
    任务:
    -名称:创建时间戳
    时间:cl_备份
    设定事实:
    cl_时间戳:{{{'%Y-%m-%d_%H_%m_%S'| strftime}}”
    -名称:创建备份文件
    时间:cl_备份
    副本:
    遥控器:是的
    src:{{item.value.path}}
    dest:{item.value.path}}{{cl_timestamp}}}.bak”
    循环:{{cl_confs}dict2items}”
    -名称:配置文件中的行
    线条填充:
    路径:“{item.0.path}}”
    regexp:“{{item.1.regexp}}”
    行:“{item.1.line}”
    循环:{{cl_confs}子元素('line')}
    通知:“{item.0.handler | default(omit)}”
    寄存器:cl_结果_行
    -名称:配置文件中的块
    区块填充:
    路径:“{item.0.path}}”
    标记:“#{mark}ANSIBLE托管块{{item.1.marker}”
    块:“{item.1.block}”
    循环:{{cl_confs}子元素('blocks')}
    通知:“{item.0.handler | default(omit)}”
    寄存器:cl_结果块
    -名称:删除未更改的备份文件
    时间:cl_备份
    文件:
    国家:缺席
    路径:“{item}}{{cl_timestamp}}}.bak”
    循环:“{{cl_confs|
    json_查询('*.path')|
    差异(cl_结果_行。结果|默认值([]))|
    json_查询('[?changed=='true`].invocation.module_args.path'))|
    差异(cl_结果_块。结果|默认值([]))|
    json_查询('[?changed=='true`].invocation.module_args.path'))
    }}"
    处理程序:
    -名称:ssh重新加载
    服务:
    姓名:ssh
    状态:重新加载
    
    我已经在Ubuntu18.04中用下面的数据对它进行了测试。(将数据适配到任何其他Linux应该不会有问题)<