mirror of
https://github.com/systemd/systemd
synced 2025-11-21 01:34:44 +01:00
Compare commits
24 Commits
468cc02045
...
67a1069b72
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
67a1069b72 | ||
|
|
377aaf6a27 | ||
|
|
89950fc6a7 | ||
|
|
c058ff41cb | ||
|
|
469c22f72d | ||
|
|
11df9345d3 | ||
|
|
5036c8f58b | ||
|
|
e76c73505b | ||
|
|
49b7015314 | ||
|
|
437a881f94 | ||
|
|
897018cc47 | ||
|
|
ba809a8584 | ||
|
|
f3c0428c39 | ||
|
|
e9ca92bd74 | ||
|
|
0d48c2b4ee | ||
|
|
2ebc1de3fb | ||
|
|
87bbee1c96 | ||
|
|
d8b74adbff | ||
|
|
7c85318b34 | ||
|
|
67f1eeff2a | ||
|
|
c286c9c894 | ||
|
|
a228628012 | ||
|
|
f7840ac0e0 | ||
|
|
b734f8d37b |
@ -825,12 +825,9 @@ mouse:usb:v0e8fp00a7:name:DaKai 2.4G RX:*
|
|||||||
# Nulea
|
# Nulea
|
||||||
##########################################
|
##########################################
|
||||||
|
|
||||||
# Note: it is possible that other devices may use the same wireless dongle,
|
# Note: The Nulea uses a generic USB dongle. Overriding its value would cause
|
||||||
# as such this could require revisiting if it causes issues with other mice
|
# other mice to be erroneously registered as trackballs, so only bluetooth
|
||||||
# Nulea M501 Wireless Trackball (USB Receiver)
|
# detection is added.
|
||||||
mouse:usb:v25a7pfa61:name:Compx 2.4G Receiver Mouse:*
|
|
||||||
ID_INPUT_TRACKBALL=1
|
|
||||||
|
|
||||||
# Nulea M501 Wireless Trackball (Bluetooth)
|
# Nulea M501 Wireless Trackball (Bluetooth)
|
||||||
mouse:bluetooth:v000ep3412:name:Nulea BT5.0 Mouse:*
|
mouse:bluetooth:v000ep3412:name:Nulea BT5.0 Mouse:*
|
||||||
ID_INPUT_TRACKBALL=1
|
ID_INPUT_TRACKBALL=1
|
||||||
|
|||||||
@ -375,10 +375,7 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
|
|||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term>
|
<term><command>list-dependencies</command> <optional><replaceable>UNIT</replaceable>…</optional></term>
|
||||||
<command>list-dependencies</command>
|
|
||||||
<optional><replaceable>UNIT</replaceable>...</optional>
|
|
||||||
</term>
|
|
||||||
|
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>Shows units required and wanted by the specified
|
<para>Shows units required and wanted by the specified
|
||||||
@ -694,12 +691,7 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
|
|||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term>
|
<term><command>bind</command> <replaceable>UNIT</replaceable> <replaceable>PATH</replaceable> [<replaceable>PATH</replaceable>]</term>
|
||||||
<command>bind</command>
|
|
||||||
<replaceable>UNIT</replaceable>
|
|
||||||
<replaceable>PATH</replaceable>
|
|
||||||
[<replaceable>PATH</replaceable>]
|
|
||||||
</term>
|
|
||||||
|
|
||||||
<listitem><para>Bind-mounts a file or directory from the host into the specified unit's mount
|
<listitem><para>Bind-mounts a file or directory from the host into the specified unit's mount
|
||||||
namespace. The first path argument is the source file or directory on the host, the second path
|
namespace. The first path argument is the source file or directory on the host, the second path
|
||||||
@ -726,13 +718,7 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
|
|||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term>
|
<term><command>mount-image</command> <replaceable>UNIT</replaceable> <replaceable>IMAGE</replaceable> [<replaceable>PATH</replaceable> [<replaceable>PARTITION_NAME</replaceable>:<replaceable>MOUNT_OPTIONS</replaceable>]]</term>
|
||||||
<command>mount-image</command>
|
|
||||||
<replaceable>UNIT</replaceable>
|
|
||||||
<replaceable>IMAGE</replaceable>
|
|
||||||
[<replaceable>PATH</replaceable>
|
|
||||||
[<replaceable>PARTITION_NAME</replaceable>:<replaceable>MOUNT_OPTIONS</replaceable>]]
|
|
||||||
</term>
|
|
||||||
|
|
||||||
<listitem><para>Mounts an image from the host into the specified unit's mount namespace. The first
|
<listitem><para>Mounts an image from the host into the specified unit's mount namespace. The first
|
||||||
path argument is the source image on the host, the second path argument is the destination
|
path argument is the source image on the host, the second path argument is the destination
|
||||||
@ -1215,10 +1201,8 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
|
|||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><command>add-wants <replaceable>TARGET</replaceable>
|
<term><command>add-wants <replaceable>TARGET</replaceable> <replaceable>UNIT</replaceable>…</command></term>
|
||||||
<replaceable>UNIT</replaceable>…</command></term>
|
<term><command>add-requires <replaceable>TARGET</replaceable> <replaceable>UNIT</replaceable>…</command></term>
|
||||||
<term><command>add-requires <replaceable>TARGET</replaceable>
|
|
||||||
<replaceable>UNIT</replaceable>…</command></term>
|
|
||||||
|
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>Adds <literal>Wants=</literal> or <literal>Requires=</literal>
|
<para>Adds <literal>Wants=</literal> or <literal>Requires=</literal>
|
||||||
@ -1444,10 +1428,7 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
|
|||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term>
|
<term><command>import-environment</command> <replaceable>VARIABLE…</replaceable></term>
|
||||||
<command>import-environment</command>
|
|
||||||
<replaceable>VARIABLE…</replaceable>
|
|
||||||
</term>
|
|
||||||
|
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>Import all, one or more environment variables set on the client into the systemd manager
|
<para>Import all, one or more environment variables set on the client into the systemd manager
|
||||||
|
|||||||
@ -488,7 +488,7 @@
|
|||||||
<filename>*.pcrlock.d/*.pcrlock</filename> files from. May be used more than once to specify multiple
|
<filename>*.pcrlock.d/*.pcrlock</filename> files from. May be used more than once to specify multiple
|
||||||
such directories. If not specified, defaults to <filename>/etc/pcrlock.d/</filename>,
|
such directories. If not specified, defaults to <filename>/etc/pcrlock.d/</filename>,
|
||||||
<filename>/run/pcrlock.d/</filename>, <filename>/var/lib/pcrlock.d/</filename>,
|
<filename>/run/pcrlock.d/</filename>, <filename>/var/lib/pcrlock.d/</filename>,
|
||||||
<filename>/usr/local/pcrlock.d/</filename>, <filename>/usr/lib/pcrlock.d/</filename>.</para>
|
<filename>/usr/local/lib/pcrlock.d/</filename>, <filename>/usr/lib/pcrlock.d/</filename>.</para>
|
||||||
|
|
||||||
<xi:include href="version-info.xml" xpointer="v255"/></listitem>
|
<xi:include href="version-info.xml" xpointer="v255"/></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|||||||
@ -28,8 +28,8 @@
|
|||||||
<member><filename>/run/pcrlock.d/*.pcrlock.d/*.pcrlock</filename></member>
|
<member><filename>/run/pcrlock.d/*.pcrlock.d/*.pcrlock</filename></member>
|
||||||
<member><filename>/var/lib/pcrlock.d/*.pcrlock</filename></member>
|
<member><filename>/var/lib/pcrlock.d/*.pcrlock</filename></member>
|
||||||
<member><filename>/var/lib/pcrlock.d/*.pcrlock.d/*.pcrlock</filename></member>
|
<member><filename>/var/lib/pcrlock.d/*.pcrlock.d/*.pcrlock</filename></member>
|
||||||
<member><filename>/usr/local/pcrlock.d/*.pcrlock</filename></member>
|
<member><filename>/usr/local/lib/pcrlock.d/*.pcrlock</filename></member>
|
||||||
<member><filename>/usr/local/pcrlock.d/*.pcrlock.d/*.pcrlock</filename></member>
|
<member><filename>/usr/local/lib/pcrlock.d/*.pcrlock.d/*.pcrlock</filename></member>
|
||||||
<member><filename>/usr/lib/pcrlock.d/*.pcrlock</filename></member>
|
<member><filename>/usr/lib/pcrlock.d/*.pcrlock</filename></member>
|
||||||
<member><filename>/usr/lib/pcrlock.d/*.pcrlock.d/*.pcrlock</filename></member>
|
<member><filename>/usr/lib/pcrlock.d/*.pcrlock.d/*.pcrlock</filename></member>
|
||||||
</simplelist></para>
|
</simplelist></para>
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
258
|
258.1
|
||||||
|
|||||||
@ -56,7 +56,7 @@ int pidfd_get_namespace(int fd, unsigned long ns_type_cmd) {
|
|||||||
if (have_pidfs == 0 || !cached_supported)
|
if (have_pidfs == 0 || !cached_supported)
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
int nsfd = ioctl(fd, ns_type_cmd);
|
int nsfd = ioctl(fd, ns_type_cmd, 0);
|
||||||
if (nsfd < 0) {
|
if (nsfd < 0) {
|
||||||
/* Kernel returns EOPNOTSUPP if the ns type in question is disabled. Hence we need to look
|
/* Kernel returns EOPNOTSUPP if the ns type in question is disabled. Hence we need to look
|
||||||
* at precise errno instead of generic ERRNO_IS_(IOCTL_)NOT_SUPPORTED. */
|
* at precise errno instead of generic ERRNO_IS_(IOCTL_)NOT_SUPPORTED. */
|
||||||
|
|||||||
@ -732,6 +732,9 @@ static int count_known_files(const BootConfig *config, const char* root, Hashmap
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
r = ref_file(&known_files, e->efi, +1);
|
r = ref_file(&known_files, e->efi, +1);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
r = ref_file(&known_files, e->uki, +1);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
STRV_FOREACH(s, e->initrd) {
|
STRV_FOREACH(s, e->initrd) {
|
||||||
@ -792,6 +795,7 @@ static int unlink_entry(const BootConfig *config, const char *root, const char *
|
|||||||
|
|
||||||
deref_unlink_file(&known_files, e->kernel, e->root);
|
deref_unlink_file(&known_files, e->kernel, e->root);
|
||||||
deref_unlink_file(&known_files, e->efi, e->root);
|
deref_unlink_file(&known_files, e->efi, e->root);
|
||||||
|
deref_unlink_file(&known_files, e->uki, e->root);
|
||||||
STRV_FOREACH(s, e->initrd)
|
STRV_FOREACH(s, e->initrd)
|
||||||
deref_unlink_file(&known_files, *s, e->root);
|
deref_unlink_file(&known_files, *s, e->root);
|
||||||
deref_unlink_file(&known_files, e->device_tree, e->root);
|
deref_unlink_file(&known_files, e->device_tree, e->root);
|
||||||
|
|||||||
@ -547,9 +547,9 @@ int bpf_firewall_compile(Unit *u) {
|
|||||||
if (!cc)
|
if (!cc)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
crt = unit_setup_cgroup_runtime(u);
|
crt = unit_get_cgroup_runtime(u);
|
||||||
if (!crt)
|
if (!crt)
|
||||||
return -ENOMEM;
|
return -ESTALE;
|
||||||
|
|
||||||
if (bpf_program_supported() <= 0)
|
if (bpf_program_supported() <= 0)
|
||||||
return log_unit_debug_errno(u, SYNTHETIC_ERRNO(EOPNOTSUPP),
|
return log_unit_debug_errno(u, SYNTHETIC_ERRNO(EOPNOTSUPP),
|
||||||
|
|||||||
@ -4262,6 +4262,15 @@ int cgroup_runtime_serialize(Unit *u, FILE *f, FDSet *fds) {
|
|||||||
if (!crt)
|
if (!crt)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if (crt->cgroup_path)
|
||||||
|
(void) serialize_item(f, "cgroup", crt->cgroup_path);
|
||||||
|
if (crt->cgroup_id != 0)
|
||||||
|
(void) serialize_item_format(f, "cgroup-id", "%" PRIu64, crt->cgroup_id);
|
||||||
|
|
||||||
|
(void) serialize_cgroup_mask(f, "cgroup-realized-mask", crt->cgroup_realized_mask);
|
||||||
|
(void) serialize_cgroup_mask(f, "cgroup-enabled-mask", crt->cgroup_enabled_mask);
|
||||||
|
(void) serialize_cgroup_mask(f, "cgroup-invalidated-mask", crt->cgroup_invalidated_mask);
|
||||||
|
|
||||||
(void) serialize_item_format(f, "cpu-usage-base", "%" PRIu64, crt->cpu_usage_base);
|
(void) serialize_item_format(f, "cpu-usage-base", "%" PRIu64, crt->cpu_usage_base);
|
||||||
if (crt->cpu_usage_last != NSEC_INFINITY)
|
if (crt->cpu_usage_last != NSEC_INFINITY)
|
||||||
(void) serialize_item_format(f, "cpu-usage-last", "%" PRIu64, crt->cpu_usage_last);
|
(void) serialize_item_format(f, "cpu-usage-last", "%" PRIu64, crt->cpu_usage_last);
|
||||||
@ -4295,15 +4304,6 @@ int cgroup_runtime_serialize(Unit *u, FILE *f, FDSet *fds) {
|
|||||||
(void) serialize_item_format(f, io_accounting_metric_field_last_to_string(im), "%" PRIu64, crt->io_accounting_last[im]);
|
(void) serialize_item_format(f, io_accounting_metric_field_last_to_string(im), "%" PRIu64, crt->io_accounting_last[im]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (crt->cgroup_path)
|
|
||||||
(void) serialize_item(f, "cgroup", crt->cgroup_path);
|
|
||||||
if (crt->cgroup_id != 0)
|
|
||||||
(void) serialize_item_format(f, "cgroup-id", "%" PRIu64, crt->cgroup_id);
|
|
||||||
|
|
||||||
(void) serialize_cgroup_mask(f, "cgroup-realized-mask", crt->cgroup_realized_mask);
|
|
||||||
(void) serialize_cgroup_mask(f, "cgroup-enabled-mask", crt->cgroup_enabled_mask);
|
|
||||||
(void) serialize_cgroup_mask(f, "cgroup-invalidated-mask", crt->cgroup_invalidated_mask);
|
|
||||||
|
|
||||||
(void) bpf_socket_bind_serialize(u, f, fds);
|
(void) bpf_socket_bind_serialize(u, f, fds);
|
||||||
|
|
||||||
(void) bpf_program_serialize_attachment(f, fds, "ip-bpf-ingress-installed", crt->ip_bpf_ingress_installed);
|
(void) bpf_program_serialize_attachment(f, fds, "ip-bpf-ingress-installed", crt->ip_bpf_ingress_installed);
|
||||||
|
|||||||
@ -772,7 +772,7 @@ static void job_emit_done_message(Unit *u, uint32_t job_id, JobType t, JobResult
|
|||||||
/* No message on the console if the job did not actually do anything due to unmet condition. */
|
/* No message on the console if the job did not actually do anything due to unmet condition. */
|
||||||
if (console_only)
|
if (console_only)
|
||||||
return;
|
return;
|
||||||
else
|
|
||||||
do_console = false;
|
do_console = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -136,7 +136,7 @@ static usec_t manager_watch_jobs_next_time(Manager *m) {
|
|||||||
/* Let the user manager without a timeout show status quickly, so the system manager can make
|
/* Let the user manager without a timeout show status quickly, so the system manager can make
|
||||||
* use of it, if it wants to. */
|
* use of it, if it wants to. */
|
||||||
timeout = JOBS_IN_PROGRESS_WAIT_USEC * 2 / 3;
|
timeout = JOBS_IN_PROGRESS_WAIT_USEC * 2 / 3;
|
||||||
else if (show_status_on(m->show_status))
|
else if (manager_get_show_status_on(m))
|
||||||
/* When status is on, just use the usual timeout. */
|
/* When status is on, just use the usual timeout. */
|
||||||
timeout = JOBS_IN_PROGRESS_WAIT_USEC;
|
timeout = JOBS_IN_PROGRESS_WAIT_USEC;
|
||||||
else
|
else
|
||||||
@ -4522,10 +4522,10 @@ static bool manager_should_show_status(Manager *m, StatusType type) {
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* If we cannot find out the status properly, just proceed. */
|
/* If we cannot find out the status properly, just proceed. */
|
||||||
if (type != STATUS_TYPE_EMERGENCY && manager_check_ask_password(m) > 0)
|
if (type < STATUS_TYPE_EMERGENCY && manager_check_ask_password(m) > 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (type == STATUS_TYPE_NOTICE && m->show_status != SHOW_STATUS_NO)
|
if (type >= STATUS_TYPE_NOTICE && manager_get_show_status(m) != SHOW_STATUS_NO)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return manager_get_show_status_on(m);
|
return manager_get_show_status_on(m);
|
||||||
|
|||||||
@ -664,8 +664,6 @@ static int timer_start(Unit *u) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
t->last_trigger = DUAL_TIMESTAMP_NULL;
|
|
||||||
|
|
||||||
/* Reenable all timers that depend on unit activation time */
|
/* Reenable all timers that depend on unit activation time */
|
||||||
LIST_FOREACH(value, v, t->values)
|
LIST_FOREACH(value, v, t->values)
|
||||||
if (v->base == TIMER_ACTIVE)
|
if (v->base == TIMER_ACTIVE)
|
||||||
|
|||||||
@ -1825,7 +1825,15 @@ static bool unit_test_assert(Unit *u) {
|
|||||||
return u->assert_result;
|
return u->assert_result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void unit_status_printf(Unit *u, StatusType status_type, const char *status, const char *format, const char *ident) {
|
void unit_status_printf(
|
||||||
|
Unit *u,
|
||||||
|
StatusType status_type,
|
||||||
|
const char *status,
|
||||||
|
const char *format,
|
||||||
|
const char *ident) {
|
||||||
|
|
||||||
|
assert(u);
|
||||||
|
|
||||||
if (log_get_show_color()) {
|
if (log_get_show_color()) {
|
||||||
if (u->manager->status_unit_format == STATUS_UNIT_FORMAT_COMBINED && strchr(ident, ' '))
|
if (u->manager->status_unit_format == STATUS_UNIT_FORMAT_COMBINED && strchr(ident, ' '))
|
||||||
ident = strjoina(ANSI_HIGHLIGHT, u->id, ANSI_NORMAL, " - ", u->description);
|
ident = strjoina(ANSI_HIGHLIGHT, u->id, ANSI_NORMAL, " - ", u->description);
|
||||||
|
|||||||
@ -52,10 +52,12 @@ typedef enum OOMPolicy {
|
|||||||
} OOMPolicy;
|
} OOMPolicy;
|
||||||
|
|
||||||
typedef enum StatusType {
|
typedef enum StatusType {
|
||||||
STATUS_TYPE_EPHEMERAL,
|
STATUS_TYPE_EPHEMERAL, /* ordered by severity! Do not break order */
|
||||||
STATUS_TYPE_NORMAL,
|
STATUS_TYPE_NORMAL,
|
||||||
STATUS_TYPE_NOTICE,
|
STATUS_TYPE_NOTICE,
|
||||||
STATUS_TYPE_EMERGENCY,
|
STATUS_TYPE_EMERGENCY,
|
||||||
|
_STATUS_TYPE_MAX,
|
||||||
|
_STATUS_TYPE_INVALID = -EINVAL,
|
||||||
} StatusType;
|
} StatusType;
|
||||||
|
|
||||||
static inline bool UNIT_IS_ACTIVE_OR_RELOADING(UnitActiveState t) {
|
static inline bool UNIT_IS_ACTIVE_OR_RELOADING(UnitActiveState t) {
|
||||||
|
|||||||
@ -404,9 +404,11 @@ int machine_load(Machine *m) {
|
|||||||
log_warning_errno(r, "Failed to parse AF_VSOCK CID, ignoring: %s", vsock_cid);
|
log_warning_errno(r, "Failed to parse AF_VSOCK CID, ignoring: %s", vsock_cid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (uid) {
|
||||||
r = parse_uid(uid, &m->uid);
|
r = parse_uid(uid, &m->uid);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
log_warning_errno(r, "Failed to parse owning UID, ignoring: %s", uid);
|
log_warning_errno(r, "Failed to parse owning UID, ignoring: %s", uid);
|
||||||
|
}
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1247,7 +1247,7 @@ static int parse_argv(int argc, char *argv[]) {
|
|||||||
|
|
||||||
arg_userns_ownership = user_namespace_ownership_from_string(optarg);
|
arg_userns_ownership = user_namespace_ownership_from_string(optarg);
|
||||||
if (arg_userns_ownership < 0)
|
if (arg_userns_ownership < 0)
|
||||||
return log_error_errno(arg_userns_ownership, "Cannot parse --user-namespace-ownership= value: %s", optarg);
|
return log_error_errno(arg_userns_ownership, "Cannot parse --private-users-ownership= value: %s", optarg);
|
||||||
|
|
||||||
arg_settings_mask |= SETTING_USERNS;
|
arg_settings_mask |= SETTING_USERNS;
|
||||||
break;
|
break;
|
||||||
|
|||||||
@ -93,6 +93,7 @@ static void boot_entry_free(BootEntry *entry) {
|
|||||||
boot_entry_addons_done(&entry->local_addons);
|
boot_entry_addons_done(&entry->local_addons);
|
||||||
free(entry->kernel);
|
free(entry->kernel);
|
||||||
free(entry->efi);
|
free(entry->efi);
|
||||||
|
free(entry->uki);
|
||||||
strv_free(entry->initrd);
|
strv_free(entry->initrd);
|
||||||
free(entry->device_tree);
|
free(entry->device_tree);
|
||||||
strv_free(entry->device_tree_overlay);
|
strv_free(entry->device_tree_overlay);
|
||||||
@ -403,6 +404,8 @@ static int boot_entry_load_type1(
|
|||||||
r = parse_path_one(tmp.path, line, field, &tmp.kernel, p);
|
r = parse_path_one(tmp.path, line, field, &tmp.kernel, p);
|
||||||
else if (streq(field, "efi"))
|
else if (streq(field, "efi"))
|
||||||
r = parse_path_one(tmp.path, line, field, &tmp.efi, p);
|
r = parse_path_one(tmp.path, line, field, &tmp.efi, p);
|
||||||
|
else if (streq(field, "uki"))
|
||||||
|
r = parse_path_one(tmp.path, line, field, &tmp.uki, p);
|
||||||
else if (streq(field, "initrd"))
|
else if (streq(field, "initrd"))
|
||||||
r = parse_path_strv(tmp.path, line, field, &tmp.initrd, p);
|
r = parse_path_strv(tmp.path, line, field, &tmp.initrd, p);
|
||||||
else if (streq(field, "devicetree"))
|
else if (streq(field, "devicetree"))
|
||||||
@ -511,7 +514,8 @@ int boot_loader_read_conf(BootConfig *config, FILE *file, const char *path) {
|
|||||||
r = free_and_strdup(&config->default_pattern, p);
|
r = free_and_strdup(&config->default_pattern, p);
|
||||||
else if (STR_IN_SET(field, "timeout", "editor", "auto-entries", "auto-firmware",
|
else if (STR_IN_SET(field, "timeout", "editor", "auto-entries", "auto-firmware",
|
||||||
"auto-poweroff", "auto-reboot", "beep", "reboot-for-bitlocker",
|
"auto-poweroff", "auto-reboot", "beep", "reboot-for-bitlocker",
|
||||||
"secure-boot-enroll", "console-mode"))
|
"reboot-on-error", "secure-boot-enroll", "secure-boot-enroll-action",
|
||||||
|
"console-mode"))
|
||||||
r = 0; /* we don't parse these in userspace, but they are OK */
|
r = 0; /* we don't parse these in userspace, but they are OK */
|
||||||
else {
|
else {
|
||||||
log_syntax(NULL, LOG_WARNING, path, line, 0, "Unknown line '%s', ignoring.", field);
|
log_syntax(NULL, LOG_WARNING, path, line, 0, "Unknown line '%s', ignoring.", field);
|
||||||
@ -1896,6 +1900,8 @@ int show_boot_entry(
|
|||||||
boot_entry_file_list("linux", e->root, e->kernel, &status);
|
boot_entry_file_list("linux", e->root, e->kernel, &status);
|
||||||
if (e->efi)
|
if (e->efi)
|
||||||
boot_entry_file_list("efi", e->root, e->efi, &status);
|
boot_entry_file_list("efi", e->root, e->efi, &status);
|
||||||
|
if (e->uki)
|
||||||
|
boot_entry_file_list("uki", e->root, e->uki, &status);
|
||||||
|
|
||||||
STRV_FOREACH(s, e->initrd)
|
STRV_FOREACH(s, e->initrd)
|
||||||
boot_entry_file_list(s == e->initrd ? "initrd" : NULL,
|
boot_entry_file_list(s == e->initrd ? "initrd" : NULL,
|
||||||
@ -1957,9 +1963,8 @@ int boot_entry_to_json(const BootConfig *c, size_t i, sd_json_variant **ret) {
|
|||||||
SD_JSON_BUILD_PAIR_CONDITION(!!opts, "options", SD_JSON_BUILD_STRING(opts)),
|
SD_JSON_BUILD_PAIR_CONDITION(!!opts, "options", SD_JSON_BUILD_STRING(opts)),
|
||||||
SD_JSON_BUILD_PAIR_CONDITION(!!e->kernel, "linux", SD_JSON_BUILD_STRING(e->kernel)),
|
SD_JSON_BUILD_PAIR_CONDITION(!!e->kernel, "linux", SD_JSON_BUILD_STRING(e->kernel)),
|
||||||
SD_JSON_BUILD_PAIR_CONDITION(!!e->efi, "efi", SD_JSON_BUILD_STRING(e->efi)),
|
SD_JSON_BUILD_PAIR_CONDITION(!!e->efi, "efi", SD_JSON_BUILD_STRING(e->efi)),
|
||||||
SD_JSON_BUILD_PAIR_CONDITION(!strv_isempty(e->initrd), "initrd", SD_JSON_BUILD_STRV(e->initrd)),
|
SD_JSON_BUILD_PAIR_CONDITION(!!e->uki, "uki", SD_JSON_BUILD_STRING(e->uki)),
|
||||||
SD_JSON_BUILD_PAIR_CONDITION(!!e->device_tree, "devicetree", SD_JSON_BUILD_STRING(e->device_tree)),
|
SD_JSON_BUILD_PAIR_CONDITION(!strv_isempty(e->initrd), "initrd", SD_JSON_BUILD_STRV(e->initrd)));
|
||||||
SD_JSON_BUILD_PAIR_CONDITION(!strv_isempty(e->device_tree_overlay), "devicetreeOverlay", SD_JSON_BUILD_STRV(e->device_tree_overlay)));
|
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_oom();
|
return log_oom();
|
||||||
|
|
||||||
@ -1968,6 +1973,8 @@ int boot_entry_to_json(const BootConfig *c, size_t i, sd_json_variant **ret) {
|
|||||||
* at once. */
|
* at once. */
|
||||||
r = sd_json_variant_merge_objectbo(
|
r = sd_json_variant_merge_objectbo(
|
||||||
&v,
|
&v,
|
||||||
|
SD_JSON_BUILD_PAIR_CONDITION(!!e->device_tree, "devicetree", SD_JSON_BUILD_STRING(e->device_tree)),
|
||||||
|
SD_JSON_BUILD_PAIR_CONDITION(!strv_isempty(e->device_tree_overlay), "devicetreeOverlay", SD_JSON_BUILD_STRV(e->device_tree_overlay)),
|
||||||
SD_JSON_BUILD_PAIR("isReported", SD_JSON_BUILD_BOOLEAN(e->reported_by_loader)),
|
SD_JSON_BUILD_PAIR("isReported", SD_JSON_BUILD_BOOLEAN(e->reported_by_loader)),
|
||||||
SD_JSON_BUILD_PAIR_CONDITION(e->tries_left != UINT_MAX, "triesLeft", SD_JSON_BUILD_UNSIGNED(e->tries_left)),
|
SD_JSON_BUILD_PAIR_CONDITION(e->tries_left != UINT_MAX, "triesLeft", SD_JSON_BUILD_UNSIGNED(e->tries_left)),
|
||||||
SD_JSON_BUILD_PAIR_CONDITION(e->tries_done != UINT_MAX, "triesDone", SD_JSON_BUILD_UNSIGNED(e->tries_done)),
|
SD_JSON_BUILD_PAIR_CONDITION(e->tries_done != UINT_MAX, "triesDone", SD_JSON_BUILD_UNSIGNED(e->tries_done)),
|
||||||
|
|||||||
@ -50,6 +50,7 @@ typedef struct BootEntry {
|
|||||||
const BootEntryAddons *global_addons; /* Backpointer into the BootConfig; we don't own this here */
|
const BootEntryAddons *global_addons; /* Backpointer into the BootConfig; we don't own this here */
|
||||||
char *kernel; /* linux is #defined to 1, yikes! */
|
char *kernel; /* linux is #defined to 1, yikes! */
|
||||||
char *efi;
|
char *efi;
|
||||||
|
char *uki;
|
||||||
char **initrd;
|
char **initrd;
|
||||||
char *device_tree;
|
char *device_tree;
|
||||||
char **device_tree_overlay;
|
char **device_tree_overlay;
|
||||||
|
|||||||
@ -47,6 +47,7 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE(
|
|||||||
SD_VARLINK_DEFINE_FIELD(options, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
|
SD_VARLINK_DEFINE_FIELD(options, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
|
||||||
SD_VARLINK_DEFINE_FIELD(linux, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
|
SD_VARLINK_DEFINE_FIELD(linux, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
|
||||||
SD_VARLINK_DEFINE_FIELD(efi, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
|
SD_VARLINK_DEFINE_FIELD(efi, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
|
||||||
|
SD_VARLINK_DEFINE_FIELD(uki, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
|
||||||
SD_VARLINK_DEFINE_FIELD(initrd, SD_VARLINK_STRING, SD_VARLINK_NULLABLE|SD_VARLINK_ARRAY),
|
SD_VARLINK_DEFINE_FIELD(initrd, SD_VARLINK_STRING, SD_VARLINK_NULLABLE|SD_VARLINK_ARRAY),
|
||||||
SD_VARLINK_DEFINE_FIELD(devicetree, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
|
SD_VARLINK_DEFINE_FIELD(devicetree, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
|
||||||
SD_VARLINK_DEFINE_FIELD(devicetreeOverlay, SD_VARLINK_STRING, SD_VARLINK_NULLABLE|SD_VARLINK_ARRAY),
|
SD_VARLINK_DEFINE_FIELD(devicetreeOverlay, SD_VARLINK_STRING, SD_VARLINK_NULLABLE|SD_VARLINK_ARRAY),
|
||||||
|
|||||||
@ -1830,10 +1830,7 @@ static int merge_subprocess(
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
r = dissected_image_decrypt_interactively(
|
r = dissected_image_decrypt(m, /* passphrase= */ NULL, &verity_settings, flags);
|
||||||
m, NULL,
|
|
||||||
&verity_settings,
|
|
||||||
flags);
|
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
|||||||
@ -132,7 +132,7 @@ _sd_const_ static __inline__ int sd_id128_is_allf(sd_id128_t a) {
|
|||||||
#define SD_ID128_NULL ((const sd_id128_t) { .qwords = { 0, 0 }})
|
#define SD_ID128_NULL ((const sd_id128_t) { .qwords = { 0, 0 }})
|
||||||
#define SD_ID128_ALLF ((const sd_id128_t) { .qwords = { UINT64_C(0xFFFFFFFFFFFFFFFF), UINT64_C(0xFFFFFFFFFFFFFFFF) }})
|
#define SD_ID128_ALLF ((const sd_id128_t) { .qwords = { UINT64_C(0xFFFFFFFFFFFFFFFF), UINT64_C(0xFFFFFFFFFFFFFFFF) }})
|
||||||
|
|
||||||
_sd_const_ static __inline__ int sd_id128_in_setv(sd_id128_t a, va_list ap) {
|
static __inline__ int sd_id128_in_setv(sd_id128_t a, va_list ap) {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
sd_id128_t b = va_arg(ap, sd_id128_t);
|
sd_id128_t b = va_arg(ap, sd_id128_t);
|
||||||
|
|
||||||
|
|||||||
@ -50,7 +50,8 @@ int main(int argc, char *argv[]) {
|
|||||||
if (!can_memlock())
|
if (!can_memlock())
|
||||||
return log_tests_skipped("Can't use mlock()");
|
return log_tests_skipped("Can't use mlock()");
|
||||||
|
|
||||||
r = enter_cgroup_subroot(NULL);
|
_cleanup_free_ char *cgroup_path = NULL;
|
||||||
|
r = enter_cgroup_subroot(&cgroup_path);
|
||||||
if (r == -ENOMEDIUM)
|
if (r == -ENOMEDIUM)
|
||||||
return log_tests_skipped("cgroupfs not available");
|
return log_tests_skipped("cgroupfs not available");
|
||||||
|
|
||||||
@ -129,6 +130,8 @@ int main(int argc, char *argv[]) {
|
|||||||
SERVICE(u)->type = SERVICE_ONESHOT;
|
SERVICE(u)->type = SERVICE_ONESHOT;
|
||||||
u->load_state = UNIT_LOADED;
|
u->load_state = UNIT_LOADED;
|
||||||
|
|
||||||
|
CGroupRuntime *crt = ASSERT_PTR(unit_setup_cgroup_runtime(u));
|
||||||
|
|
||||||
unit_dump(u, stdout, NULL);
|
unit_dump(u, stdout, NULL);
|
||||||
|
|
||||||
r = bpf_firewall_compile(u);
|
r = bpf_firewall_compile(u);
|
||||||
@ -136,7 +139,6 @@ int main(int argc, char *argv[]) {
|
|||||||
return log_tests_skipped("Kernel doesn't support the necessary bpf bits (masked out via seccomp?)");
|
return log_tests_skipped("Kernel doesn't support the necessary bpf bits (masked out via seccomp?)");
|
||||||
ASSERT_OK(r);
|
ASSERT_OK(r);
|
||||||
|
|
||||||
CGroupRuntime *crt = ASSERT_PTR(unit_get_cgroup_runtime(u));
|
|
||||||
ASSERT_NOT_NULL(crt->ip_bpf_ingress);
|
ASSERT_NOT_NULL(crt->ip_bpf_ingress);
|
||||||
ASSERT_NOT_NULL(crt->ip_bpf_egress);
|
ASSERT_NOT_NULL(crt->ip_bpf_egress);
|
||||||
|
|
||||||
|
|||||||
@ -151,6 +151,7 @@ udev_binaries_dict = [
|
|||||||
include_directories('.', 'net'),
|
include_directories('.', 'net'),
|
||||||
],
|
],
|
||||||
'dependencies' : udev_dependencies,
|
'dependencies' : udev_dependencies,
|
||||||
|
'link_with' : udev_link_with,
|
||||||
'install_rpath' : udev_rpath,
|
'install_rpath' : udev_rpath,
|
||||||
'install_tag' : 'udev',
|
'install_tag' : 'udev',
|
||||||
'extract' : udevadm_extract_sources,
|
'extract' : udevadm_extract_sources,
|
||||||
|
|||||||
@ -70,7 +70,7 @@ foreach dirname : [
|
|||||||
'TEST-46-HOMED',
|
'TEST-46-HOMED',
|
||||||
'TEST-50-DISSECT',
|
'TEST-50-DISSECT',
|
||||||
'TEST-52-HONORFIRSTSHUTDOWN',
|
'TEST-52-HONORFIRSTSHUTDOWN',
|
||||||
'TEST-53-ISSUE-16347',
|
'TEST-53-TIMER',
|
||||||
'TEST-54-CREDS',
|
'TEST-54-CREDS',
|
||||||
'TEST-55-OOMD',
|
'TEST-55-OOMD',
|
||||||
'TEST-58-REPART',
|
'TEST-58-REPART',
|
||||||
|
|||||||
97
test/units/TEST-53-TIMER.RandomizedDelaySec-reload.sh
Executable file
97
test/units/TEST-53-TIMER.RandomizedDelaySec-reload.sh
Executable file
@ -0,0 +1,97 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
|
#
|
||||||
|
# When deserializing a serialized timer unit with RandomizedDelaySec= set, systemd should use the last
|
||||||
|
# inactive exit timestamp instead of current realtime to calculate the new next elapse, so the timer unit
|
||||||
|
# actually runs in the given calendar window.
|
||||||
|
#
|
||||||
|
# Provides coverage for:
|
||||||
|
# - https://github.com/systemd/systemd/issues/18678
|
||||||
|
# - https://github.com/systemd/systemd/pull/27752
|
||||||
|
set -eux
|
||||||
|
set -o pipefail
|
||||||
|
|
||||||
|
# shellcheck source=test/units/test-control.sh
|
||||||
|
. "$(dirname "$0")"/util.sh
|
||||||
|
|
||||||
|
UNIT_NAME="timer-RandomizedDelaySec-$RANDOM"
|
||||||
|
TARGET_TS="$(date --date="tomorrow 00:10")"
|
||||||
|
TARGET_TS_S="$(date --date="$TARGET_TS" "+%s")"
|
||||||
|
# Maximum possible next elapse timestamp: $TARGET_TS (OnCalendar=) + 22 hours (RandomizedDelaySec=)
|
||||||
|
MAX_NEXT_ELAPSE_REALTIME_S="$((TARGET_TS_S + 22 * 60 * 60))"
|
||||||
|
MAX_NEXT_ELAPSE_REALTIME="$(date --date="@$MAX_NEXT_ELAPSE_REALTIME_S")"
|
||||||
|
|
||||||
|
# Let's make sure to return the date & time back to the original state once we're done with our time
|
||||||
|
# shenigans. One way to do this would be to use hwclock, but the RTC in VMs can be unreliable or slow to
|
||||||
|
# respond, causing unexpected test fails/timeouts.
|
||||||
|
#
|
||||||
|
# Instead, let's save the realtime timestamp before we start with the test together with a current monotonic
|
||||||
|
# timestamp, after the test ends take the difference between the current monotonic timestamp and the "start"
|
||||||
|
# one, add it to the originally saved realtime timestamp, and finally use that timestamp to set the system
|
||||||
|
# time. This should advance the system time by the amount of time the test actually ran, and hence restore it
|
||||||
|
# to some sane state after the time jumps performed by the test. It won't be perfect, but it should be close
|
||||||
|
# enough for our needs.
|
||||||
|
START_REALTIME="$(date "+%s")"
|
||||||
|
START_MONOTONIC="$(cut -d . -f 1 /proc/uptime)"
|
||||||
|
at_exit() {
|
||||||
|
: "Restore the system date to a sane state"
|
||||||
|
END_MONOTONIC="$(cut -d . -f 1 /proc/uptime)"
|
||||||
|
date --set="@$((START_REALTIME + END_MONOTONIC - START_MONOTONIC))"
|
||||||
|
}
|
||||||
|
trap at_exit EXIT
|
||||||
|
|
||||||
|
# Set some predictable time so we can schedule the first timer elapse in a deterministic-ish way
|
||||||
|
date --set="23:00"
|
||||||
|
|
||||||
|
# Setup
|
||||||
|
cat >"/run/systemd/system/$UNIT_NAME.timer" <<EOF
|
||||||
|
[Timer]
|
||||||
|
# Run this timer daily, ten minutes after midnight
|
||||||
|
OnCalendar=*-*-* 00:10:00
|
||||||
|
RandomizedDelaySec=22h
|
||||||
|
AccuracySec=1ms
|
||||||
|
EOF
|
||||||
|
|
||||||
|
cat >"/run/systemd/system/$UNIT_NAME.service" <<EOF
|
||||||
|
[Service]
|
||||||
|
ExecStart=echo "Hello world"
|
||||||
|
EOF
|
||||||
|
|
||||||
|
systemctl daemon-reload
|
||||||
|
|
||||||
|
check_elapse_timestamp() {
|
||||||
|
systemctl status "$UNIT_NAME.timer"
|
||||||
|
systemctl show -p InactiveExitTimestamp "$UNIT_NAME.timer"
|
||||||
|
|
||||||
|
NEXT_ELAPSE_REALTIME="$(systemctl show -P NextElapseUSecRealtime "$UNIT_NAME.timer")"
|
||||||
|
NEXT_ELAPSE_REALTIME_S="$(date --date="$NEXT_ELAPSE_REALTIME" "+%s")"
|
||||||
|
: "Next elapse timestamp should be $TARGET_TS <= $NEXT_ELAPSE_REALTIME <= $MAX_NEXT_ELAPSE_REALTIME"
|
||||||
|
assert_ge "$NEXT_ELAPSE_REALTIME_S" "$TARGET_TS_S"
|
||||||
|
assert_le "$NEXT_ELAPSE_REALTIME_S" "$MAX_NEXT_ELAPSE_REALTIME_S"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Restart the timer unit and check the initial next elapse timestamp
|
||||||
|
: "Initial next elapse timestamp"
|
||||||
|
systemctl restart "$UNIT_NAME.timer"
|
||||||
|
check_elapse_timestamp
|
||||||
|
|
||||||
|
# Bump the system date to 1 minute after the original calendar timer would've expired (without any random
|
||||||
|
# delay!) - systemd should recalculate the next elapse timestamp with a new randomized delay, but it should
|
||||||
|
# use the original inactive exit timestamp as a "base", so the final timestamp should not end up beyond the
|
||||||
|
# original calendar timestamp + randomized delay range.
|
||||||
|
#
|
||||||
|
# Similarly, do the same check after doing daemon-reload, as that also forces systemd to recalculate the next
|
||||||
|
# elapse timestamp (this goes through a slightly different codepath that actually contained the original
|
||||||
|
# issue).
|
||||||
|
: "Next elapse timestamp after time jump"
|
||||||
|
date -s "tomorrow 00:11"
|
||||||
|
check_elapse_timestamp
|
||||||
|
|
||||||
|
: "Next elapse timestamp after daemon-reload"
|
||||||
|
systemctl daemon-reload
|
||||||
|
check_elapse_timestamp
|
||||||
|
|
||||||
|
# Cleanup
|
||||||
|
systemctl stop "$UNIT_NAME".{timer,service}
|
||||||
|
rm -f "/run/systemd/system/$UNIT_NAME".{timer,service}
|
||||||
|
systemctl daemon-reload
|
||||||
@ -3,10 +3,9 @@
|
|||||||
set -eux
|
set -eux
|
||||||
set -o pipefail
|
set -o pipefail
|
||||||
|
|
||||||
: >/failed
|
|
||||||
|
|
||||||
# Reset host date to current time, 3 days in the past.
|
# Reset host date to current time, 3 days in the past.
|
||||||
date -s "-3 days"
|
date -s "-3 days"
|
||||||
|
trap 'date -s "+3 days"' EXIT
|
||||||
|
|
||||||
# Run a timer for every 15 minutes.
|
# Run a timer for every 15 minutes.
|
||||||
systemd-run --unit test-timer --on-calendar "*:0/15:0" true
|
systemd-run --unit test-timer --on-calendar "*:0/15:0" true
|
||||||
@ -17,15 +16,12 @@ now=$(date +%s)
|
|||||||
time_delta=$((next_elapsed - now))
|
time_delta=$((next_elapsed - now))
|
||||||
|
|
||||||
# Check that the timer will elapse in less than 20 minutes.
|
# Check that the timer will elapse in less than 20 minutes.
|
||||||
((0 < time_delta && time_delta < 1200)) || {
|
if [[ "$time_delta" -lt 0 || "$time_delta" -gt 1200 ]]; then
|
||||||
echo 'Timer elapse outside of the expected 20 minute window.'
|
echo 'Timer elapse outside of the expected 20 minute window.'
|
||||||
echo " next_elapsed=${next_elapsed}"
|
echo " next_elapsed=${next_elapsed}"
|
||||||
echo " now=${now}"
|
echo " now=${now}"
|
||||||
echo " time_delta=${time_delta}"
|
echo " time_delta=${time_delta}"
|
||||||
echo ''
|
echo
|
||||||
} >>/failed
|
|
||||||
|
|
||||||
if test ! -s /failed ; then
|
exit 1
|
||||||
rm -f /failed
|
|
||||||
touch /testok
|
|
||||||
fi
|
fi
|
||||||
77
test/units/TEST-53-TIMER.restart-trigger.sh
Executable file
77
test/units/TEST-53-TIMER.restart-trigger.sh
Executable file
@ -0,0 +1,77 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
|
#
|
||||||
|
# Restarting an already elapsed timer shouldn't immediately trigger the corresponding service unit.
|
||||||
|
#
|
||||||
|
# Provides coverage for:
|
||||||
|
# - https://github.com/systemd/systemd/issues/31231
|
||||||
|
# - https://github.com/systemd/systemd/issues/35805
|
||||||
|
set -eux
|
||||||
|
set -o pipefail
|
||||||
|
|
||||||
|
# shellcheck source=test/units/test-control.sh
|
||||||
|
. "$(dirname "$0")"/util.sh
|
||||||
|
|
||||||
|
UNIT_NAME="timer-restart-$RANDOM"
|
||||||
|
TEST_MESSAGE="Hello from timer $RANDOM"
|
||||||
|
|
||||||
|
# Setup
|
||||||
|
cat >"/run/systemd/system/$UNIT_NAME.timer" <<EOF
|
||||||
|
[Timer]
|
||||||
|
OnCalendar=$(date --date="+1 hour" "+%Y-%m-%d %H:%M:%S")
|
||||||
|
AccuracySec=1s
|
||||||
|
EOF
|
||||||
|
|
||||||
|
cat >"/run/systemd/system/$UNIT_NAME.service" <<EOF
|
||||||
|
[Service]
|
||||||
|
ExecStart=echo "$TEST_MESSAGE"
|
||||||
|
EOF
|
||||||
|
|
||||||
|
systemctl daemon-reload
|
||||||
|
|
||||||
|
JOURNAL_TS="$(date "+%s")"
|
||||||
|
# Paranoia check that the test message is not already in the logs
|
||||||
|
(! journalctl -p info --since="@$JOURNAL_TS" --unit="$UNIT_NAME" --grep="$TEST_MESSAGE")
|
||||||
|
|
||||||
|
# Restart time timer and move time forward by 2 hours to trigger the timer
|
||||||
|
systemctl restart "$UNIT_NAME.timer"
|
||||||
|
systemctl status "$UNIT_NAME.timer"
|
||||||
|
|
||||||
|
date -s '+2 hours'
|
||||||
|
trap 'date -s "-2 hours"' EXIT
|
||||||
|
sleep 1
|
||||||
|
systemctl status "$UNIT_NAME.timer"
|
||||||
|
assert_eq "$(journalctl -q -p info --since="@$JOURNAL_TS" --unit="$UNIT_NAME" --grep="$TEST_MESSAGE" | wc -l)" "1"
|
||||||
|
|
||||||
|
# Restarting the timer unit shouldn't trigger neither the timer nor the service, so these
|
||||||
|
# fields should remain constant through the following tests
|
||||||
|
SERVICE_INV_ID="$(systemctl show --property=InvocationID "$UNIT_NAME.service")"
|
||||||
|
TIMER_LAST_TRIGGER="$(systemctl show --property=LastTriggerUSec "$UNIT_NAME.timer")"
|
||||||
|
|
||||||
|
# Now restart the timer and check if the timer and the service weren't triggered again
|
||||||
|
systemctl restart "$UNIT_NAME.timer"
|
||||||
|
sleep 5
|
||||||
|
assert_eq "$(journalctl -q -p info --since="@$JOURNAL_TS" --unit="$UNIT_NAME" --grep="$TEST_MESSAGE" | wc -l)" "1"
|
||||||
|
assert_eq "$SERVICE_INV_ID" "$(systemctl show --property=InvocationID "$UNIT_NAME.service")"
|
||||||
|
assert_eq "$TIMER_LAST_TRIGGER" "$(systemctl show --property=LastTriggerUSec "$UNIT_NAME.timer")"
|
||||||
|
|
||||||
|
# Set the timer into the past, restart it, and again check if it wasn't triggered
|
||||||
|
TIMER_TS="$(date --date="-1 day" "+%Y-%m-%d %H:%M:%S")"
|
||||||
|
mkdir "/run/systemd/system/$UNIT_NAME.timer.d/"
|
||||||
|
cat >"/run/systemd/system/$UNIT_NAME.timer.d/99-override.conf" <<EOF
|
||||||
|
[Timer]
|
||||||
|
OnCalendar=$TIMER_TS
|
||||||
|
EOF
|
||||||
|
systemctl daemon-reload
|
||||||
|
systemctl status "$UNIT_NAME.timer"
|
||||||
|
assert_in "OnCalendar=$TIMER_TS" "$(systemctl show -P TimersCalendar "$UNIT_NAME".timer)"
|
||||||
|
systemctl restart "$UNIT_NAME.timer"
|
||||||
|
sleep 5
|
||||||
|
assert_eq "$(journalctl -q -p info --since="@$JOURNAL_TS" --unit="$UNIT_NAME" --grep="$TEST_MESSAGE" | wc -l)" "1"
|
||||||
|
assert_eq "$SERVICE_INV_ID" "$(systemctl show --property=InvocationID "$UNIT_NAME.service")"
|
||||||
|
assert_eq "$TIMER_LAST_TRIGGER" "$(systemctl show --property=LastTriggerUSec "$UNIT_NAME.timer")"
|
||||||
|
|
||||||
|
# Cleanup
|
||||||
|
systemctl stop "$UNIT_NAME".{timer,service}
|
||||||
|
rm -f "/run/systemd/system/$UNIT_NAME".{timer,service}
|
||||||
|
systemctl daemon-reload
|
||||||
11
test/units/TEST-53-TIMER.sh
Executable file
11
test/units/TEST-53-TIMER.sh
Executable file
@ -0,0 +1,11 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
|
set -eux
|
||||||
|
set -o pipefail
|
||||||
|
|
||||||
|
# shellcheck source=test/units/test-control.sh
|
||||||
|
. "$(dirname "$0")"/test-control.sh
|
||||||
|
|
||||||
|
run_subtests
|
||||||
|
|
||||||
|
touch /testok
|
||||||
@ -57,6 +57,15 @@ assert_le() {(
|
|||||||
fi
|
fi
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
assert_ge() {(
|
||||||
|
set +ex
|
||||||
|
|
||||||
|
if [[ "${1:?}" -lt "${2:?}" ]]; then
|
||||||
|
echo "FAIL: '$1' < '$2'" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
)}
|
||||||
|
|
||||||
assert_in() {(
|
assert_in() {(
|
||||||
set +ex
|
set +ex
|
||||||
|
|
||||||
|
|||||||
@ -18,7 +18,7 @@ Before=sysinit.target shutdown.target
|
|||||||
DefaultDependencies=no
|
DefaultDependencies=no
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
#CapabilityBoundingSet=CAP_DAC_READ_SEARCH CAP_SYS_RESOURCE CAP_BPF CAP_PERFMON CAP_SETGID CAP_SETUID
|
CapabilityBoundingSet=CAP_DAC_READ_SEARCH CAP_SYS_RESOURCE CAP_BPF CAP_PERFMON CAP_SETGID CAP_SETUID CAP_DAC_OVERRIDE CAP_CHOWN CAP_SYS_ADMIN
|
||||||
ExecStart={{LIBEXECDIR}}/systemd-mountfsd
|
ExecStart={{LIBEXECDIR}}/systemd-mountfsd
|
||||||
IPAddressDeny=any
|
IPAddressDeny=any
|
||||||
LimitNOFILE={{HIGH_RLIMIT_NOFILE}}
|
LimitNOFILE={{HIGH_RLIMIT_NOFILE}}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user