mirror of
https://github.com/systemd/systemd
synced 2025-12-29 12:24:45 +01:00
Compare commits
6 Commits
e2ebc406ac
...
f1c86dd9ab
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f1c86dd9ab | ||
|
|
8d7dab1fda | ||
|
|
b562b9c68c | ||
|
|
3b9b916968 | ||
|
|
1f22621ba3 | ||
|
|
96cceb35e7 |
@ -52,9 +52,13 @@ All tools:
|
|||||||
* `$SYSTEMD_EFI_OPTIONS` — if set, used instead of the string in the
|
* `$SYSTEMD_EFI_OPTIONS` — if set, used instead of the string in the
|
||||||
SystemdOptions EFI variable. Analogous to `$SYSTEMD_PROC_CMDLINE`.
|
SystemdOptions EFI variable. Analogous to `$SYSTEMD_PROC_CMDLINE`.
|
||||||
|
|
||||||
* `$SYSTEMD_IN_INITRD` — takes a boolean. If set, overrides initrd detection.
|
* `$SYSTEMD_IN_INITRD=[auto|lenient|0|1]` — if set, specifies initrd detection
|
||||||
This is useful for debugging and testing initrd-only programs in the main
|
method. Defaults to `auto`. Behavior is defined as follows:
|
||||||
system.
|
`auto`: Checks if `/etc/initrd-release` exists, and a temporary fs is mounted
|
||||||
|
on `/`. If both conditions meet, then it's in initrd.
|
||||||
|
`lenient`: Similiar to `auto`, but the rootfs check is skipped.
|
||||||
|
`0|1`: Simply overrides initrd detection. This is useful for debugging and
|
||||||
|
testing initrd-only programs in the main system.
|
||||||
|
|
||||||
* `$SYSTEMD_BUS_TIMEOUT=SECS` — specifies the maximum time to wait for method call
|
* `$SYSTEMD_BUS_TIMEOUT=SECS` — specifies the maximum time to wait for method call
|
||||||
completion. If no time unit is specified, assumes seconds. The usual other units
|
completion. If no time unit is specified, assumes seconds. The usual other units
|
||||||
|
|||||||
@ -2383,8 +2383,8 @@ SystemCallErrorNumber=EPERM</programlisting>
|
|||||||
to. Takes one of <option>inherit</option>, <option>null</option>, <option>tty</option>,
|
to. Takes one of <option>inherit</option>, <option>null</option>, <option>tty</option>,
|
||||||
<option>journal</option>, <option>kmsg</option>, <option>journal+console</option>,
|
<option>journal</option>, <option>kmsg</option>, <option>journal+console</option>,
|
||||||
<option>kmsg+console</option>, <option>file:<replaceable>path</replaceable></option>,
|
<option>kmsg+console</option>, <option>file:<replaceable>path</replaceable></option>,
|
||||||
<option>append:<replaceable>path</replaceable></option>, <option>socket</option> or
|
<option>append:<replaceable>path</replaceable></option>, <option>truncate:<replaceable>path</replaceable></option>,
|
||||||
<option>fd:<replaceable>name</replaceable></option>.</para>
|
<option>socket</option> or <option>fd:<replaceable>name</replaceable></option>.</para>
|
||||||
|
|
||||||
<para><option>inherit</option> duplicates the file descriptor of standard input for standard output.</para>
|
<para><option>inherit</option> duplicates the file descriptor of standard input for standard output.</para>
|
||||||
|
|
||||||
@ -2424,6 +2424,10 @@ SystemCallErrorNumber=EPERM</programlisting>
|
|||||||
<option>file:<replaceable>path</replaceable></option> above, but it opens the file in append mode.
|
<option>file:<replaceable>path</replaceable></option> above, but it opens the file in append mode.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
<para><option>truncate:<replaceable>path</replaceable></option> is similar to
|
||||||
|
<option>file:<replaceable>path</replaceable></option> above, but it truncates the file when opening it.
|
||||||
|
</para>
|
||||||
|
|
||||||
<para><option>socket</option> connects standard output to a socket acquired via socket activation. The
|
<para><option>socket</option> connects standard output to a socket acquired via socket activation. The
|
||||||
semantics are similar to the same option of <varname>StandardInput=</varname>, see above.</para>
|
semantics are similar to the same option of <varname>StandardInput=</varname>, see above.</para>
|
||||||
|
|
||||||
|
|||||||
@ -52,13 +52,14 @@ int prot_from_flags(int flags) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool in_initrd(void) {
|
bool in_initrd(void) {
|
||||||
struct statfs s;
|
|
||||||
int r;
|
int r;
|
||||||
|
const char *e;
|
||||||
|
bool lenient = false;
|
||||||
|
|
||||||
if (saved_in_initrd >= 0)
|
if (saved_in_initrd >= 0)
|
||||||
return saved_in_initrd;
|
return saved_in_initrd;
|
||||||
|
|
||||||
/* We make two checks here:
|
/* We have two checks here:
|
||||||
*
|
*
|
||||||
* 1. the flag file /etc/initrd-release must exist
|
* 1. the flag file /etc/initrd-release must exist
|
||||||
* 2. the root file system must be a memory file system
|
* 2. the root file system must be a memory file system
|
||||||
@ -66,18 +67,46 @@ bool in_initrd(void) {
|
|||||||
* The second check is extra paranoia, since misdetecting an
|
* The second check is extra paranoia, since misdetecting an
|
||||||
* initrd can have bad consequences due the initrd
|
* initrd can have bad consequences due the initrd
|
||||||
* emptying when transititioning to the main systemd.
|
* emptying when transititioning to the main systemd.
|
||||||
|
*
|
||||||
|
* If env var $SYSTEMD_IN_INITRD is not set or set to "auto",
|
||||||
|
* both checks are used. If it's set to "lenient", only check
|
||||||
|
* 1 is used. If set to a booleen value, then the boolean
|
||||||
|
* value is returned.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
r = getenv_bool_secure("SYSTEMD_IN_INITRD");
|
e = secure_getenv("SYSTEMD_IN_INITRD");
|
||||||
if (r < 0 && r != -ENXIO)
|
if (e) {
|
||||||
log_debug_errno(r, "Failed to parse $SYSTEMD_IN_INITRD, ignoring: %m");
|
if (streq(e, "lenient"))
|
||||||
|
lenient = true;
|
||||||
|
else if (!streq(e, "auto")) {
|
||||||
|
r = parse_boolean(e);
|
||||||
|
if (r >= 0) {
|
||||||
|
saved_in_initrd = r > 0;
|
||||||
|
return saved_in_initrd;
|
||||||
|
}
|
||||||
|
log_debug_errno(r, "Failed to parse $SYSTEMD_IN_INITRD, ignoring: %m");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!lenient) {
|
||||||
|
r = path_is_temporary_fs("/");
|
||||||
|
if (r < 0)
|
||||||
|
log_debug_errno(r, "Couldn't determine if / is a temporary file system: %m");
|
||||||
|
|
||||||
if (r >= 0)
|
|
||||||
saved_in_initrd = r > 0;
|
saved_in_initrd = r > 0;
|
||||||
else
|
}
|
||||||
saved_in_initrd = access("/etc/initrd-release", F_OK) >= 0 &&
|
|
||||||
statfs("/", &s) >= 0 &&
|
r = access("/etc/initrd-release", F_OK);
|
||||||
is_temporary_fs(&s);
|
if (r >= 0) {
|
||||||
|
if (saved_in_initrd == 0)
|
||||||
|
log_debug("/etc/initrd-release exists, but it's not an initrd.");
|
||||||
|
else
|
||||||
|
saved_in_initrd = 1;
|
||||||
|
} else {
|
||||||
|
if (errno != ENOENT)
|
||||||
|
log_debug_errno(errno, "Failed to test if /etc/initrd-release exists: %m");
|
||||||
|
saved_in_initrd = 0;
|
||||||
|
}
|
||||||
|
|
||||||
return saved_in_initrd;
|
return saved_in_initrd;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2727,8 +2727,8 @@ int bus_exec_context_set_transient_property(
|
|||||||
|
|
||||||
} else if (STR_IN_SET(name,
|
} else if (STR_IN_SET(name,
|
||||||
"StandardInputFile",
|
"StandardInputFile",
|
||||||
"StandardOutputFile", "StandardOutputFileToAppend",
|
"StandardOutputFile", "StandardOutputFileToAppend", "StandardOutputFileToTruncate",
|
||||||
"StandardErrorFile", "StandardErrorFileToAppend")) {
|
"StandardErrorFile", "StandardErrorFileToAppend", "StandardErrorFileToTruncate")) {
|
||||||
const char *s;
|
const char *s;
|
||||||
|
|
||||||
r = sd_bus_message_read(message, "s", &s);
|
r = sd_bus_message_read(message, "s", &s);
|
||||||
@ -2752,7 +2752,7 @@ int bus_exec_context_set_transient_property(
|
|||||||
c->std_input = EXEC_INPUT_FILE;
|
c->std_input = EXEC_INPUT_FILE;
|
||||||
unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardInput=file:%s", s);
|
unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardInput=file:%s", s);
|
||||||
|
|
||||||
} else if (STR_IN_SET(name, "StandardOutputFile", "StandardOutputFileToAppend")) {
|
} else if (STR_IN_SET(name, "StandardOutputFile", "StandardOutputFileToAppend", "StandardOutputFileToTruncate")) {
|
||||||
r = free_and_strdup(&c->stdio_file[STDOUT_FILENO], empty_to_null(s));
|
r = free_and_strdup(&c->stdio_file[STDOUT_FILENO], empty_to_null(s));
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
@ -2760,13 +2760,16 @@ int bus_exec_context_set_transient_property(
|
|||||||
if (streq(name, "StandardOutputFile")) {
|
if (streq(name, "StandardOutputFile")) {
|
||||||
c->std_output = EXEC_OUTPUT_FILE;
|
c->std_output = EXEC_OUTPUT_FILE;
|
||||||
unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardOutput=file:%s", s);
|
unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardOutput=file:%s", s);
|
||||||
} else {
|
} else if (streq(name, "StandardOutputFileToAppend")) {
|
||||||
assert(streq(name, "StandardOutputFileToAppend"));
|
|
||||||
c->std_output = EXEC_OUTPUT_FILE_APPEND;
|
c->std_output = EXEC_OUTPUT_FILE_APPEND;
|
||||||
unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardOutput=append:%s", s);
|
unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardOutput=append:%s", s);
|
||||||
|
} else {
|
||||||
|
assert(streq(name, "StandardOutputFileToTruncate"));
|
||||||
|
c->std_output = EXEC_OUTPUT_FILE_TRUNCATE;
|
||||||
|
unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardOutput=truncate:%s", s);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
assert(STR_IN_SET(name, "StandardErrorFile", "StandardErrorFileToAppend"));
|
assert(STR_IN_SET(name, "StandardErrorFile", "StandardErrorFileToAppend", "StandardErrorFileToTruncate"));
|
||||||
|
|
||||||
r = free_and_strdup(&c->stdio_file[STDERR_FILENO], empty_to_null(s));
|
r = free_and_strdup(&c->stdio_file[STDERR_FILENO], empty_to_null(s));
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
@ -2775,10 +2778,13 @@ int bus_exec_context_set_transient_property(
|
|||||||
if (streq(name, "StandardErrorFile")) {
|
if (streq(name, "StandardErrorFile")) {
|
||||||
c->std_error = EXEC_OUTPUT_FILE;
|
c->std_error = EXEC_OUTPUT_FILE;
|
||||||
unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardError=file:%s", s);
|
unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardError=file:%s", s);
|
||||||
} else {
|
} else if (streq(name, "StandardErrorFileToAppend")) {
|
||||||
assert(streq(name, "StandardErrorFileToAppend"));
|
|
||||||
c->std_error = EXEC_OUTPUT_FILE_APPEND;
|
c->std_error = EXEC_OUTPUT_FILE_APPEND;
|
||||||
unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardError=append:%s", s);
|
unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardError=append:%s", s);
|
||||||
|
} else {
|
||||||
|
assert(streq(name, "StandardErrorFileToTruncate"));
|
||||||
|
c->std_error = EXEC_OUTPUT_FILE_TRUNCATE;
|
||||||
|
unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardError=truncate:%s", s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -562,7 +562,7 @@ static bool can_inherit_stderr_from_stdout(
|
|||||||
if (e == EXEC_OUTPUT_NAMED_FD)
|
if (e == EXEC_OUTPUT_NAMED_FD)
|
||||||
return streq_ptr(context->stdio_fdname[STDOUT_FILENO], context->stdio_fdname[STDERR_FILENO]);
|
return streq_ptr(context->stdio_fdname[STDOUT_FILENO], context->stdio_fdname[STDERR_FILENO]);
|
||||||
|
|
||||||
if (IN_SET(e, EXEC_OUTPUT_FILE, EXEC_OUTPUT_FILE_APPEND))
|
if (IN_SET(e, EXEC_OUTPUT_FILE, EXEC_OUTPUT_FILE_APPEND, EXEC_OUTPUT_FILE_TRUNCATE))
|
||||||
return streq_ptr(context->stdio_file[STDOUT_FILENO], context->stdio_file[STDERR_FILENO]);
|
return streq_ptr(context->stdio_file[STDOUT_FILENO], context->stdio_file[STDERR_FILENO]);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -698,7 +698,8 @@ static int setup_output(
|
|||||||
return dup2(named_iofds[fileno], fileno) < 0 ? -errno : fileno;
|
return dup2(named_iofds[fileno], fileno) < 0 ? -errno : fileno;
|
||||||
|
|
||||||
case EXEC_OUTPUT_FILE:
|
case EXEC_OUTPUT_FILE:
|
||||||
case EXEC_OUTPUT_FILE_APPEND: {
|
case EXEC_OUTPUT_FILE_APPEND:
|
||||||
|
case EXEC_OUTPUT_FILE_TRUNCATE: {
|
||||||
bool rw;
|
bool rw;
|
||||||
int fd, flags;
|
int fd, flags;
|
||||||
|
|
||||||
@ -713,6 +714,8 @@ static int setup_output(
|
|||||||
flags = O_WRONLY;
|
flags = O_WRONLY;
|
||||||
if (o == EXEC_OUTPUT_FILE_APPEND)
|
if (o == EXEC_OUTPUT_FILE_APPEND)
|
||||||
flags |= O_APPEND;
|
flags |= O_APPEND;
|
||||||
|
else if (o == EXEC_OUTPUT_FILE_TRUNCATE)
|
||||||
|
flags |= O_TRUNC;
|
||||||
|
|
||||||
fd = acquire_path(context->stdio_file[fileno], flags, 0666 & ~context->umask);
|
fd = acquire_path(context->stdio_file[fileno], flags, 0666 & ~context->umask);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
@ -5357,10 +5360,14 @@ void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) {
|
|||||||
fprintf(f, "%sStandardOutputFile: %s\n", prefix, c->stdio_file[STDOUT_FILENO]);
|
fprintf(f, "%sStandardOutputFile: %s\n", prefix, c->stdio_file[STDOUT_FILENO]);
|
||||||
if (c->std_output == EXEC_OUTPUT_FILE_APPEND)
|
if (c->std_output == EXEC_OUTPUT_FILE_APPEND)
|
||||||
fprintf(f, "%sStandardOutputFileToAppend: %s\n", prefix, c->stdio_file[STDOUT_FILENO]);
|
fprintf(f, "%sStandardOutputFileToAppend: %s\n", prefix, c->stdio_file[STDOUT_FILENO]);
|
||||||
|
if (c->std_output == EXEC_OUTPUT_FILE_TRUNCATE)
|
||||||
|
fprintf(f, "%sStandardOutputFileToTruncate: %s\n", prefix, c->stdio_file[STDOUT_FILENO]);
|
||||||
if (c->std_error == EXEC_OUTPUT_FILE)
|
if (c->std_error == EXEC_OUTPUT_FILE)
|
||||||
fprintf(f, "%sStandardErrorFile: %s\n", prefix, c->stdio_file[STDERR_FILENO]);
|
fprintf(f, "%sStandardErrorFile: %s\n", prefix, c->stdio_file[STDERR_FILENO]);
|
||||||
if (c->std_error == EXEC_OUTPUT_FILE_APPEND)
|
if (c->std_error == EXEC_OUTPUT_FILE_APPEND)
|
||||||
fprintf(f, "%sStandardErrorFileToAppend: %s\n", prefix, c->stdio_file[STDERR_FILENO]);
|
fprintf(f, "%sStandardErrorFileToAppend: %s\n", prefix, c->stdio_file[STDERR_FILENO]);
|
||||||
|
if (c->std_error == EXEC_OUTPUT_FILE_TRUNCATE)
|
||||||
|
fprintf(f, "%sStandardErrorFileToTruncate: %s\n", prefix, c->stdio_file[STDERR_FILENO]);
|
||||||
|
|
||||||
if (c->tty_path)
|
if (c->tty_path)
|
||||||
fprintf(f,
|
fprintf(f,
|
||||||
@ -6449,6 +6456,7 @@ static const char* const exec_output_table[_EXEC_OUTPUT_MAX] = {
|
|||||||
[EXEC_OUTPUT_NAMED_FD] = "fd",
|
[EXEC_OUTPUT_NAMED_FD] = "fd",
|
||||||
[EXEC_OUTPUT_FILE] = "file",
|
[EXEC_OUTPUT_FILE] = "file",
|
||||||
[EXEC_OUTPUT_FILE_APPEND] = "append",
|
[EXEC_OUTPUT_FILE_APPEND] = "append",
|
||||||
|
[EXEC_OUTPUT_FILE_TRUNCATE] = "truncate",
|
||||||
};
|
};
|
||||||
|
|
||||||
DEFINE_STRING_TABLE_LOOKUP(exec_output, ExecOutput);
|
DEFINE_STRING_TABLE_LOOKUP(exec_output, ExecOutput);
|
||||||
|
|||||||
@ -61,6 +61,7 @@ typedef enum ExecOutput {
|
|||||||
EXEC_OUTPUT_NAMED_FD,
|
EXEC_OUTPUT_NAMED_FD,
|
||||||
EXEC_OUTPUT_FILE,
|
EXEC_OUTPUT_FILE,
|
||||||
EXEC_OUTPUT_FILE_APPEND,
|
EXEC_OUTPUT_FILE_APPEND,
|
||||||
|
EXEC_OUTPUT_FILE_TRUNCATE,
|
||||||
_EXEC_OUTPUT_MAX,
|
_EXEC_OUTPUT_MAX,
|
||||||
_EXEC_OUTPUT_INVALID = -1
|
_EXEC_OUTPUT_INVALID = -1
|
||||||
} ExecOutput;
|
} ExecOutput;
|
||||||
|
|||||||
@ -1202,6 +1202,20 @@ int config_parse_exec_output(
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
eo = EXEC_OUTPUT_FILE_APPEND;
|
eo = EXEC_OUTPUT_FILE_APPEND;
|
||||||
|
|
||||||
|
} else if ((n = startswith(rvalue, "truncate:"))) {
|
||||||
|
|
||||||
|
r = unit_full_printf(u, n, &resolved);
|
||||||
|
if (r < 0) {
|
||||||
|
log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", n);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = path_simplify_and_warn(resolved, PATH_CHECK_ABSOLUTE | PATH_CHECK_FATAL, unit, filename, line, lvalue);
|
||||||
|
if (r < 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
eo = EXEC_OUTPUT_FILE_TRUNCATE;
|
||||||
} else {
|
} else {
|
||||||
eo = exec_output_from_string(rvalue);
|
eo = exec_output_from_string(rvalue);
|
||||||
if (eo < 0) {
|
if (eo < 0) {
|
||||||
@ -5761,8 +5775,8 @@ int config_parse_output_restricted(
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IN_SET(t, EXEC_OUTPUT_SOCKET, EXEC_OUTPUT_NAMED_FD, EXEC_OUTPUT_FILE, EXEC_OUTPUT_FILE_APPEND)) {
|
if (IN_SET(t, EXEC_OUTPUT_SOCKET, EXEC_OUTPUT_NAMED_FD, EXEC_OUTPUT_FILE, EXEC_OUTPUT_FILE_APPEND, EXEC_OUTPUT_FILE_TRUNCATE)) {
|
||||||
log_syntax(unit, LOG_WARNING, filename, line, 0, "Standard output types socket, fd:, file:, append: are not supported as defaults, ignoring: %s", rvalue);
|
log_syntax(unit, LOG_WARNING, filename, line, 0, "Standard output types socket, fd:, file:, append:, truncate: are not supported as defaults, ignoring: %s", rvalue);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1144,6 +1144,9 @@ static int bus_append_execute_property(sd_bus_message *m, const char *field, con
|
|||||||
} else if ((n = startswith(eq, "append:"))) {
|
} else if ((n = startswith(eq, "append:"))) {
|
||||||
appended = strjoina(field, "FileToAppend");
|
appended = strjoina(field, "FileToAppend");
|
||||||
r = sd_bus_message_append(m, "(sv)", appended, "s", n);
|
r = sd_bus_message_append(m, "(sv)", appended, "s", n);
|
||||||
|
} else if ((n = startswith(eq, "truncate:"))) {
|
||||||
|
appended = strjoina(field, "FileToTruncate");
|
||||||
|
r = sd_bus_message_append(m, "(sv)", appended, "s", n);
|
||||||
} else
|
} else
|
||||||
r = sd_bus_message_append(m, "(sv)", field, "s", eq);
|
r = sd_bus_message_append(m, "(sv)", field, "s", eq);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
|
|||||||
@ -811,6 +811,10 @@ static void test_exec_standardoutput_append(Manager *m) {
|
|||||||
test(m, "exec-standardoutput-append.service", 0, CLD_EXITED);
|
test(m, "exec-standardoutput-append.service", 0, CLD_EXITED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_exec_standardoutput_truncate(Manager *m) {
|
||||||
|
test(m, "exec-standardoutput-truncate.service", 0, CLD_EXITED);
|
||||||
|
}
|
||||||
|
|
||||||
static void test_exec_condition(Manager *m) {
|
static void test_exec_condition(Manager *m) {
|
||||||
test_service(m, "exec-condition-failed.service", SERVICE_FAILURE_EXIT_CODE);
|
test_service(m, "exec-condition-failed.service", SERVICE_FAILURE_EXIT_CODE);
|
||||||
test_service(m, "exec-condition-skip.service", SERVICE_SKIP_CONDITION);
|
test_service(m, "exec-condition-skip.service", SERVICE_SKIP_CONDITION);
|
||||||
@ -876,6 +880,7 @@ int main(int argc, char *argv[]) {
|
|||||||
entry(test_exec_standardinput),
|
entry(test_exec_standardinput),
|
||||||
entry(test_exec_standardoutput),
|
entry(test_exec_standardoutput),
|
||||||
entry(test_exec_standardoutput_append),
|
entry(test_exec_standardoutput_append),
|
||||||
|
entry(test_exec_standardoutput_truncate),
|
||||||
entry(test_exec_supplementarygroups),
|
entry(test_exec_supplementarygroups),
|
||||||
entry(test_exec_systemcallerrornumber),
|
entry(test_exec_systemcallerrornumber),
|
||||||
entry(test_exec_systemcallfilter),
|
entry(test_exec_systemcallfilter),
|
||||||
|
|||||||
13
test/test-execute/exec-standardoutput-truncate.service
Normal file
13
test/test-execute/exec-standardoutput-truncate.service
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Test for StandardOutput=truncate:
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
ExecStartPre=sh -c 'printf "hello\n" > /tmp/test-exec-standardoutput-output'
|
||||||
|
ExecStartPre=sh -c 'printf "hi\n" > /tmp/test-exec-standardoutput-expected'
|
||||||
|
StandardInput=data
|
||||||
|
StandardInputText=hi
|
||||||
|
StandardOutput=truncate:/tmp/test-exec-standardoutput-output
|
||||||
|
StandardError=null
|
||||||
|
ExecStart=cat
|
||||||
|
ExecStartPost=cmp /tmp/test-exec-standardoutput-output /tmp/test-exec-standardoutput-expected
|
||||||
|
Type=oneshot
|
||||||
@ -43,6 +43,18 @@ a
|
|||||||
c
|
c
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
systemd-run --wait --unit=test27-four \
|
||||||
|
-p StandardOutput=truncate:/tmp/stdout \
|
||||||
|
-p StandardError=truncate:/tmp/stderr \
|
||||||
|
-p Type=exec \
|
||||||
|
sh -c 'echo a ; echo b >&2'
|
||||||
|
cmp /tmp/stdout <<EOF
|
||||||
|
a
|
||||||
|
EOF
|
||||||
|
cmp /tmp/stderr <<EOF
|
||||||
|
b
|
||||||
|
EOF
|
||||||
|
|
||||||
systemd-analyze log-level info
|
systemd-analyze log-level info
|
||||||
|
|
||||||
echo OK >/testok
|
echo OK >/testok
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user