如何通过Ansible在更新APT包时记录更新前后的版本到文件
如何通过Ansible在更新APT包时记录更新前后的版本到文件
哈哈,这个需求太实用了!我之前维护服务器的时候也经常需要记录包更新的版本变更,APT模块本身确实不会主动返回这些信息,不过咱们可以拆成几个步骤来实现,稳得很:
核心思路就是先查版本、再更包、再查版本、最后写记录,用dpkg-query来精准获取包版本(比解析APT输出靠谱多了),具体来看完整的Playbook示例:
--- - name: 升级包并记录版本变更 hosts: your_target_hosts become: yes # 需要root权限执行APT操作和写入系统日志路径 vars: packages: - nginx - curl # 替换成你要升级的包列表 version_log_file: /var/log/package_upgrade_history.log # 日志文件路径,可自定义 tasks: - name: 获取升级前的包版本 ansible.builtin.command: dpkg-query -W -f='${Package}\t${Version}' {{ item }} register: pre_upgrade_versions loop: "{{ packages }}" changed_when: false # 这个操作不会修改系统,标记为无状态变更 - name: 执行包升级操作 ansible.builtin.apt: name: "{{ item }}" state: latest update_cache: true only_upgrade: true loop: "{{ packages }}" register: upgrade_results - name: 获取升级后的包版本 ansible.builtin.command: dpkg-query -W -f='${Package}\t${Version}' {{ item }} register: post_upgrade_versions loop: "{{ packages }}" changed_when: false - name: 将版本变更记录写入日志文件 ansible.builtin.lineinfile: path: "{{ version_log_file }}" line: "{{ ansible_date_time.iso8601 }} - 包名: {{ item.0.item }} | 升级前版本: {{ item.0.stdout.split('\t')[1] }} | 升级后版本: {{ item.1.stdout.split('\t')[1] }}" create: true # 如果日志文件不存在则自动创建 loop: "{{ pre_upgrade_versions.results | zip(post_upgrade_versions.results) | list }}" when: item.0.stdout.split('\t')[1] != item.1.stdout.split('\t')[1] # 只记录确实发生版本变化的包
几个实用的小细节:
- 只记录变更:最后一步的
when条件会过滤掉没有版本变化的包,避免日志冗余;如果需要记录所有包(哪怕没更新),删掉这个条件就行。 - 自定义日志格式:你可以把
line字段改成自己喜欢的格式,比如JSON格式方便后续脚本解析:line: '{"timestamp": "{{ ansible_date_time.iso8601 }}", "package": "{{ item.0.item }}", "pre_version": "{{ item.0.stdout.split('\t')[1] }}", "post_version": "{{ item.1.stdout.split('\t')[1] }}"}' - 权限问题:如果日志路径是系统目录(比如
/var/log),一定要加上become: yes确保有写入权限。 - 处理未安装包:如果你的
packages列表里可能有未安装的包,可以在第一步加个failed_when: false,然后在后续步骤判断是否已安装,不过你的only_upgrade: true配置已经确保只会处理已安装包,所以这个可以不用额外处理。
备注:内容来源于stack exchange,提问作者idiot one
相关产品推荐
相关产品推荐

