github.com/meulengracht/snapd@v0.0.0-20210719210640-8bde69bcc84e/cmd/snap-mgmt/snap-mgmt.sh.in (about)

     1  #!/bin/bash
     2  
     3  # Overlord management of snapd for package manager actions.
     4  # Implements actions that would be invoked in %pre(un) actions for snapd.
     5  # Derived from the snapd.postrm scriptlet used in the Ubuntu packaging for
     6  # snapd.
     7  
     8  set -e
     9  set +x
    10  
    11  SNAP_MOUNT_DIR="@SNAP_MOUNT_DIR@"
    12  
    13  show_help() {
    14      exec cat <<'EOF'
    15  Usage: snap-mgmt.sh [OPTIONS]
    16  
    17  A simple script to cleanup snap installations.
    18  
    19  optional arguments:
    20    --help                           Show this help message and exit
    21    --snap-mount-dir=<path>          Provide a path to be used as $SNAP_MOUNT_DIR
    22    --purge                          Purge all data from $SNAP_MOUNT_DIR
    23  EOF
    24  }
    25  
    26  SNAP_UNIT_PREFIX="$(systemd-escape -p ${SNAP_MOUNT_DIR})"
    27  
    28  systemctl_stop() {
    29      unit="$1"
    30      if systemctl is-active -q "$unit"; then
    31          echo "Stopping $unit"
    32          systemctl stop -q "$unit" || true
    33      fi
    34  }
    35  
    36  purge() {
    37      # shellcheck disable=SC1091
    38      distribution=$(. /etc/os-release; echo "${ID}-${VERSION_ID}")
    39  
    40      if [ "$distribution" = "ubuntu-14.04" ]; then
    41          # snap.mount.service is a trusty thing
    42          systemctl_stop snap.mount.service
    43      fi
    44  
    45      # Undo any bind mounts to ${SNAP_MOUNT_DIR} or /var/snap done by parallel
    46      # installs or LP:#1668659
    47      for mp in "$SNAP_MOUNT_DIR" /var/snap; do
    48          if grep -q " $mp $mp" /proc/self/mountinfo; then
    49              umount -l "$mp" || true
    50          fi
    51      done
    52  
    53      units=$(systemctl list-unit-files --no-legend --full | grep -vF snap.mount.service || true)
    54      # *.snap mount points
    55      mounts=$(echo "$units" | grep "^${SNAP_UNIT_PREFIX}[-.].*\\.mount" | cut -f1 -d ' ')
    56      # services from snaps
    57      services=$(echo "$units" | grep '^snap\..*\.service' | cut -f1 -d ' ')
    58      # slices from snaps
    59      slices=$(echo "$units" | grep '^snap\..*\.slice' | cut -f1 -d ' ')
    60      for unit in $services $mounts $slices; do
    61          # ensure its really a snap mount unit or systemd unit
    62          if ! grep -q 'What=/var/lib/snapd/snaps/' "/etc/systemd/system/$unit" && ! grep -q 'X-Snappy=yes' "/etc/systemd/system/$unit"; then
    63              echo "Skipping non-snapd systemd unit $unit"
    64              continue
    65          fi
    66  
    67          echo "Stopping $unit"
    68          systemctl_stop "$unit"
    69  
    70          if echo "$unit" | grep -q '.*\.mount' ; then
    71              # Transform ${SNAP_MOUNT_DIR}/core/3440 -> core/3440 removing any
    72              # extra / preceding snap name, eg:
    73              #  /var/lib/snapd/snap/core/3440  -> core/3440
    74              #  /snap/core/3440                -> core/3440
    75              #  /snap/core//3440               -> core/3440
    76              # NOTE: we could have used `systemctl show $unit -p Where --value`
    77              # but systemd 204 shipped with Ubuntu 14.04 does not support this
    78              snap_rev=$(systemctl show "$unit" -p Where | sed -e 's#Where=##' -e "s#$SNAP_MOUNT_DIR##" -e 's#^/*##')
    79              snap=$(echo "$snap_rev" |cut -f1 -d/)
    80              rev=$(echo "$snap_rev" |cut -f2 -d/)
    81              if [ -n "$snap" ]; then
    82                  echo "Removing snap $snap"
    83                  # aliases
    84                  if [ -d "${SNAP_MOUNT_DIR}/bin" ]; then
    85                      find "${SNAP_MOUNT_DIR}/bin" -maxdepth 1 -lname "$snap" -delete
    86                      find "${SNAP_MOUNT_DIR}/bin" -maxdepth 1 -lname "$snap.*" -delete
    87                  fi
    88                  # generated binaries
    89                  rm -f "${SNAP_MOUNT_DIR}/bin/$snap"
    90                  rm -f "${SNAP_MOUNT_DIR}/bin/$snap".*
    91                  # snap mount dir
    92                  umount -l "${SNAP_MOUNT_DIR}/$snap/$rev" 2> /dev/null || true
    93                  rm -rf "${SNAP_MOUNT_DIR:?}/$snap/$rev"
    94                  rm -f "${SNAP_MOUNT_DIR}/$snap/current"
    95                  # snap data dir
    96                  rm -rf "/var/snap/$snap/$rev"
    97                  rm -rf "/var/snap/$snap/common"
    98                  rm -f "/var/snap/$snap/current"
    99                  # opportunistic remove (may fail if there are still revisions left)
   100                  for d in "${SNAP_MOUNT_DIR}/$snap" "/var/snap/$snap"; do
   101                      if [ -d "$d" ]; then
   102                          rmdir --ignore-fail-on-non-empty "$d"
   103                      fi
   104                  done
   105                  # udev rules
   106                  find /etc/udev/rules.d -name "*-snap.${snap}.rules" -execdir rm -f "{}" \;
   107                  # dbus policy files
   108                  if [ -d /etc/dbus-1/system.d ]; then
   109                      find /etc/dbus-1/system.d -name "snap.${snap}.*.conf" -execdir rm -f "{}" \;
   110                  fi
   111                  # modules
   112                  rm -f "/etc/modules-load.d/snap.${snap}.conf"
   113                  # timer and socket units
   114                  find /etc/systemd/system -name "snap.${snap}.*.timer" -o -name "snap.${snap}.*.socket" | while read -r f; do
   115                      systemctl_stop "$(basename "$f")"
   116                      rm -f "$f"
   117                  done
   118                  # user services, sockets, and timers - we make no attempt to stop any of them.
   119                  # TODO: ask snapd to ask each snapd.session-agent.service to stop snaps
   120                  # user-session services and stop itself.
   121                  find /etc/systemd/user -name "snap.${snap}.*.timer" -o -name "snap.${snap}.*.socket" -o -name "snap.${snap}.*.service" | while read -r f; do
   122                      rm -f "$f"
   123                  done
   124              fi
   125          fi
   126  
   127          echo "Removing $unit"
   128          rm -f "/etc/systemd/system/$unit"
   129          rm -f "/etc/systemd/system/multi-user.target.wants/$unit"
   130      done
   131  
   132      # snapd session-agent
   133      rm -f /etc/systemd/user/snapd.session-agent.socket
   134      rm -f /etc/systemd/user/snapd.session-agent.service
   135      rm -f /etc/systemd/user/sockets.target.wants/snapd.session-agent.socket
   136  
   137      # dbus activation configuration
   138      rm -f /etc/dbus-1/session.d/snapd.session-services.conf
   139      rm -f /etc/dbus-1/system.d/snapd.system-services.conf
   140  
   141      echo "Discarding preserved snap namespaces"
   142      # opportunistic as those might not be actually mounted
   143      if [ -d /run/snapd/ns ]; then
   144          if [ "$(find /run/snapd/ns/ -name "*.mnt" | wc -l)" -gt 0 ]; then
   145              for mnt in /run/snapd/ns/*.mnt; do
   146                  umount -l "$mnt" || true
   147                  rm -f "$mnt"
   148              done
   149          fi
   150          find /run/snapd/ns/ \( -name '*.fstab' -o -name '*.user-fstab' -o -name '*.info' \) -delete
   151          umount -l /run/snapd/ns/ || true
   152      fi
   153  
   154      echo "Removing downloaded snaps"
   155      rm -rf /var/lib/snapd/snaps/*
   156  
   157      echo "Removing features exported from snapd to helper tools"
   158      rm -rf /var/lib/snapd/features
   159  
   160      echo "Final directory cleanup"
   161      rm -rf "${SNAP_MOUNT_DIR}"
   162      rm -rf /var/snap
   163  
   164      echo "Removing leftover snap shared state data"
   165      rm -rf /var/lib/snapd/dbus-1/services/*
   166      rm -rf /var/lib/snapd/dbus-1/system-services/*
   167      rm -rf /var/lib/snapd/desktop/applications/*
   168      rm -rf /var/lib/snapd/seccomp/bpf/*
   169      rm -rf /var/lib/snapd/device/*
   170      rm -rf /var/lib/snapd/assertions/*
   171      rm -rf /var/lib/snapd/cookie/*
   172      rm -rf /var/lib/snapd/cache/*
   173      rm -rf /var/lib/snapd/mount/*
   174      rm -rf /var/lib/snapd/sequence/*
   175      rm -rf /var/lib/snapd/apparmor/*
   176      rm -rf /var/lib/snapd/inhibit/*
   177      rm -f /var/lib/snapd/state.json
   178      rm -f /var/lib/snapd/system-key
   179  
   180      echo "Removing snapd catalog cache"
   181      rm -rf /var/cache/snapd/*
   182  
   183      if test -d /etc/apparmor.d; then
   184          # Remove auto-generated rules for snap-confine from the 'core' snap
   185          echo "Removing extra snap-confine apparmor rules"
   186          # shellcheck disable=SC2046
   187          rm -f /etc/apparmor.d/$(echo "$SNAP_UNIT_PREFIX" | tr '-' '.').core.*.usr.lib.snapd.snap-confine
   188      fi
   189  }
   190  
   191  while [ -n "$1" ]; do
   192      case "$1" in
   193          --help)
   194              show_help
   195              exit
   196              ;;
   197          --snap-mount-dir=*)
   198              SNAP_MOUNT_DIR=${1#*=}
   199              SNAP_UNIT_PREFIX=$(systemd-escape -p "$SNAP_MOUNT_DIR")
   200              shift
   201              ;;
   202          --purge)
   203              purge
   204              shift
   205              ;;
   206          *)
   207              echo "Unknown command: $1"
   208              exit 1
   209              ;;
   210      esac
   211  done