Merge pull request #10944 from poettering/redirect-file-fix

StandardOutput=file: fixes
This commit is contained in:
Lennart Poettering 2018-11-27 13:18:26 +01:00 committed by GitHub
commit 4917894417
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 127 additions and 9 deletions

View File

@ -1795,8 +1795,8 @@ int bus_exec_context_set_transient_property(
} else if (STR_IN_SET(name,
"StandardInputFile",
"StandardOutputFile", "StandardOutputFileToCreate", "StandardOutputFileToAppend",
"StandardErrorFile", "StandardErrorFileToCreate", "StandardErrorFileToAppend")) {
"StandardOutputFile", "StandardOutputFileToAppend",
"StandardErrorFile", "StandardErrorFileToAppend")) {
const char *s;
r = sd_bus_message_read(message, "s", &s);
@ -1842,11 +1842,11 @@ int bus_exec_context_set_transient_property(
if (streq(name, "StandardErrorFile")) {
c->std_error = 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, "StandardError=file:%s", s);
} else {
assert(streq(name, "StandardErrorFileToAppend"));
c->std_error = EXEC_OUTPUT_FILE_APPEND;
unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardOutput=append:%s", s);
assert(streq(name, "StandardErrorFileToAppend"));
c->std_error = EXEC_OUTPUT_FILE_APPEND;
unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardError=append:%s", s);
}
}
}

View File

@ -544,6 +544,30 @@ static int setup_input(
}
}
static bool can_inherit_stderr_from_stdout(
const ExecContext *context,
ExecOutput o,
ExecOutput e) {
assert(context);
/* Returns true, if given the specified STDERR and STDOUT output we can directly dup() the stdout fd to the
* stderr fd */
if (e == EXEC_OUTPUT_INHERIT)
return true;
if (e != o)
return false;
if (e == EXEC_OUTPUT_NAMED_FD)
return streq_ptr(context->stdio_fdname[STDOUT_FILENO], context->stdio_fdname[STDERR_FILENO]);
if (IN_SET(e, EXEC_OUTPUT_FILE, EXEC_OUTPUT_FILE_APPEND))
return streq_ptr(context->stdio_file[STDOUT_FILENO], context->stdio_file[STDERR_FILENO]);
return true;
}
static int setup_output(
const Unit *unit,
const ExecContext *context,
@ -602,7 +626,7 @@ static int setup_output(
return fileno;
/* Duplicate from stdout if possible */
if ((e == o && e != EXEC_OUTPUT_NAMED_FD) || e == EXEC_OUTPUT_INHERIT)
if (can_inherit_stderr_from_stdout(context, o, e))
return dup2(STDOUT_FILENO, fileno) < 0 ? -errno : fileno;
o = e;
@ -693,7 +717,6 @@ static int setup_output(
flags |= O_APPEND;
fd = acquire_path(context->stdio_file[fileno], flags, 0666 & ~context->umask);
if (fd < 0)
return fd;

View File

@ -873,9 +873,11 @@ static int bus_append_execute_property(sd_bus_message *m, const char *field, con
} else if ((n = startswith(eq, "file:"))) {
appended = strjoina(field, "File");
r = sd_bus_message_append(m, "(sv)", appended, "s", n);
} else if ((n = startswith(eq, "append:"))) {
appended = strjoina(field, "FileToAppend");
r = sd_bus_message_append(m, "(sv)", appended, "s", n);
} else
r = sd_bus_message_append(m, "(sv)", field, "s", eq);
if (r < 0)
return bus_log_create_error(r);

View File

@ -0,0 +1 @@
../TEST-01-BASIC/Makefile

52
test/TEST-27-STDOUTFILE/test.sh Executable file
View File

@ -0,0 +1,52 @@
#!/bin/bash
# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
# ex: ts=8 sw=4 sts=4 et filetype=sh
set -e
TEST_DESCRIPTION="test StandardOutput=file:"
. $TEST_BASE_DIR/test-functions
test_setup() {
create_empty_image
mkdir -p $TESTDIR/root
mount ${LOOPDEV}p1 $TESTDIR/root
(
LOG_LEVEL=5
eval $(udevadm info --export --query=env --name=${LOOPDEV}p2)
inst_binary cmp
setup_basic_environment
# mask some services that we do not want to run in these tests
ln -fs /dev/null $initdir/etc/systemd/system/systemd-hwdb-update.service
ln -fs /dev/null $initdir/etc/systemd/system/systemd-journal-catalog-update.service
ln -fs /dev/null $initdir/etc/systemd/system/systemd-networkd.service
ln -fs /dev/null $initdir/etc/systemd/system/systemd-networkd.socket
ln -fs /dev/null $initdir/etc/systemd/system/systemd-resolved.service
ln -fs /dev/null $initdir/etc/systemd/system/systemd-machined.service
# setup the testsuite service
cat >$initdir/etc/systemd/system/testsuite.service <<EOF
[Unit]
Description=Testsuite service
[Service]
ExecStart=/testsuite.sh
Type=oneshot
StandardOutput=tty
StandardError=tty
NotifyAccess=all
EOF
cp testsuite.sh $initdir/
setup_testsuite
) || return 1
setup_nspawn_root
ddebug "umount $TESTDIR/root"
umount $TESTDIR/root
}
do_test "$@"

View File

@ -0,0 +1,40 @@
#!/bin/bash
# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
# ex: ts=8 sw=4 sts=4 et filetype=sh
set -ex
set -o pipefail
systemd-analyze set-log-level debug
systemd-analyze set-log-target console
systemd-run --unit=one -p StandardOutput=file:/tmp/stdout -p StandardError=file:/tmp/stderr -p Type=exec sh -c 'echo x ; echo y >&2'
cmp /tmp/stdout <<EOF
x
EOF
cmp /tmp/stderr <<EOF
y
EOF
systemd-run --unit=two -p StandardOutput=file:/tmp/stdout -p StandardError=file:/tmp/stderr -p Type=exec sh -c 'echo z ; echo a >&2'
cmp /tmp/stdout <<EOF
z
EOF
cmp /tmp/stderr <<EOF
a
EOF
systemd-run --unit=three -p StandardOutput=append:/tmp/stdout -p StandardError=append:/tmp/stderr -p Type=exec sh -c 'echo b ; echo c >&2'
cmp /tmp/stdout <<EOF
z
b
EOF
cmp /tmp/stderr <<EOF
a
c
EOF
systemd-analyze set-log-level info
echo OK > /testok
exit 0