Package: init-system-helpers
Version: 1.69+nmu1
Severity: normal
Tags: patch
User: [email protected]
Usertags: origin-ubuntu stonking ubuntu-patch
Dear Maintainer,
I have 2 packages that provide that same systemd unit file
and when I try to replace one by the other, the systemd unit
becomes disabled since the link has been removed on the purge
of the second package.
The current behavior of deb-systemd-helper purge:
If the unit files are provided by 2 packages (that Replaces and
Conflicst each other). Purging the first package while the second
is install removes all the links and break the first package.
This commit propose a more conservative purging behavior by
keeping symlinks during purge when their target unit file still exists,
preventing one package's purge from disabling a unit still provided
by another installed package.
* deb-systemd-helper: preserve links to existing units during purge
Thanks for considering the patch.
-- System Information:
Debian Release: trixie/sid
APT prefers noble-updates
APT policy: (500, 'noble-updates'), (500, 'noble-security'), (500, 'noble'),
(100, 'noble-backports')
Architecture: amd64 (x86_64)
Kernel: Linux 7.0.0-28-generic (SMP w/16 CPU threads; PREEMPT)
Kernel taint flags: TAINT_PROPRIETARY_MODULE, TAINT_OOT_MODULE
Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8), LANGUAGE not set
Shell: /bin/sh linked to /usr/bin/dash
Init: systemd (via /run/systemd/system)
LSM: AppArmor: enabled
Versions of packages init-system-helpers is related to:
pn insserv <none>
diff -Nru init-system-helpers-1.69+nmu1/script/deb-systemd-helper
init-system-helpers-1.69+nmu1ubuntu1/script/deb-systemd-helper
--- init-system-helpers-1.69+nmu1/script/deb-systemd-helper 2022-07-13
21:55:56.000000000 +0200
+++ init-system-helpers-1.69+nmu1ubuntu1/script/deb-systemd-helper
2026-08-23 00:45:26.000000000 +0200
@@ -447,19 +447,26 @@
assertdpkgroot($dsh_state, "remove_links");
assertnotdpkgroot($service_path, "remove_links");
- if (is_purge()) {
+ # If the unit file still exists on disk, another still-installed package
+ # also ships it (e.g. identical shared conffiles, or reached via Also=
+ # from a package other than the one being purged); don't wipe out its
+ # enabled-state bookkeeping just because we are purging.
+ my $can_purge = is_purge() && ! -f "$dpkg_root$service_path";
+
+ if ($can_purge) {
unlink($dsh_state) if -e $dsh_state;
}
# Also disable all the units which were enabled when this one was enabled.
for my $link (@entries) {
# Delete the corresponding state file:
- # • Always when purging
+ # • Always when purging (and no other package still ships the unit)
# • If the user did not disable (= link still exists) the service.
# If we don’t do this, the link will be deleted a few lines down,
# but not re-created when re-installing the package.
assertdpkgroot($link, "remove_links");
- if (is_purge() || -l $link) {
+ next if is_purge() && -e $link;
+ if ($can_purge || -l $link) {
my $link_state = $link;
$link_state =~
s,^\Q$dpkg_root\E/etc/systemd/$instance/,$enabled_state_dir/,;
unlink($link_state);