There are a few reasons that isn’t true.
Updating binaries that are currently in use only appears to work. Most of the time you can get away with it. This works because when a file is replaced on a UNIX system, processes that already have it open continue using the old inode. In effect, you temporarily have two versions of the file on disk: the new one linked in the filesystem, and the old one still referenced by open file descriptors. The old copy remains until all handles to it are closed. Even ext2 from 1993 operates this way.
For simple cases (or minor updates), you can update while something is running and then restart the affected service. That often works fine. If you update a shared library without breaking ABI compatibility (things like function names), processes using the old version will keep using it until restarted, and newly started processes will use the new one. As long as the library hasn’t changed in an incompatible way, things will behave perfectly fine.
That’s a simplification. The real picture is more complex.
The safest approach is not to overwrite components that are actively in use.
You’re playing with fire otherwise, especially when updating an entire desktop environment.
A commonly recommended approach here is to stop the display manager:
sudo systemctl stop gdm lightdm sddm plasmalogin
Which avoids most problems..
However, if you truly want to update from a TTY, the cleaner method is to switch the system out of graphical.target and into multi-user.target. This stops the display manager and related graphical dependencies in a controlled way.
And this works for any DE!
When you only stop the login manager, there’s still a lot running under graphical.target, so I try to minimise that.
I enter the TTY by running:
sudo systemctl isolate multi-user
(.target is implied for the isolate command.)
I used to only update in rescue.target, or single user mode. But I hate killing off all my terminal sessions! But it really is the safest way.
Once truly in the TTY, then I run the updates, and reboot.
But if you want to return to the *GUI,* you can just run:
sudo systemctl isolate graphical
Old-school SysV users will remember init <runlevel>. This is the systemd equivalent, just with dependency awareness instead of fixed runlevels.
You can see the difference on this fairly vanilla Plasma install:
systemctl list-dependencies rescue.target
stdout
rescue.target
○ ├─rescue.service
● └─sysinit.target
● ├─dev-hugepages.mount
● ├─dev-mqueue.mount
● ├─kmod-static-nodes.service
○ ├─ldconfig.service
● ├─lvm2-lvmpolld.socket
● ├─lvm2-monitor.service
● ├─plymouth-read-write.service
● ├─plymouth-start.service
● ├─proc-sys-fs-binfmt_misc.automount
● ├─sys-fs-fuse-connections.mount
● ├─sys-kernel-config.mount
● ├─sys-kernel-debug.mount
● ├─sys-kernel-tracing.mount
○ ├─systemd-ask-password-console.path
○ ├─systemd-binfmt.service
○ ├─systemd-boot-random-seed.service
○ ├─systemd-firstboot.service
○ ├─systemd-hibernate-clear.service
○ ├─systemd-hwdb-update.service
○ ├─systemd-journal-catalog-update.service
● ├─systemd-journal-flush.service
● ├─systemd-journald.service
○ ├─systemd-machine-id-commit.service
● ├─systemd-modules-load.service
○ ├─systemd-pcrmachine.service
○ ├─systemd-pcrnvdone.service
○ ├─systemd-pcrphase-sysinit.service
○ ├─systemd-pcrphase.service
○ ├─systemd-pcrproduct.service
● ├─systemd-random-seed.service
○ ├─systemd-repart.service
● ├─systemd-sysctl.service
○ ├─systemd-sysusers.service
● ├─systemd-timesyncd.service
● ├─systemd-tmpfiles-setup-dev-early.service
● ├─systemd-tmpfiles-setup-dev.service
● ├─systemd-tmpfiles-setup.service
○ ├─systemd-tpm2-setup-early.service
○ ├─systemd-tpm2-setup.service
● ├─systemd-udev-trigger.service
● ├─systemd-udevd.service
○ ├─systemd-update-done.service
● ├─systemd-update-utmp.service
● ├─cryptsetup.target
● ├─imports.target
● ├─integritysetup.target
● ├─local-fs.target
● │ ├─-.mount
● │ ├─\x2esnapshots.mount
● │ ├─boot-efi.mount
● │ ├─home-.snapshots.mount
● │ ├─home.mount
● │ ├─systemd-remount-fs.service
● │ ├─tmp.mount
● ├─kmod-static-nodes.service
○ ├─ldconfig.service
● ├─lvm2-lvmpolld.socket
● ├─lvm2-monitor.service
● ├─plymouth-read-write.service
● ├─plymouth-start.service
● ├─proc-sys-fs-binfmt_misc.automount
● ├─sys-fs-fuse-connections.mount
● ├─sys-kernel-config.mount
● ├─sys-kernel-debug.mount
● ├─sys-kernel-tracing.mount
○ ├─systemd-ask-password-console.path
○ ├─systemd-binfmt.service
○ ├─systemd-boot-random-seed.service
○ ├─systemd-firstboot.service
○ ├─systemd-hibernate-clear.service
○ ├─systemd-hwdb-update.service
○ ├─systemd-journal-catalog-update.service
● ├─systemd-journal-flush.service
● ├─systemd-journald.service
○ ├─systemd-machine-id-commit.service
● ├─systemd-modules-load.service
○ ├─systemd-pcrmachine.service
○ ├─systemd-pcrnvdone.service
○ ├─systemd-pcrphase-sysinit.service
○ ├─systemd-pcrphase.service
○ ├─systemd-pcrproduct.service
● ├─systemd-random-seed.service
○ ├─systemd-repart.service
● ├─systemd-sysctl.service
○ ├─systemd-sysusers.service
● ├─systemd-timesyncd.service
● ├─systemd-tmpfiles-setup-dev-early.service
● ├─systemd-tmpfiles-setup-dev.service
● ├─systemd-tmpfiles-setup.service
○ ├─systemd-tpm2-setup-early.service
○ ├─systemd-tpm2-setup.service
● ├─systemd-udev-trigger.service
● ├─systemd-udevd.service
○ ├─systemd-update-done.service
● ├─systemd-update-utmp.service
● ├─cryptsetup.target
● ├─imports.target
● ├─integritysetup.target
● ├─local-fs.target
● │ ├─-.mount
● │ ├─\x2esnapshots.mount
● │ ├─boot-efi.mount
● │ ├─home-.snapshots.mount
● │ ├─home.mount
● │ ├─systemd-remount-fs.service
● │ ├─tmp.mount
● │ ├─var-cache.mount
● │ └─var-log.mount
● ├─swap.target
● │ └─dev-disk-by\x2duuid-a9ddc99c\x2d63fa\x2d454f\x2d9692\x2da5d3bb0e961a.swap
● └─veritysetup.target
systemctl list-dependencies graphical.target
stdout
graphical.target
● ├─plasmalogin.service
● └─multi-user.target
● ├─cronie.service
● ├─dbus-broker.service
● ├─ModemManager.service
● ├─NetworkManager.service
● ├─plymouth-quit-wait.service
● ├─plymouth-quit.service
● ├─sshd.service
● ├─systemd-ask-password-wall.path
● ├─systemd-logind.service
● ├─systemd-user-sessions.service
● ├─basic.target
● │ ├─-.mount
○ │ ├─beesd@enp1s0.service
● │ ├─tmp.mount
● │ ├─paths.target
● │ ├─slices.target
● │ │ ├─-.slice
● │ │ └─system.slice
● │ ├─sockets.target
● │ │ ├─dbus.socket
● │ │ ├─dirmngr@etc-pacman.d-gnupg.socket
● │ │ ├─dm-event.socket
● │ │ ├─gpg-agent-browser@etc-pacman.d-gnupg.socket
● │ │ ├─gpg-agent-extra@etc-pacman.d-gnupg.socket
● │ │ ├─gpg-agent-ssh@etc-pacman.d-gnupg.socket
● │ │ ├─gpg-agent@etc-pacman.d-gnupg.socket
● │ │ ├─keyboxd@etc-pacman.d-gnupg.socket
● │ │ ├─polkit-agent-helper.socket
● │ │ ├─sshd-unix-local.socket
● │ │ ├─systemd-ask-password.socket
● │ │ ├─systemd-bootctl.socket
● │ │ ├─systemd-coredump.socket
● │ │ ├─systemd-creds.socket
● │ │ ├─systemd-factory-reset.socket
● │ │ ├─systemd-hostnamed.socket
● │ │ ├─systemd-importd.socket
● │ │ ├─systemd-journald-dev-log.socket
● │ │ ├─systemd-journald.socket
● │ │ ├─systemd-logind-varlink.socket
● │ │ ├─systemd-machined.socket
● │ │ ├─systemd-mute-console.socket
○ │ │ ├─systemd-pcrextend.socket
○ │ │ ├─systemd-pcrlock.socket
● │ │ ├─systemd-repart.socket
● │ │ ├─systemd-sysext.socket
● │ │ ├─systemd-udevd-control.socket
● │ │ ├─systemd-udevd-kernel.socket
● │ │ ├─systemd-udevd-varlink.socket
● │ │ └─systemd-userdbd.socket
● │ ├─sysinit.target
● │ │ ├─dev-hugepages.mount
● │ │ ├─dev-mqueue.mount
● │ │ ├─kmod-static-nodes.service
○ │ │ ├─ldconfig.service
● │ │ ├─lvm2-lvmpolld.socket
● │ │ ├─lvm2-monitor.service
● │ │ ├─plymouth-read-write.service
● │ │ ├─plymouth-start.service
● │ │ ├─proc-sys-fs-binfmt_misc.automount
● │ │ ├─sys-fs-fuse-connections.mount
● │ │ ├─sys-kernel-config.mount
● │ │ ├─sys-kernel-debug.mount
● │ │ ├─sys-kernel-tracing.mount
○ │ │ ├─systemd-ask-password-console.path
○ │ │ ├─systemd-binfmt.service
○ │ │ ├─systemd-boot-random-seed.service
○ │ │ ├─systemd-firstboot.service
○ │ │ ├─systemd-hibernate-clear.service
○ │ │ ├─systemd-hwdb-update.service
○ │ │ ├─systemd-journal-catalog-update.service
● │ │ ├─systemd-journal-flush.service
● │ │ ├─systemd-journald.service
○ │ │ ├─systemd-machine-id-commit.service
● │ │ ├─systemd-modules-load.service
○ │ │ ├─systemd-pcrmachine.service
○ │ │ ├─systemd-pcrnvdone.service
○ │ │ ├─systemd-pcrphase-sysinit.service
○ │ │ ├─systemd-pcrphase.service
○ │ │ ├─systemd-pcrproduct.service
● │ │ ├─systemd-random-seed.service
○ │ │ ├─systemd-repart.service
● │ │ ├─systemd-sysctl.service
○ │ │ ├─systemd-sysusers.service
● │ │ ├─systemd-timesyncd.service
● │ │ ├─systemd-tmpfiles-setup-dev-early.service
● │ │ ├─systemd-tmpfiles-setup-dev.service
● │ │ ├─systemd-tmpfiles-setup.service
○ │ │ ├─systemd-tpm2-setup-early.service
○ │ │ ├─systemd-tpm2-setup.service
● │ │ ├─systemd-udev-trigger.service
● │ │ ├─systemd-udevd.service
○ │ │ ├─systemd-update-done.service
● │ │ ├─systemd-update-utmp.service
● │ │ ├─cryptsetup.target
● │ │ ├─imports.target
● │ │ ├─integritysetup.target
● │ │ ├─local-fs.target
● │ │ │ ├─-.mount
● │ │ │ ├─\x2esnapshots.mount
● │ │ │ ├─boot-efi.mount
● │ │ │ ├─home-.snapshots.mount
● │ │ │ ├─home.mount
● │ │ │ ├─systemd-remount-fs.service
● │ │ │ ├─tmp.mount
● │ │ │ ├─var-cache.mount
● │ │ │ └─var-log.mount
● │ │ ├─swap.target
● │ │ │ └─dev-disk-by\x2duuid-a9ddc99c\x2d63fa\x2d454f\x2d9692\x2da5d3bb0e961a.…
● │ │ └─veritysetup.target
● │ └─timers.target
● │ ├─archlinux-keyring-wkd-sync.timer
○ │ │ ├─systemd-hibernate-clear.service
○ │ │ ├─systemd-hwdb-update.service
○ │ │ ├─systemd-journal-catalog-update.service
● │ │ ├─systemd-journal-flush.service
● │ │ ├─systemd-journald.service
○ │ │ ├─systemd-machine-id-commit.service
● │ │ ├─systemd-modules-load.service
○ │ │ ├─systemd-pcrmachine.service
○ │ │ ├─systemd-pcrnvdone.service
○ │ │ ├─systemd-pcrphase-sysinit.service
○ │ │ ├─systemd-pcrphase.service
○ │ │ ├─systemd-pcrproduct.service
● │ │ ├─systemd-random-seed.service
○ │ │ ├─systemd-repart.service
● │ │ ├─systemd-sysctl.service
○ │ │ ├─systemd-sysusers.service
● │ │ ├─systemd-timesyncd.service
● │ │ ├─systemd-tmpfiles-setup-dev-early.service
● │ │ ├─systemd-tmpfiles-setup-dev.service
● │ │ ├─systemd-tmpfiles-setup.service
○ │ │ ├─systemd-tpm2-setup-early.service
○ │ │ ├─systemd-tpm2-setup.service
● │ │ ├─systemd-udev-trigger.service
● │ │ ├─systemd-udevd.service
○ │ │ ├─systemd-update-done.service
● │ │ ├─systemd-update-utmp.service
● │ │ ├─cryptsetup.target
● │ │ ├─imports.target
● │ │ ├─integritysetup.target
● │ │ ├─local-fs.target
● │ │ │ ├─-.mount
● │ │ │ ├─\x2esnapshots.mount
● │ │ │ ├─boot-efi.mount
● │ │ │ ├─home-.snapshots.mount
● │ │ │ ├─home.mount
● │ │ │ ├─systemd-remount-fs.service
● │ │ │ ├─tmp.mount
● │ │ │ ├─var-cache.mount
● │ │ │ └─var-log.mount
● │ │ ├─swap.target
● │ │ │ └─dev-disk-by\x2duuid-a9ddc99c\x2d63fa\x2d454f\x2d9692\x2da5d3bb0e961a.…
● │ │ └─veritysetup.target
● │ └─timers.target
● │ ├─archlinux-keyring-wkd-sync.timer
● │ ├─fstrim.timer
● │ ├─logrotate.timer
● │ ├─man-db.timer
● │ ├─pamac-cleancache.timer
● │ ├─pamac-mirrorlist.timer
● │ ├─shadow.timer
● │ ├─snapper-cleanup.timer
● │ ├─snapper-timeline.timer
● │ └─systemd-tmpfiles-clean.timer
● ├─getty.target
○ │ └─getty@tty1.service
● └─remote-fs.target
○ └─var-lib-machines.mount
Too Long Didn’t Click:
systemctl list-dependencies rescue.target --no-pager | wc
62 133 2310
systemctl list-dependencies graphical.target --no-pager | wc
127 464 5395