找到一个文件并将其重命名为ansible playbook
Find a file and rename it ansible playbook
所以我一直在尝试使用剧本来修复我在所有服务器中犯的一个错误。基本上我启动了一个带有 logrotate 的 playbook 来解决不断增长的日志问题,并且其中有一个名为 btmp 的日志,我不应该旋转它但无论如何都是偶然的,现在 logrotate 更改了它的名称以添加一个日期并因此制动日志。现在我想使用一个剧本,它将在 /var/log 目录中找到一个名为 btmp 的日志并将其重命名,问题是文件 atm 在每个服务器中都不同,例如 1 个服务器有 btmp-20210316,另一个有 btmp -20210309,因此在 bash 命令行中可以使用通配符“btmp*”来绕过这些问题,但这似乎在 playbook 中不起作用。到目前为止,我想到了这个:
tasks:
- name: stat btmp*
stat: path=/var/log
register: btmp_stat
- name: Move btmp
command: mv /var/log/btmp* /var/log/btmp
when: btmp_stat.stat.exists
然而,这会导致找不到文件的错误。所以我的问题是如何让通配符在剧本中工作,或者是否有一种等效的方法来查找名称中包含“btmp”的所有文件并重命名它们?顺便说一句,所有服务器都是 Centos 7 服务器。
所以我也会添加我自己的解决方案,即使答案解决方案更好。
在你的 ansible VM 中的任何地方用一行制作一个 bash 脚本。
行是:mv /var/log/filename* /var/log/filename
现在创建一个 playbook 来在目标 VM 中运行它:
---
- hosts: '{{ server }}'
remote_user: username
become: yes
become_method: sudo
vars_prompt:
- name: "server"
prompt: "Enter server name or group"
private: no
tasks:
- name: Move the script to target host VM
copy: src=/anywhereyouwant/bashscript.sh dest=/tmp mode=0777
- name: Execute the script
command: sh /tmp/bashscript.sh
- name: delete the script
command: rm /tmp/bashscript.sh
在 Ansible 中有不止一种方法可以做到这一点,使用 shell
模块当然是一种可行的方法(但你需要 shell
模块代替 command
因为后者不支持通配符)。我会按如下方式解决问题:
- 首先创建一个任务来查找所有匹配的文件(即
/var/log/btmp*
)并将它们存储在一个变量中供以后处理 - 这看起来像这样:
- name: Find all files named /var/log/btmp*
ansible.builtin.find:
paths: /var/log
patterns: 'btmp*'
register: find_btmp
此任务使用 find
模块定位 /var/log
中所有名为 btmp*
的文件 - 结果存储在名为 find_btmp
.[=36= 的变量中]
- 接下来创建一个任务,将 btmp* 文件复制到 btmp。现在你很可能有超过 1 个文件路径上述模式,并且逻辑上你不想将它们全部重命名为 btmp 因为这只是每次都覆盖文件。相反,假设您只需要匹配的最新文件——我们可以使用一个聪明的 Jinja2 过滤器从第一个任务的结果中获取此条目:
- name: Copy the btmp* to the required filename
ansible.builtin.copy:
src: "{{ find_btmp.files | sort(attribute='mtime',reverse=true) | map(attribute='path') | first }}"
dest: /var/log/btmp
remote_src: yes
when: find_btmp.failed == false
此任务使用 Ansible 的 copy
模块将我们选择的源文件复制到 /var/log/btmp
。 remote_src: yes
参数告诉复制模块源文件存在于远程机器上而不是 Ansible 主机本身。
我们使用 when
子句来确保如果找不到任何文件,我们不会 运行 此复制操作。
现在让我们分解一下 Jinja2 过滤器:
find_btmp.files
- 这是我们的 find_btmp
变量 中列出的所有文件
sort(attribute='mtime',reverse=true)
- 这里我们使用 mtime
(修改时间)属性对文件列表进行排序 - 我们进行反向排序,以便最新的条目位于列表的顶部。
map(attribute='path')
- 我们正在使用 map 来“提取”文件字典的 path
属性,因为这是我们实际想要传递给复制模块的唯一数据 - 路径文件本身
first
- 这只选择列表中的第一个元素(即最新的文件,因为它们被反向排序)
- 最后,您要求进行移动操作 - Ansible 中没有本地“移动”模块,因此您需要在复制后删除源文件 - 这可以按如下方式完成(Jinja2 过滤器与之前:
- name: Delete the original file
ansible.builtin.file:
path: "{{ find_btmp.files | sort(attribute='mtime',reverse=true) | map(attribute='path') | first }}"
state: absent
when: find_btmp.failed == false
我们再次使用 when
子句来确保我们不会删除一开始没有找到的任何内容。
我已经在 Ansible 3.1.0/ansible-base 2.10.7 上测试过这个 - 如果你 运行ning Ansible 2.9 或更早版本,请从模块名称中删除 ansible.builtin.
(即ansible.builtin.copy
变成 copy
.)
希望对您有所帮助!
所以我一直在尝试使用剧本来修复我在所有服务器中犯的一个错误。基本上我启动了一个带有 logrotate 的 playbook 来解决不断增长的日志问题,并且其中有一个名为 btmp 的日志,我不应该旋转它但无论如何都是偶然的,现在 logrotate 更改了它的名称以添加一个日期并因此制动日志。现在我想使用一个剧本,它将在 /var/log 目录中找到一个名为 btmp 的日志并将其重命名,问题是文件 atm 在每个服务器中都不同,例如 1 个服务器有 btmp-20210316,另一个有 btmp -20210309,因此在 bash 命令行中可以使用通配符“btmp*”来绕过这些问题,但这似乎在 playbook 中不起作用。到目前为止,我想到了这个:
tasks:
- name: stat btmp*
stat: path=/var/log
register: btmp_stat
- name: Move btmp
command: mv /var/log/btmp* /var/log/btmp
when: btmp_stat.stat.exists
然而,这会导致找不到文件的错误。所以我的问题是如何让通配符在剧本中工作,或者是否有一种等效的方法来查找名称中包含“btmp”的所有文件并重命名它们?顺便说一句,所有服务器都是 Centos 7 服务器。
所以我也会添加我自己的解决方案,即使答案解决方案更好。 在你的 ansible VM 中的任何地方用一行制作一个 bash 脚本。 行是:mv /var/log/filename* /var/log/filename
现在创建一个 playbook 来在目标 VM 中运行它:
---
- hosts: '{{ server }}'
remote_user: username
become: yes
become_method: sudo
vars_prompt:
- name: "server"
prompt: "Enter server name or group"
private: no
tasks:
- name: Move the script to target host VM
copy: src=/anywhereyouwant/bashscript.sh dest=/tmp mode=0777
- name: Execute the script
command: sh /tmp/bashscript.sh
- name: delete the script
command: rm /tmp/bashscript.sh
在 Ansible 中有不止一种方法可以做到这一点,使用 shell
模块当然是一种可行的方法(但你需要 shell
模块代替 command
因为后者不支持通配符)。我会按如下方式解决问题:
- 首先创建一个任务来查找所有匹配的文件(即
/var/log/btmp*
)并将它们存储在一个变量中供以后处理 - 这看起来像这样:
- name: Find all files named /var/log/btmp*
ansible.builtin.find:
paths: /var/log
patterns: 'btmp*'
register: find_btmp
此任务使用 find
模块定位 /var/log
中所有名为 btmp*
的文件 - 结果存储在名为 find_btmp
.[=36= 的变量中]
- 接下来创建一个任务,将 btmp* 文件复制到 btmp。现在你很可能有超过 1 个文件路径上述模式,并且逻辑上你不想将它们全部重命名为 btmp 因为这只是每次都覆盖文件。相反,假设您只需要匹配的最新文件——我们可以使用一个聪明的 Jinja2 过滤器从第一个任务的结果中获取此条目:
- name: Copy the btmp* to the required filename
ansible.builtin.copy:
src: "{{ find_btmp.files | sort(attribute='mtime',reverse=true) | map(attribute='path') | first }}"
dest: /var/log/btmp
remote_src: yes
when: find_btmp.failed == false
此任务使用 Ansible 的 copy
模块将我们选择的源文件复制到 /var/log/btmp
。 remote_src: yes
参数告诉复制模块源文件存在于远程机器上而不是 Ansible 主机本身。
我们使用 when
子句来确保如果找不到任何文件,我们不会 运行 此复制操作。
现在让我们分解一下 Jinja2 过滤器:
find_btmp.files
- 这是我们的find_btmp
变量 中列出的所有文件
sort(attribute='mtime',reverse=true)
- 这里我们使用mtime
(修改时间)属性对文件列表进行排序 - 我们进行反向排序,以便最新的条目位于列表的顶部。map(attribute='path')
- 我们正在使用 map 来“提取”文件字典的path
属性,因为这是我们实际想要传递给复制模块的唯一数据 - 路径文件本身first
- 这只选择列表中的第一个元素(即最新的文件,因为它们被反向排序)
- 最后,您要求进行移动操作 - Ansible 中没有本地“移动”模块,因此您需要在复制后删除源文件 - 这可以按如下方式完成(Jinja2 过滤器与之前:
- name: Delete the original file
ansible.builtin.file:
path: "{{ find_btmp.files | sort(attribute='mtime',reverse=true) | map(attribute='path') | first }}"
state: absent
when: find_btmp.failed == false
我们再次使用 when
子句来确保我们不会删除一开始没有找到的任何内容。
我已经在 Ansible 3.1.0/ansible-base 2.10.7 上测试过这个 - 如果你 运行ning Ansible 2.9 或更早版本,请从模块名称中删除 ansible.builtin.
(即ansible.builtin.copy
变成 copy
.)
希望对您有所帮助!