123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189 |
- #!/bin/bash
- # Overlord management of snapd for package manager actions.
- # Implements actions that would be invoked in %pre(un) actions for snapd.
- # Derived from the snapd.postrm scriptlet used in the Ubuntu packaging for
- # snapd.
- set -e
- set +x
- SNAP_MOUNT_DIR="/snap"
- show_help() {
- exec cat <<'EOF'
- Usage: snap-mgmt.sh [OPTIONS]
- A simple script to cleanup snap installations.
- optional arguments:
- --help Show this help message and exit
- --snap-mount-dir=<path> Provide a path to be used as $SNAP_MOUNT_DIR
- --purge Purge all data from $SNAP_MOUNT_DIR
- EOF
- }
- SNAP_UNIT_PREFIX="$(systemd-escape -p ${SNAP_MOUNT_DIR})"
- systemctl_stop() {
- unit="$1"
- if systemctl is-active -q "$unit"; then
- echo "Stopping $unit"
- systemctl stop -q "$unit" || true
- fi
- }
- purge() {
- # shellcheck disable=SC1091
- distribution=$(. /etc/os-release; echo "${ID}-${VERSION_ID}")
- if [ "$distribution" = "ubuntu-14.04" ]; then
- # snap.mount.service is a trusty thing
- systemctl_stop snap.mount.service
- fi
- # Undo any bind mounts to ${SNAP_MOUNT_DIR} or /var/snap done by parallel
- # installs or LP:#1668659
- for mp in "$SNAP_MOUNT_DIR" /var/snap; do
- if grep -q " $mp $mp" /proc/self/mountinfo; then
- umount -l "$mp" || true
- fi
- done
- units=$(systemctl list-unit-files --no-legend --full | grep -vF snap.mount.service || true)
- # *.snap mount points
- mounts=$(echo "$units" | grep "^${SNAP_UNIT_PREFIX}[-.].*\\.mount" | cut -f1 -d ' ')
- # services from snaps
- services=$(echo "$units" | grep '^snap\..*\.service' | cut -f1 -d ' ')
- for unit in $services $mounts; do
- # ensure its really a snap mount unit or systemd unit
- if ! grep -q 'What=/var/lib/snapd/snaps/' "/etc/systemd/system/$unit" && ! grep -q 'X-Snappy=yes' "/etc/systemd/system/$unit"; then
- echo "Skipping non-snapd systemd unit $unit"
- continue
- fi
- echo "Stopping $unit"
- systemctl_stop "$unit"
- if echo "$unit" | grep -q '.*\.mount' ; then
- # Transform ${SNAP_MOUNT_DIR}/core/3440 -> core/3440 removing any
- # extra / preceding snap name, eg:
- # /var/lib/snapd/snap/core/3440 -> core/3440
- # /snap/core/3440 -> core/3440
- # /snap/core//3440 -> core/3440
- # NOTE: we could have used `systemctl show $unit -p Where --value`
- # but systemd 204 shipped with Ubuntu 14.04 does not support this
- snap_rev=$(systemctl show "$unit" -p Where | sed -e 's#Where=##' -e "s#$SNAP_MOUNT_DIR##" -e 's#^/*##')
- snap=$(echo "$snap_rev" |cut -f1 -d/)
- rev=$(echo "$snap_rev" |cut -f2 -d/)
- if [ -n "$snap" ]; then
- echo "Removing snap $snap"
- # aliases
- if [ -d "${SNAP_MOUNT_DIR}/bin" ]; then
- find "${SNAP_MOUNT_DIR}/bin" -maxdepth 1 -lname "$snap" -delete
- find "${SNAP_MOUNT_DIR}/bin" -maxdepth 1 -lname "$snap.*" -delete
- fi
- # generated binaries
- rm -f "${SNAP_MOUNT_DIR}/bin/$snap"
- rm -f "${SNAP_MOUNT_DIR}/bin/$snap".*
- # snap mount dir
- umount -l "${SNAP_MOUNT_DIR}/$snap/$rev" 2> /dev/null || true
- rm -rf "${SNAP_MOUNT_DIR:?}/$snap/$rev"
- rm -f "${SNAP_MOUNT_DIR}/$snap/current"
- # snap data dir
- rm -rf "/var/snap/$snap/$rev"
- rm -rf "/var/snap/$snap/common"
- rm -f "/var/snap/$snap/current"
- # opportunistic remove (may fail if there are still revisions left)
- for d in "${SNAP_MOUNT_DIR}/$snap" "/var/snap/$snap"; do
- if [ -d "$d" ]; then
- rmdir --ignore-fail-on-non-empty "$d"
- fi
- done
- # udev rules
- find /etc/udev/rules.d -name "*-snap.${snap}.rules" -execdir rm -f "{}" \;
- # dbus policy files
- if [ -d /etc/dbus-1/system.d ]; then
- find /etc/dbus-1/system.d -name "snap.${snap}.*.conf" -execdir rm -f "{}" \;
- fi
- # timer and socket units
- find /etc/systemd/system -name "snap.${snap}.*.timer" -o -name "snap.${snap}.*.socket" | while read -r f; do
- systemctl_stop "$(basename "$f")"
- rm -f "$f"
- done
- fi
- fi
- echo "Removing $unit"
- rm -f "/etc/systemd/system/$unit"
- rm -f "/etc/systemd/system/multi-user.target.wants/$unit"
- done
- echo "Discarding preserved snap namespaces"
- # opportunistic as those might not be actually mounted
- if [ -d /run/snapd/ns ]; then
- if [ "$(find /run/snapd/ns/ -name "*.mnt" | wc -l)" -gt 0 ]; then
- for mnt in /run/snapd/ns/*.mnt; do
- umount -l "$mnt" || true
- rm -f "$mnt"
- done
- fi
- find /run/snapd/ns/ \( -name '*.fstab' -o -name '*.user-fstab' -o -name '*.info' \) -delete
- umount -l /run/snapd/ns/ || true
- fi
- echo "Removing downloaded snaps"
- rm -rf /var/lib/snapd/snaps/*
- echo "Removing features exported from snapd to helper tools"
- rm -rf /var/lib/snapd/features
- echo "Final directory cleanup"
- rm -rf "${SNAP_MOUNT_DIR}"
- rm -rf /var/snap
- echo "Removing leftover snap shared state data"
- rm -rf /var/lib/snapd/desktop/applications/*
- rm -rf /var/lib/snapd/seccomp/bpf/*
- rm -rf /var/lib/snapd/device/*
- rm -rf /var/lib/snapd/assertions/*
- rm -rf /var/lib/snapd/cookie/*
- rm -rf /var/lib/snapd/cache/*
- rm -rf /var/lib/snapd/mount/*
- rm -rf /var/lib/snapd/sequence/*
- rm -rf /var/lib/snapd/apparmor/*
- rm -f /var/lib/snapd/state.json
- rm -f /var/lib/snapd/system-key
- echo "Removing snapd catalog cache"
- rm -rf /var/cache/snapd/*
- if test -d /etc/apparmor.d; then
- # Remove auto-generated rules for snap-confine from the 'core' snap
- echo "Removing extra snap-confine apparmor rules"
- # shellcheck disable=SC2046
- rm -f /etc/apparmor.d/$(echo "$SNAP_UNIT_PREFIX" | tr '-' '.').core.*.usr.lib.snapd.snap-confine
- fi
- }
- while [ -n "$1" ]; do
- case "$1" in
- --help)
- show_help
- exit
- ;;
- --snap-mount-dir=*)
- SNAP_MOUNT_DIR=${1#*=}
- SNAP_UNIT_PREFIX=$(systemd-escape -p "$SNAP_MOUNT_DIR")
- shift
- ;;
- --purge)
- purge
- shift
- ;;
- *)
- echo "Unknown command: $1"
- exit 1
- ;;
- esac
- done
|