/
snap
/
snapd
/
27710
/
usr
/
lib
/
snapd
/
/snap/snapd/27710/usr/lib/snapd
mkdir
upload
Name
Size
Mode
Actions
apparmor/
-
0755
rm
apparmor.d/
-
0755
rm
apparmor_parser
1700832
0755
edit
dl
rm
complete.sh
5394
0644
edit
dl
rm
etelpmoc.sh
7031
0644
edit
dl
rm
info
118
0644
edit
dl
rm
preseed.json
841
0644
edit
dl
rm
snap-bootstrap
13865297
0755
edit
dl
rm
snap-confine
218241
0755
edit
dl
rm
snap-confine.caps
143
0644
edit
dl
rm
snap-confine.v2-only.caps
121
0644
edit
dl
rm
snap-debug-info.sh
2372
0755
edit
dl
rm
snap-device-helper
67545
0755
edit
dl
rm
snap-discard-ns
51113
0755
edit
dl
rm
snap-exec
5616696
0755
edit
dl
rm
snap-failure
3219529
0755
edit
dl
rm
snap-fde-keymgr
5328969
0755
edit
dl
rm
snap-gdbserver-shim
1079280
0755
edit
dl
rm
snap-gpio-helper
3080265
0755
edit
dl
rm
snap-mgmt
22207
0755
edit
dl
rm
snap-mgmt-selinux
3269
0755
edit
dl
rm
snap-preseed
11771977
0755
edit
dl
rm
snap-recovery-chooser
9486409
0755
edit
dl
rm
snap-repair
8765513
0755
edit
dl
rm
snap-seccomp
3010897
0755
edit
dl
rm
snap-strace-shim
34273
0755
edit
dl
rm
snap-update-ns
6718584
0755
edit
dl
rm
snapctl
8455848
0755
edit
dl
rm
snapd
31965257
0755
edit
dl
rm
snapd-apparmor
2695241
0755
edit
dl
rm
snapd.core-fixup.sh
3826
0755
edit
dl
rm
snapd.run-from-snap
73
0755
edit
dl
rm
system-shutdown
38585
0755
edit
dl
rm
Edit:
/snap/snapd/27710/usr/lib/snapd/snap-mgmt
(22207B)
#!/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 STATIC_SNAP_TOOLING_DIR="/usr/lib/snapd" show_help() { exec cat <<'EOF' Usage: snap-mgmt.sh [OPTIONS] A simple script to cleanup snap installations. Options: --help Show this help message and exit --snap-tooling-dir=<path> Override default path to snapd tooling dir --force Force operation (relevant for mount directory migration) Actions: --purge Purge all snaps and their data --migrate-mount-dir Migrate mount directory from /snap to /var/lib/snapd/snap --check-mount-dir-migration Check system state required to run mount directory migration EOF } systemctl_stop() { unit="$1" echo "Stopping unit $unit" systemctl stop -q "$unit" || true for i in $(seq 10); do echo "Waiting until unit $unit is stopped [attempt $i]" if ! systemctl is-active -q "$unit"; then echo "$unit is stopped." break fi sleep .5 done if echo "$unit" | grep -q '.*\.service' ; then # snap services can request KillMode=process, which would result in only # the main process getting stopped, however during purge we are doing a # full cleanup systemctl kill -q "$unit" || true fi } is_component_mount_unit() { systemctl show "$1" -p Where | sed 's#Where=##' | grep -q '\(/snap\|/var/lib/snapd/snap\)/[^/]*/components/mnt/[^/]*/[^/]*' } 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 units=$(systemctl list-unit-files --no-legend --full 'snap.*' 'snap-*.mount' 'var-lib-snapd-snap-*.mount' | grep -vF snap.mount.service || true) mounts=$(echo "$units" | grep -e "^snap-.*\\.mount" -e "^var-lib-snapd-snap-.*\\.mount" | cut -f1 -d ' ') # *.snap and *.comp mount points snap_mounts="" components_mounts="" for mount in $mounts; do if is_component_mount_unit "$mount"; then components_mounts="$components_mounts $mount" else snap_mounts="$snap_mounts $mount" fi done # services from snaps services=$(echo "$units" | grep '^snap\..*\.service' | cut -f1 -d ' ') # slices from snaps slices=$(echo "$units" | grep '^snap\..*\.slice' | cut -f1 -d ' ') # component mounts must come first so that they are unmounted before we # unmount the snap mounts for unit in $services $components_mounts $snap_mounts $slices; 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' && ! is_component_mount_unit "$unit"; then # Transform /var/lib/snapd/snap/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 systemctl_where="$(systemctl show "$unit" -p Where)" # Where=/var/lib/snapd/snap/core/3440 -> core/3440 snap_rev="${systemctl_where#Where=*/snap/}" # core/3440 -> core snap="${snap_rev%/*}" # core/3440 -> 3440 rev="${snap_rev#*/}" # Transform: # Where=/var/lib/snapd/snap/core/3440 -> /var/lib/snapd/snap snap_mountpoint="${systemctl_where#Where=}" global_snaps_mount_dir="$(dirname "$(dirname "$snap_mountpoint")")" if [ -n "$snap" ]; then echo "Removing snap $snap" # aliases if [ -d "${global_snaps_mount_dir}/bin" ]; then find "${global_snaps_mount_dir}/bin" -maxdepth 1 -lname "$snap" -delete find "${global_snaps_mount_dir}/bin" -maxdepth 1 -lname "$snap.*" -delete fi # generated binaries rm -f "${global_snaps_mount_dir}/bin/$snap" # snap mount dir umount -l "$snap_mountpoint" 2> /dev/null || true rm -rf "$snap_mountpoint" rm -f "${global_snaps_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 "${global_snaps_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 # modules rm -f "/etc/modules-load.d/snap.${snap}.conf" rm -f "/etc/modprobe.d/snap.${snap}.conf" # 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 # user services, sockets, and timers - we make no attempt to stop any of them. # TODO: ask snapd to ask each snapd.session-agent.service to stop snaps # user-session services and stop itself. find /etc/systemd/user -name "snap.${snap}.*.timer" -o -name "snap.${snap}.*.socket" -o -name "snap.${snap}.*.service" | while read -r f; do 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" rm -f "/etc/systemd/system/snapd.mounts.target.wants/${unit}" done # Remove empty ".wants/" directory created by enabling mount units rmdir "/etc/systemd/system/snapd.mounts.target.wants" || true # Units may have been removed do a reload systemctl -q daemon-reload || true # Undo any bind mounts to /var/lib/snapd/snap, /snap or /var/snap done by parallel # installs or LP:#1668659 for mp in /snap /var/lib/snapd/snap /var/snap; do # btrfs bind mounts actually include subvolume in the filesystem-path # https://www.mail-archive.com/linux-btrfs@vger.kernel.org/msg51810.html if grep -q " $mp $mp " /proc/self/mountinfo || grep -q -e "\(/.*\)$mp $mp .* btrfs .*\(subvol=\1\)\(,.*\)\?\$" /proc/self/mountinfo ; then echo "umounting $mp" umount -l "$mp" || true fi done # stop snapd services for serv in snapd.autoimport.service snapd.seeded.service snapd.apparmor.service snapd.mounts.target snapd.mounts-pre.target; do systemctl_stop "$serv" done # snapd session-agent rm -f /etc/systemd/user/snapd.session-agent.socket rm -f /etc/systemd/user/snapd.session-agent.service rm -f /etc/systemd/user/sockets.target.wants/snapd.session-agent.socket # dbus activation configuration rm -f /etc/dbus-1/session.d/snapd.session-services.conf rm -f /etc/dbus-1/system.d/snapd.system-services.conf 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" for snap_mount_dir in /snap /var/lib/snapd/snap; do if [ -L "$snap_mount_dir" ]; then continue fi if [ -d "$snap_mount_dir" ]; then rm -rf "$snap_mount_dir" fi done rm -rf /var/snap echo "Removing leftover snap shared state data" rm -rf /var/lib/snapd/dbus-1/services/* rm -rf /var/lib/snapd/dbus-1/system-services/* rm -rf /var/lib/snapd/desktop/applications/* rm -rf /var/lib/snapd/environment/* 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 -rf /var/lib/snapd/inhibit/* rm -rf /var/lib/snapd/cgroup/* rm -rf /var/lib/snapd/desktop/* rm -f /var/lib/snapd/state.json rm -f /var/lib/snapd/state.lock 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 for snap_unit_prefix in snap var-lib-snapd-snap; do rm -f /etc/apparmor.d/$(echo "$snap_unit_prefix" | tr '-' '.').core.*.usr.lib.snapd.snap-confine done fi } ensure_snap_apps_stopped() { apps_or_services="$(find /sys/fs/cgroup/ -name 'snap.*.*.scope' -o -name 'snap.*.*.service')" if [ -n "$apps_or_services" ]; then ( echo "Found active snap services or applications in the following cgroups:" for n in $apps_or_services; do # transform snap.foo.bar.service into foo sn="$(basename "$n")" sn="${sn#snap.}" sn="${sn%%.*}" echo "- $n" echo " likely owned by snap: '$sn'" echo " PIDs: $(paste -s -d' ' "$n/cgroup.procs")" done ) >&2 return 1 fi return 0 } discard_mount_namespaces() { if [ ! -d /run/snapd/ns ]; then return fi tooldir="$1" if [ -z "$tooldir" ]; then tooldir="$STATIC_SNAP_TOOLING_DIR" fi echo "Discarding snap mount namespaces" find /run/snapd/ns/ -name '*.mnt' | while read -r mntns; do snname="$(basename "${mntns%.mnt}")" echo " ..discarding mount namespace of snap $snname" "$tooldir"/snap-discard-ns "$snname" done } _patch_service_unit_mount_dependencies() { mount_from_nopref="$1" mount_to_nopref="$2" svc_unit="$3" tmpdir="$4" # strip out snap. and <svc>.service, leaving the snap name only snap_name=${svc_unit#snap.} snap_name=${snap_name%%.*} old_mount_p="$(systemd-escape -p "$mount_from_nopref/$snap_name/")" new_mount_p="$(systemd-escape -p "$mount_to_nopref/$snap_name/")" # given e.g. /snap/test-snapd-service/ # systemd-escape produces: snap-test\x2dsnapd\x2dservice # but we need to convert to: snap-test\\x2dsnapd\\x2dservice # match entries like: # Requires=snap-foo- # After=snap-foo old_mount_p_escaped="${old_mount_p//\\/\\\\}" new_mount_p_escaped="${new_mount_p//\\/\\\\}" if ! grep -F -q "=${old_mount_p_escaped}" "/etc/systemd/system/$svc_unit" ; then echo "Service unit $svc_unit already patched" return fi echo "Updating service unit $svc_unit" cp -v "/etc/systemd/system/$svc_unit" "$tmpdir/backup/etc/systemd/system/$svc_unit" sed -i \ -e "s#^Requires=${old_mount_p_escaped}-#Requires=${new_mount_p_escaped}-#" \ -e "s#^After=${old_mount_p_escaped}-#After=${new_mount_p_escaped}-#" \ "/etc/systemd/system/$svc_unit" } _mount_dir_migrate() { mount_from="$1" mount_from_nopref="${mount_from#/}" mount_to="$2" mount_to_nopref="${mount_to#/}" # TODO error when $mount_from is a prefix of $mount_to set -x mount_from_escaped="$(systemd-escape -p "${mount_from_nopref}")" mount_to_escaped="$(systemd-escape -p "${mount_to_nopref}")" echo "Attempting migration of snap mount location:" echo " $mount_from -> $mount_to" if ! ensure_snap_apps_stopped; then echo "Please ensure all snap services or applications are stopped before attempting migration." >&2 exit 1 fi service_units=$(systemctl list-unit-files --no-legend --full 'snap.*.service' | cut -f1 -d' '|| true) mount_units=$(systemctl list-unit-files --no-legend --full "${mount_from_escaped}-*.mount" | cut -f1 -d' ' || true) echo "-- services" echo "$service_units" echo "-- mounts" echo "$mount_units" tmpdir="$(mktemp -d -t snap-mgmt-migrate.XXXXX)" mkdir -p "$tmpdir/backup/etc/systemd/system" echo "Backup saved to $tmpdir" # stop service units first, the services could theoretically reach out to # snapd while stopping echo "Stopping snap services..." for unit in $service_units; do echo "Stopping service $unit" systemctl stop "$unit" done echo "Stopping snapd..." systemctl stop snapd.socket snapd.service echo "Checking for snap applications or services that are still alive" if ! ensure_snap_apps_stopped; then echo "Found running snap services or applications." >&2 exit 1 fi discard_mount_namespaces "$STATIC_SNAP_TOOLING_DIR" new_units=() if [ -z "$mount_units" ]; then echo "All mount units already migrated or no snap mounts" else echo "Stopping mount units..." for unit in $mount_units; do echo "Stopping mount unit $unit" systemctl stop "$unit" done # make a backup copy of the whole snap mount dir, all units should be # stopped now, so this should be a tree of empty directories and current # symlinks cp -av "/$mount_from_nopref" "$tmpdir/backup/" echo "Updating mount units" # note, we're only iterating over mount units which still have the old name for unit in $mount_units; do # e.g. /snap/foo/123 # assumes systemd 246+ where_mount="$(systemctl show -p Where --value "$unit")" # e.g. /snap/foo snap_where_mount="$(dirname "$where_mount")" # some units may have been patched already echo "Updating mount unit $unit" # new unit name nn="${mount_to_escaped}-${unit#"$mount_from_escaped"-}" new_units+=("$nn") echo " ..new unit name $nn" # new mount point location n_where_mount="$mount_to/${where_mount#"$mount_from"}" # new snap mount location n_snap_where_mount="$(dirname "$n_where_mount")" echo " ..new mount path $n_where_mount" # make a backup copy mkdir -p "$tmpdir/backup/etc/systemd/system" cp -v "/etc/systemd/system/$unit" "$tmpdir/backup/etc/systemd/system/" echo " ..patching $unit" # Where=/snap/foo/123 -> Where=/var/lib/snapd/snap/foo/123 sed -e "s#Where=/${mount_from_nopref}/#Where=/${mount_to_nopref}/#" \ "/etc/systemd/system/$unit" > "/etc/systemd/system/$unit.swp" echo " ..renaming to $nn" mv -v "/etc/systemd/system/$unit.swp" "/etc/systemd/system/$nn" rm -v "/etc/systemd/system/$unit" if [ -L "/etc/systemd/system/multi-user.target.wants/$unit" ]; then # enabled units appear as symlinks rm -v "/etc/systemd/system/multi-user.target.wants/$unit" ln -sv "/etc/systemd/system/$nn" "/etc/systemd/system/multi-user.target.wants/$nn" fi # ensure mount point exists mkdir -p "$n_where_mount" # recreate current symlink if [ -L "$snap_where_mount/current" ] && [ ! -L "$n_snap_where_mount/current" ]; then cp -av "$snap_where_mount/current" "$n_snap_where_mount/current" fi done fi if [ -z "$service_units" ]; then echo "No snap service units" else for svc_unit in $service_units; do if ! [[ "$svc_unit" = *.service ]]; then continue fi _patch_service_unit_mount_dependencies "$mount_from_nopref" "$mount_to_nopref" "$svc_unit" "$tmpdir" done fi if [ -d "$mount_from/bin" ] && [ ! -L "$mount_from" ]; then cp -av "$mount_from/bin" "$mount_to/bin" fi if [ -f "$mount_from/README" ] && [ ! -L "$mount_from" ]; then cp -av "$mount_from/README" "$mount_to/README" fi # TODO: restore SELinux context of created files and directories? echo "Reloading systemd" systemctl daemon-reload echo "Starting new mount units" for new_unit in "${new_units[@]}"; do systemctl start "$new_unit" done if [ -d "$mount_from" ]; then echo "Renaming old snap mount directory $mount_from to $mount_from.old" if mountpoint "$mount_from"; then echo "Found $mount_from to be a mount point, likely from parallel instances" umount -l "$mount_from" fi mv -v "$mount_from" "${mount_from}.old" fi if [ "$mount_from" = "/snap" ] && [ ! -L "$mount_from" ]; then echo "Restoring ability to run classic snaps" ln -sv "$mount_to" "$mount_from" fi systemctl start snapd.socket snapd.service } # check whether migration is needed, returns 0 when needed _mount_dir_paths_check() { if [ -e /var/lib/snapd/snap ] && { [ -L /snap ] || [ ! -e /snap ] }; then echo "Snap mount directory migration already completed or not needed" >&2 return 1 fi return 0 } mount_dir_migrate() { force="$1" if ! _mount_dir_paths_check; then if [ "$force" = "yes" ]; then echo "WARNING: Forcing mount directory migration" >&2 else exit 0 fi fi echo "#############################################" echo "####### snap mount directory migration ######" echo "#############################################" echo echo "Please report any issues in the snapcraft forum at: https://forum.snapcraft.io/" echo _mount_dir_migrate "/snap" "/var/lib/snapd/snap" echo "######################################################" echo "####### snap mount directory migration complete ######" echo "######################################################" echo echo "You may start using snaps again." echo "System reboot is recommended." echo echo "A copy of old snap mount directory was saved as /snap.old" echo "Remove it manually by executing:" echo " rm -rf /snap.old" echo } mount_dir_migrate_check() { bad=0 not_needed=0 echo "Checking snap mount directories presence..." if ! _mount_dir_paths_check ; then not_needed=1 fi echo echo "Checking snap applications and services..." if ! ensure_snap_apps_stopped; then echo "Found running snap services or applications." bad=1 fi echo if [ "$bad" != 0 ]; then echo "Mount directory migration cannot continue." exit 1 elif [ "$not_needed" = 0 ]; then echo "System is ready for migration." fi } force=no action="" while [ -n "$1" ]; do case "$1" in --help) show_help exit ;; --snap-tooling-dir=*) STATIC_SNAP_TOOLING_DIR=${1#*=} shift ;; --purge) if [ -n "$action" ]; then echo "Cannot request purge when already doing '$action'" >&2 exit 1 fi action=purge shift ;; --migrate-mount-dir) if [ -n "$action" ]; then echo "Cannot request mount directory migration when already doing '$action'" >&2 exit 1 fi action=migrate-mount-dir shift ;; --check-mount-dir-migration) if [ -n "$action" ]; then echo "Cannot request mount directory migration check when already doing '$action'" >&2 exit 1 fi action=check-mount-dir-migration shift ;; --force) force=yes shift ;; *) echo "Unknown command: $1, see --help" >&2 exit 1 ;; esac done case "$action" in purge) purge ;; migrate-mount-dir) mount_dir_migrate "$force" ;; check-mount-dir-migration) mount_dir_migrate_check ;; *) if [ -z "$action" ]; then echo "No action specified, see --help" >&2 else echo "Unknown action '$action'" >&2 fi exit 1 ;; esac
Save
cmd:
run