Skip to content

Commit f1e24a2

Browse files
sourcejedipoettering
authored andcommitted
units: don't kill the emergency shell when sysinit.target is triggered (systemd#6765)
Why --- The advantage of this is that starting sysinit.target from the emergency shell will no longer kill the emergency shell and lock you out of the system. Our docs already claimed that emergency.target was useful for "starting individual units in order to continue the boot process in steps". This resolves systemd#6509 for my purposes. Remaining limitation -------------------- Starting getty.target will still kill the shell, and if you don't have a root password you will then be locked out at that point. This is relevant to distributions which patch the sulogin system to permit logins when the root password is locked. Both Debian and RedHat used to follow this behaviour! Debian have been discussing what they could replace it with at https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=806852 So this doesn't quite achieve perfection, but I think it's a worthwhile change. It should be easier to understand the logic now it doesn't have such a big hole in it. Repairing the sysinit stage of the boot is the main reason we have emergency.target. And as discussed in the issue, sysinit.target gets pulled in implicitly as soon as any DefaultDependencies service is activated. How --- sysinit.target only needs to conflict with emergency.target. It didn't need to conflict with emergency.service as well. In theory the conflicts are pointless, we could just change the dependency of sysinit.target on local-fs.target from Wants to Requires. However, doing so would mean that when local-fs fails, the screen is flooded with yellow [DEPEND] failures. That would hinder the poor unfortunate admin, so let's not do that. There is no additional ordering requirement against emergency. If the failure happens, the job for sysinit will be cancelled instantly. We don't need to worry about when sysinit.target and its dependents would be stopped, because sysinit waits for local-fs before it starts. emergency.target is still necessarily stopped once we reach sysinit (you can't express a one-way conflict in pure unit directives). This is largely cosmetic... though perhaps it symbolizes that you're no longer in Emergency Mode if System Initialization is successful ;-). As a secondary advantage, the getty's which conflict on rescue.service now need to conflict on emergency.service as well. This makes the system more uniform and simpler to understand. The only other effect this should have is that `systemctl start emergency.target` is now practically the same as `systemctl start rescue.target`. The only units this command will stop are the conflicting getty units. Neither of those commands should ever be used. E.g. they will not stop the gdm.service unit on Fedora 26.
1 parent 21f0669 commit f1e24a2

File tree

4 files changed

+16
-9
lines changed

4 files changed

+16
-9
lines changed

units/[email protected]

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ ConditionPathExists=/dev/pts/%I
1919

2020
# IgnoreOnIsolate is an issue: when someone isolates rescue.target,
2121
# tradition expects that we shut down all but the main console.
22-
Conflicts=rescue.service
23-
Before=rescue.service
22+
Conflicts=rescue.service emergency.service
23+
Before=rescue.service emergency.service
2424

2525
[Service]
2626
# The '-o' option value tells agetty to replace 'login' arguments with an

units/[email protected]

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ IgnoreOnIsolate=yes
2323
# IgnoreOnIsolate causes issues with sulogin, if someone isolates
2424
# rescue.target or starts rescue.service from multi-user.target or
2525
# graphical.target.
26-
Conflicts=rescue.service
27-
Before=rescue.service
26+
Conflicts=rescue.service emergency.service
27+
Before=rescue.service emergency.service
2828

2929
# On systems without virtual consoles, don't start any getty. Note
3030
# that serial gettys are covered by [email protected], not this

units/[email protected]

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ IgnoreOnIsolate=yes
2424
# IgnoreOnIsolate causes issues with sulogin, if someone isolates
2525
# rescue.target or starts rescue.service from multi-user.target or
2626
# graphical.target.
27-
Conflicts=rescue.service
28-
Before=rescue.service
27+
Conflicts=rescue.service emergency.service
28+
Before=rescue.service emergency.service
2929

3030
[Service]
3131
# The '-o' option value tells agetty to replace 'login' arguments with an

units/sysinit.target

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,13 @@
88
[Unit]
99
Description=System Initialization
1010
Documentation=man:systemd.special(7)
11-
Conflicts=emergency.service emergency.target
12-
Wants=local-fs.target swap.target
13-
After=local-fs.target swap.target emergency.service emergency.target
11+
Wants=swap.target local-fs.target
12+
After=swap.target local-fs.target
13+
14+
# local-fs.target uses OnFailure="emergency.target" to start an emergency
15+
# shell. In that case we also need to cancel everything that relies on
16+
# local-fs.target. Flooding the screen with yellow [DEPEND] failures would
17+
# be unhelpful. Therefore we break the chain here. We use a Wants
18+
# dependency instead of Requires, and use a Conflict with emergency.target,
19+
# so that we are cancelled without actually failing any more units.
20+
Conflicts=emergency.target

0 commit comments

Comments
 (0)