Score:8

Can I remove the older revision package of duplicated snap packages?

cn flag

While examining the snap packages that are installed in a system, I noticed that some packages have a duplicate, one having an over revision number while the other having a newer revision number. For such duplicated packages, my questions are:

  1. Why are they duplicated?
  2. Can I remove the older package to ensure better disk space management?
  3. How do I remove the older package?

Below are examples of packages that do and do not have duplicates:

$ du -hcs /var/lib/snapd/snaps/*
31M /var/lib/snapd/snaps/2048x_3.snap
286M    /var/lib/snapd/snaps/atom_282.snap
4.0K    /var/lib/snapd/snaps/bare_5.snap
72M /var/lib/snapd/snaps/bitwarden_58.snap
72M /var/lib/snapd/snaps/bitwarden_59.snap
196M    /var/lib/snapd/snaps/blender_1113.snap
214M    /var/lib/snapd/snaps/blender_1237.snap
9.1M    /var/lib/snapd/snaps/canonical-livepatch_119.snap
9.1M    /var/lib/snapd/snaps/canonical-livepatch_126.snap
148M    /var/lib/snapd/snaps/chromium_1854.snap
148M    /var/lib/snapd/snaps/chromium_1864.snap
17M /var/lib/snapd/snaps/chromium-ffmpeg_23.snap
18M /var/lib/snapd/snaps/chromium-ffmpeg_24.snap
....

~$ ls -lh /var/lib/snapd/snaps/
total 12G
-rw------- 2 root root  31M Aug  5 06:23 2048x_3.snap
-rw------- 2 root root 286M Aug  5 08:35 atom_282.snap
-rw------- 2 root root 4.0K Sep 22 18:17 bare_5.snap
-rw------- 1 root root  72M Oct 30 00:20 bitwarden_58.snap
-rw------- 1 root root  72M Dec  9 04:28 bitwarden_59.snap
-rw------- 1 root root 196M Nov 18 04:06 blender_1113.snap
-rw------- 1 root root 214M Dec  4 09:39 blender_1237.snap
-rw------- 2 root root 9.1M Nov 17 21:06 canonical-livepatch_119.snap
-rw------- 2 root root 9.1M Nov 22 22:39 canonical-livepatch_126.snap
-rw------- 1 root root 148M Dec 16 04:28 chromium_1854.snap
-rw------- 1 root root 148M Jan  8 08:33 chromium_1864.snap
-rw------- 1 root root  17M Sep  3 06:29 chromium-ffmpeg_23.snap
-rw------- 2 root root  18M Nov 29 14:23 chromium-ffmpeg_24.snap
....

On the system that I am looking at, the total disk space utilized by /var/lib/snapd/snaps/* is 12,180.248 MB. The disk space of all the duplicated packages(i.e. older revision of the same package) is 4,163.1 MB. In short, the older revision packages currently takes up 34.18% of the 12,180.248 MB. This appears to be a cost to using SNAP apps that I had not realised before.

cocomac avatar
cn flag
Assuming you don't mind taking a risk... why not make a backup of the `/var/.../snaps/` folder somewhere safe, removing the old versions, rebooting, and seeing if it works? You can always restore your backup, and then you can answer your own question.
Someone avatar
my flag
BTW if you're running low on space then consider installing the `apt` versions of these softwares. They are lighter and better in everything.
Sun Bear avatar
cn flag
@cocomac I am hoping that I don't have to experiment to learn the answer to my questions as SNAP packages have been in practice for quite some time. There should be some SOP or standard knowledge by now on this matter.
guiverc avatar
cn flag
Snaps are changing again (eg. https://ubuntu.com//blog/the-future-of-snapcraft) which could be what @Someone was thinking/talking about... rules that apply to a single snap, may **not** apply to others created under a different environment (core16, core18, core20, and soon core22) so it's not a *single* set of rules; though of course many rules apply to all.
Sun Bear avatar
cn flag
@Someone `snap refresh` did not remove the duplicated packages.
Sun Bear avatar
cn flag
@Someone I found that Snap packages are typically more up to date than apt packages. However, they can be at times more troublesome to use. Some features need extra commands to enable. But I hear you that they are lighter to use. Thanks for your many helpful inputs. :)
Sun Bear avatar
cn flag
@Someone I have incorporated my learning from the inputs by you, matigo and user535733 to create this [remove_disabled_snap_pkgs.py](https://askubuntu.com/a/1386544/541417) python script to do the job.
Someone avatar
my flag
@SunBear Good Job! I like using scripts for everything. I've git cloned your repository but haven't tested it yet. Hopefully, it will work :D
Sun Bear avatar
cn flag
@Someone Thanks. Do let me know if improvements/corrections are needed. It worked at my end. :)
Sun Bear avatar
cn flag
@Someone I have added more comments to the script.
Score:11
in flag

To answer your questions:

Why are they duplicated?

⇢ They're different revisions (versions), not duplications.

Can I remove the older package to ensure better disk space management?

⇢ Yes. It's your computer, after all.

How do I remove the older package?

You can do this in Terminal like this:

snap remove {snap} --revision={revision}

You can also tell the system how many past versions to limit itself to like this:

sudo snap set system refresh.retain=2

Note: The value must be between 2 and 20, and a number like 2 or 3 is generally recommended to save storage space and allow a rollback in the event of a bad update.

If you would like to list all the snaps and their versions, you can run this command:

snap list --all

Which will give you something like:

Name                 Version                     Rev    Tracking         Publisher   Notes
bare                 1.0                         5      latest/stable    canonical✓  base
canonical-livepatch  10.0.1                      119    latest/stable    canonical✓  disabled
canonical-livepatch  10.1.2                      126    latest/stable    canonical✓  -
core                 16-2.52                     11798  latest/stable    canonical✓  core,disabled
core                 16-2.52.1                   11993  latest/stable    canonical✓  core
core18               20211028                    2253   latest/stable    canonical✓  base
core18               20211015                    2246   latest/stable    canonical✓  base,disabled
core20               20211115                    1242   latest/stable    canonical✓  base,disabled
core20               20211129                    1270   latest/stable    canonical✓  base
gnome-3-28-1804      3.28.0-19-g98f9e67.98f9e67  145    latest/stable    canonical✓  disabled
gnome-3-28-1804      3.28.0-19-g98f9e67.98f9e67  161    latest/stable    canonical✓  -
gnome-3-34-1804      0+git.3556cb3               77     latest/stable/…  canonical✓  -
gnome-3-34-1804      0+git.3556cb3               72     latest/stable/…  canonical✓  disabled
gnome-3-38-2004      0+git.cd626d1               87     latest/stable    canonical✓  -
gnome-3-38-2004      0+git.6ba6040               76     latest/stable    canonical✓  disabled
gtk-common-themes    0.1-52-gb92ac40             1515   latest/stable/…  canonical✓  disabled
gtk-common-themes    0.1-59-g7bca6ae             1519   latest/stable/…  canonical✓  -
snap-store           3.38.0-66-gbd5b8f7          558    latest/stable/…  canonical✓  -
snap-store           3.38.0-64-g23c4c77          547    latest/stable/…  canonical✓  disabled
snapd                2.53.2                      14066  latest/stable    canonical✓  snapd,disabled
snapd                2.53.4                      14295  latest/stable    canonical✓  snapd

Need a Script?

IMPORTANT: You will want to check the output of snap list --all on your computer before continuing, and the following is a script that should not be copy/pasted without sanity checking if you are using a locale that is not en_US.UTF-8.

The Script:

#!/bin/bash
# This script will remove disabled snap revisions.
set -eu

LANG=C snap list --all | awk '/disabled/{print $1, $3}' |
    while read name rev; do
        snap remove "$name" --revision="$rev"
    done

This will run snap list -all and extract the lines that contain the word disabled. This will be different depending on your locale, so check the output of the function first, then update awk '/disabled/ to replace disabled with the label that is found in your output.

Save the script to a file (for example scrub-snaps.sh) and then set it as being executable:

sudo chmod +x scrub-snaps.sh

Now you can run it, remembering to use sudo:

sudo ./scrub-snaps.sh

Note: sudo was not part of the script, but can be added if you prefer to have it in there. Either way, you'll be prompted for a password if required.

Sun Bear avatar
cn flag
Do you have a command to remove all older revisions of all installed Snap packages? Deleting them one by one is really a pain.
Sun Bear avatar
cn flag
Thanks. I have also shared an answer [here](https://askubuntu.com/a/1386544/541417) to facilitate a visual check of the Snap packages before executing any removal of disabled Snap packages.
vn flag
You can create an alias to [this onliner](https://askubuntu.com/a/1141683/349837) to do this
Score:7
cn flag

Keeping at least one older version of a snap is inherent in the design.

Snap packages were originally designed for a variety of environments where there is often no human admin and/or no way to attach a keyboard and monitor...like phones or IOT devices. Resiliency is a critical requirement for these systems: If an application crashes or an upgrade is corrupted, some form of guaranteed rollback without human intervention is needed. Hence the requirement for at least one older version on-hand.

Folks on classic desktops and servers don't care much about that rollback capability. They like different snap design elements: The secure automatic upgrades that are independent of the OS, the read-only squashfs tamper-prevention, the process confinement, etc.

But it's all a single standard, so you get the rollback capability, too. Even if you think you won't use it.

You cannot "disable" the rollback capability of snaps -- it's not really a "feature" but a key design element.

Sun Bear avatar
cn flag
Thanks for explaining. In the system that I looked at, I discovered that the cost of the minimum redundancy feature of Snap is at least 34% of the total disk space of all the Snap packages.
Sun Bear avatar
cn flag
Despite the design intent for redundancy, did the Snap development team also provide a command to remove all older revisions of all snap packages? This capability is to better serve the folks on classic desktops and servers who don't care much about that rollback capability.
user535733 avatar
cn flag
Sure, the answer by @matigo explains *how*. This answer complements by explaining *why*.
Score:2
cn flag

Building on @matigo answer, I wrote a python script to automate the removal of disabled SNAP packages. It allows a user to visually check the snap packages before proceeding with (or not) the removal process. An example of what the executed script does is shown in the link.

remove_disabled_snap_pkgs.py

#!/bin/python3
''' This python script automates the removal of all disabled SNAP packages in
a system. Doing so helps free up the system's disk space. This outcome can be
significant in the situation where many disabled SNAP packages are retained in
the system.
'''
from subprocess import run, PIPE, CalledProcessError
from pathlib import Path
import sys

# Assumptions
SNAP_PKGS_PATH = Path('/var/lib/snapd/snaps/')
# Also, at a minimum, this directory has at least one xxx.snap file there. 


def snap_list():
    '''Function to execute a bash 'snap list' cmd and returns a Python
    dictionary of info of the ACTIVE SNAPCRAFT pkgs in the system.

    pkgs_dict = {Name : {'Version':'xxx', 'Rev':'xxx', 'Tracking':'xxx',
                         'Publisher':'xxx', 'Notes':'xxx'}
                }
    '''
    try:
        cmd = ['snap', 'list']
        completed = run(cmd, check=True, stdout=PIPE)
    except CalledProcessError as err:
        print('ERROR:', err)
    else:
        headers = completed.stdout.decode('utf-8').splitlines()[0].split()
        pkgs=[line.split() for line in
              completed.stdout.decode('utf-8').splitlines()[1:]]
        pkgs_dict = {}
        for pkg in pkgs:
            pkgs_dict[pkg[0]] = {i:pkg[n+1] for n, i in enumerate(headers[1:])}
        return pkgs_dict


# 1. Get all SNAPCRAFT pkgs in system
all_path = sorted(SNAP_PKGS_PATH.glob('*.snap'))
all_size = sum([p.stat().st_size for p in all_path])

# 2. Get active SNAPCRAFT pkgs in system
active_snap_pkgs = snap_list()
active_path = [SNAP_PKGS_PATH / Path(k+'_'+v['Rev']+'.snap')
               for k, v in active_snap_pkgs.items()]
active_size = sum([p.stat().st_size for p in active_path])

# 3. Display info and instructions in terminal
print(f'ALL (ACTIVE & DISABLED) SNAP PACKAGES IN SYSTEM:')
for n, i in enumerate(all_path):
    size = i.stat().st_size
    if i in active_path:
        print(f'Active\t{size:>12}\t{i}')
    else:
        print(f'      \t{size:>12}\t{i}')

# 4. Show stats on total size of All, Active & Disabled SNAPCRAFT packages 
width = 12
disabled_size = all_size - active_size
print('\nSIZE OF SNAP PACKAGES:')
print(f'1. All      : {all_size:>{width}} bytes')
print(f'2. Active   : {active_size:>{width}} bytes')
print(f'2. Disabled : {disabled_size:>{width}} bytes or '
      f'{(disabled_size/all_size):.2%} of All')

# 5. Make decision to remove or not to remove Disabled SNAPCRAFT packages 
if disabled_size > 0:
    print(f'\nREMOVE ALL DISABLED SNAP PACKAGES? [y/n]')
    while True:
        decision = input()
        if decision in ['y', 'Y', 'yes', 'Yes', 'YES']:
            print('Removal in progress... pls wait')
            for p in all_path:
                if p not in active_path:
                    stem = p.stem
                    bar_index = stem.index('_')
                    name = stem[:bar_index]
                    revision = stem[bar_index+1:]
                    cmd = ['sudo', 'snap', 'remove', name,
                           '--revision='+revision]
                    print(f"\n{' '.join(cmd)}")
                    run(cmd, stdout=sys.stdout, stderr=sys.stderr,
                        encoding='utf8')
            print(f'\nREMOVE ALL DISABLED SNAP PACKAGES? COMPLETED.')
            break
        elif decision in ['n', 'N', 'no', 'No', 'NO']:
            print(f'\nNO REMOVAL IS PERFORMED.')
            break
        else:
            print('Please enter only "y" or "n":')
else:
    print(f'\nNO REMOVAL IS NEEDED.')
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.