25

I maintain a flock of EC2 servers with ansible. The servers are regularly updates and upgraded using the apt module.

When I manually tried to upgrade a server, I received the following message:

$ sudo apt-get upgrade
Reading package lists... Done
Building dependency tree
Reading state information... Done
Calculating upgrade... Done
The following packages were automatically installed and are no longer required:
  linux-headers-3.13.0-29 linux-headers-3.13.0-29-generic
  linux-headers-3.13.0-32 linux-headers-3.13.0-32-generic
  linux-image-3.13.0-29-generic linux-image-3.13.0-32-generic
Use 'apt-get autoremove' to remove them.
0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.

Is there a way to run sudo apt-get autoremove with ansible?

1
  • 1
    You can always use the command module to do a raw shell command.
    – ceejayoz
    Commented Nov 13, 2014 at 13:47

6 Answers 6

31

Support for the apt-get option --auto-remove is now built into Ansible's apt (option autoremove) as of version 2.1 Official documentation is at http://docs.ansible.com/ansible/apt_module.html

- name: Remove dependencies that are no longer required
  apt:
    autoremove: yes

The merge happened here.

Note that autoclean is also available as of 2.4

6
  • Could you please add a reference link?
    – Adam Matan
    Commented Apr 14, 2016 at 13:51
  • @AdamMatan Updated answer with a link to the docs.
    – oalders
    Commented Apr 14, 2016 at 17:40
  • 1
    if you check here you will see that "autoremove" with a "state" option is considered a bug. Ansible dev team will need to define if "autoremove" will be only an option or an full operation for Ansible 2.2 (I hope...) Commented Oct 19, 2016 at 12:59
  • @YonsySolis someone hijacked this answer via an edit. I've reverted it to its original state.
    – oalders
    Commented Oct 19, 2016 at 13:20
  • 1
    @flickerfly according to the docs you should be able to run this without having to provide a package name. I've updated my answer to reflect this.
    – oalders
    Commented Jul 6, 2017 at 11:03
14

This simplified method requires one task only

  - name: Autoremove unused packages
    command: apt-get -y autoremove
    register: autoremove_output
    changed_when: "'The following packages will be REMOVED' in autoremove_output.stdout"
1
  • this should probably be the accepted answer.
    – ab77
    Commented Mar 23, 2017 at 17:19
10

You can do it with command (untested):

  - name: Check if anything needs autoremoving
    shell: apt-get -y --dry-run autoremove | grep -q "0 to remove"
    register: check_autoremove
    ignore_errors: True
    changed_when: False
    always_run: True

  - name: Autoremove unused packages
    command: apt-get -y autoremove
    when: "check_autoremove.rc != 0"

However, I think it could be risky to run autoremove automatically. Because of system administration errors that you've made in the past (these could be in your ansible code), it's possible that a package that is needed can at some point be falsely detected as autoremovable, and this could stop the server from working. On the other hand, it's no big deal to leave unused packages on the system, and it's not very common unless you make a major change in the server's setup.

Therefore, I would stay away from autoremoving packages without confirmation from a human.

2
  • Ansible does not necessarily mark packages as 'manual', even if you have installed them using the apt module. So 'autoremove' might remove the wrong packages. Quick fix: use apt-mark manual <pkg>
    – Willem
    Commented Mar 4, 2015 at 16:47
  • 1
    On Ubuntu, if you don't do regular autoremove, then your /boot might fill up until it is full! Mostly autoremove has only removed older unused kernel. Because, this needs regular check, it ought to be automated. :-) On Fedora/RHEL, you can instruct yum/dnf to keep only a certain number of package (like 3 kernel versions), so you never have this problem.
    – Huygens
    Commented Sep 9, 2015 at 12:26
6

This is a variation on the solution Antonis Christofides provided. It is tested and works for me. I avoided using ignore_errors in the check command. Otherwise it generally takes the same approach.

- name: Check if packages need to be autoremoved
  command: apt-get --dry-run autoremove
  register: check_autoremove
  changed_when: False
- name: Autoremove unused packages
  command: apt-get -y autoremove
  when: "'packages will be REMOVED' in check_autoremove.stdout"
2
  • What's the reason for a --dry-run first? apt-get -y autoremove doesn't return a non-zero status. So it seems you could unconditionally run without the --dry-run and check changed_when against the actual autoremove call I think.
    – thom_nic
    Commented Apr 14, 2015 at 17:11
  • @thom_nic I think you're right. I was able to structure like this: - name: autoremove unused packages become: yes command: apt-get -y autoremove register: check_autoremove changed_when: "'packages will be REMOVED' in check_autoremove.stdout" Commented Aug 7, 2015 at 15:08
2

A variation that highlights the change in packages (first task will be appropriately colored green or yellow):

  - name: check if packages need to be autoremoved
    shell: apt-get --dry-run autoremove | grep "to remove" | sed "s/^[0-9]\+ upgraded, [0-9]\+ newly installed, \([0-9]\+\) to remove and [0-9]\+ not upgraded\.$/\1/"
    register: check_autoremove
    changed_when: check_autoremove.stdout != "0"

  - name: autoremove unused packages
    command: apt-get -y autoremove
    when: check_autoremove.changed
2
  • Problem with your "sed" string is that it is not "portable". The execution of apt-get --dry-run autoremove | grep "to remove" returns on Ubuntu 14.04, 0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded. but on Ubuntu 15.04 it returns 0 to upgrade, 0 to newly install, 0 to remove and 0 not to upgrade. which your sed doesn't match.
    – Huygens
    Commented Sep 9, 2015 at 11:21
  • Always hard to match changing text. Probably replace install with install(ed)? or something like that. Commented Sep 9, 2015 at 13:45
1

I like this simplified method, and I add some check and print message for me.

#!/usr/bin/env ansible-playbook
---

- name: Autoremove 'apt' package for Debian, Ubuntu
  hosts: all

  pre_tasks:
    - name: check storage space - before
      shell: df -h
      register: check_storage_space_before

    - name: print storage space
      debug:
        msg: "{{ check_storage_space_before.stdout_lines }}"

    - name: apt autoremove check 
      command: apt-get -y --dry-run autoremove
      register: apt_autoremove_output

    - name: print apt autoremove packages
      debug:
        msg: "{{ apt_autoremove_output.stdout_lines }}"

  tasks:    
    - name: autoremove unused packages
      become: yes
      command: apt-get -y autoremove
      changed_when: "'The following packages will be REMOVED' in apt_autoremove_output.stdout"

  post_tasks:
    - name: check storage space - after
      shell: df -h
      register: check_storage_space_after

    - name: print storage space
      debug:
        msg: "{{ check_storage_space_after.stdout_lines }}"

# vim: ft=ansible :

Thank you for cortopy and Dave James Miller.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .