<!ENTITY HIGH_RLIMIT_NOFILE "{{HIGH_RLIMIT_NOFILE}}">
<!ENTITY DEFAULT_DNSSEC_MODE "{{DEFAULT_DNSSEC_MODE_STR}}">
<!ENTITY DEFAULT_DNS_OVER_TLS_MODE "{{DEFAULT_DNS_OVER_TLS_MODE_STR}}">
+<!ENTITY FALLBACK_DEFAULT_TARGET "{{FALLBACK_DEFAULT_TARGET}}">
<!ENTITY DEFAULT_TIMEOUT_SEC "{{DEFAULT_TIMEOUT_SEC}} s">
<!ENTITY DEFAULT_USER_TIMEOUT_SEC "{{DEFAULT_USER_TIMEOUT_SEC}} s">
<!ENTITY SYSTEMD_DEFAULT_KEYMAP "{{SYSTEMD_DEFAULT_KEYMAP}}">
<?xml version='1.0'?> <!--*-nxml-*-->
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
- "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+ "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+<!ENTITY % entities SYSTEM "custom-entities.ent" >
+%entities;
+]>
<!-- SPDX-License-Identifier: LGPL-2.1-or-later -->
<refentry id="systemd.special" xmlns:xi="http://www.w3.org/2001/XInclude">
<varname>3</varname>, <varname>5</varname>, …; see
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>.</para>
+ <para>If <filename>default.target</filename> is not present on disk and no unit was requested on
+ the kernel command line, the default set at compile time will be used
+ (<filename>&FALLBACK_DEFAULT_TARGET;</filename>).</para>
+
+ <para>If the default unit or one of the fallbacks cannot be started, systemd starts
+ <filename>rescue.target</filename>.</para>
+
<para>For typical unit files please set <literal>WantedBy=</literal> to a regular target (like
<filename>multi-user.target</filename> or <filename>graphical.target</filename>),
instead of <filename>default.target</filename>, since such a service will also be run on special
endif
conf.set_quoted('FALLBACK_HOSTNAME', fallback_hostname)
+fallback_default_target = get_option('fallback-default-target')
+conf.set_quoted('FALLBACK_DEFAULT_TARGET', fallback_default_target)
+
extra_net_naming_schemes = []
extra_net_naming_map = []
foreach scheme: get_option('extra-net-naming-schemes').split(',')
'nobody user name' : nobody_user,
'nobody group name' : nobody_group,
'fallback hostname' : get_option('fallback-hostname'),
+ 'fallback default target' : fallback_default_target,
'default compression method' : compression,
'default DNSSEC mode' : default_dnssec,
'default DNS-over-TLS mode' : default_dns_over_tls,
description : 'maximum value in microseconds for the difference between RTC and epoch, exceeding which is considered an RTC error ["0" disables]')
option('default-user-shell', type : 'string', value : '/bin/bash',
description : 'default interactive shell')
+option('fallback-default-target', type : 'string', value : 'graphical.target',
+ description : 'unit to activate when default.target is not found on disk')
option('system-alloc-uid-min', type : 'integer', value : 0,
description : 'minimum system UID used when allocating')
log_debug("Activating default unit: %s", unit);
r = manager_load_startable_unit_or_warn(m, unit, NULL, &target);
- if (r < 0 && in_initrd() && !arg_default_unit) {
- /* Fall back to default.target, which we used to always use by default. Only do this if no
- * explicit configuration was given. */
-
- log_info("Falling back to %s.", SPECIAL_DEFAULT_TARGET);
+ if (r == -ENOENT && !arg_default_unit) {
+ if (in_initrd())
+ /* Fall back to default.target, which we used to always use by default.
+ * Only do this if no explicit configuration was given. */
+ unit = SPECIAL_DEFAULT_TARGET;
+ else
+ /* The default.target symlink was not found on disk and the target was not
+ * explicitly specified. Fall back to the target configured at build time
+ * via -Ddefault-target=. */
+ unit = FALLBACK_DEFAULT_TARGET;
- r = manager_load_startable_unit_or_warn(m, SPECIAL_DEFAULT_TARGET, NULL, &target);
+ log_info("Falling back to %s.", unit);
+ r = manager_load_startable_unit_or_warn(m, unit, NULL, &target);
}
if (r < 0) {
+ /* We failed. Activate rescue mode. */
log_info("Falling back to %s.", SPECIAL_RESCUE_TARGET);
r = manager_load_startable_unit_or_warn(m, SPECIAL_RESCUE_TARGET, NULL, &target);
test_unit_name_is_valid_one("foo.target.wants/plain.service", UNIT_NAME_ANY, false);
test_unit_name_is_valid_one("foo.target.conf/foo.conf", UNIT_NAME_ANY, false);
test_unit_name_is_valid_one("foo.target.requires/plain.socket", UNIT_NAME_ANY, false);
+
+ /* The build-time configured fallback for default.target must be a valid plain unit name. */
+ test_unit_name_is_valid_one(FALLBACK_DEFAULT_TARGET, UNIT_NAME_PLAIN, true);
}
static void test_unit_name_replace_instance_one(const char *pattern, const char *repl, const char *expected, int ret) {