Merge pull request #3074 from keszybz/tmpfiles

systemd-tmpfiles improvements, nspawn -E, honouring $TERM in pid1
This commit is contained in:
Lennart Poettering
2016-04-20 20:26:34 +02:00
11 changed files with 142 additions and 108 deletions
+7 -9
View File
@@ -195,16 +195,14 @@
</varlistentry>
<varlistentry>
<term><option>--setenv=</option></term>
<term><option>-E <replaceable>NAME</replaceable>=<replaceable>VALUE</replaceable></option></term>
<term><option>--setenv=<replaceable>NAME</replaceable>=<replaceable>VALUE</replaceable></option></term>
<listitem><para>When used with the <command>shell</command>
command, sets an environment variable to pass to the executed
shell. Takes a pair of environment variable name and value,
separated by <literal>=</literal> as argument. This switch
may be used multiple times to set multiple environment
variables. Note that this switch is not supported for the
<command>login</command> command (see
below).</para></listitem>
<listitem><para>When used with the <command>shell</command> command, sets an environment
variable to pass to the executed shell. Takes an environment variable name and value,
separated by <literal>=</literal>. This switch may be used multiple times to set multiple
environment variables. Note that this switch is not supported for the
<command>login</command> command (see below).</para></listitem>
</varlistentry>
<varlistentry>
+2 -1
View File
@@ -737,7 +737,8 @@
</varlistentry>
<varlistentry>
<term><option>--setenv=</option></term>
<term><option>-E <replaceable>NAME</replaceable>=<replaceable>VALUE</replaceable></option></term>
<term><option>--setenv=<replaceable>NAME</replaceable>=<replaceable>VALUE</replaceable></option></term>
<listitem><para>Specifies an environment variable assignment
to pass to the init process in the container, in the format
+4 -4
View File
@@ -226,11 +226,11 @@
</varlistentry>
<varlistentry>
<term><option>--setenv=</option></term>
<term><option>-E <replaceable>NAME</replaceable>=<replaceable>VALUE</replaceable></option></term>
<term><option>--setenv=<replaceable>NAME</replaceable>=<replaceable>VALUE</replaceable></option></term>
<listitem><para>Runs the service process with the specified
environment variables set. Also see
<varname>Environment=</varname> in
<listitem><para>Runs the service process with the specified environment variable set.
Also see <varname>Environment=</varname> in
<citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
</listitem>
</varlistentry>
+5 -5
View File
@@ -75,11 +75,11 @@
<citerefentry><refentrytitle>tmpfiles.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
</para>
<para>If invoked with no arguments, it applies all directives from
all configuration files. If one or more absolute filenames are passed on
the command line, only the directives in these files are applied.
If only the basename of a configuration file is specified, all
configuration directories as specified in
<para>If invoked with no arguments, it applies all directives from all configuration
files. If one or more absolute filenames are passed on the command line, only the
directives in these files are applied. If <literal>-</literal> is specified instead
of a filename, directives are read from standard input. If only the basename of a
configuration file is specified, all configuration directories as specified in
<citerefentry><refentrytitle>tmpfiles.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>
are searched for a matching file.</para>
</refsect1>
+67 -16
View File
@@ -157,13 +157,23 @@
<varlistentry>
<term><varname>d</varname></term>
<listitem><para>Create a directory if it does not exist yet.
</para></listitem>
<listitem><para>Create a directory. The mode and ownership will be adjusted if
specified and the directory already exists. Contents of this directory are subject
to time based cleanup if the time argument is specified.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>D</varname></term>
<listitem><para>Create or empty a directory.</para></listitem>
<listitem><para>Similar to <varname>d</varname>, but in addition the contents
of the directory will be removed when <option>--remove</option> is used.
</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>e</varname></term>
<listitem><para>Similar to <varname>d</varname>, but the directory will not be
created if it does not exist. Lines of this type accept shell-style globs in
place of normal path names.</para></listitem>
</varlistentry>
<varlistentry>
@@ -577,7 +587,7 @@
unconditionally.</para>
<para>The age field only applies to lines starting with
<varname>d</varname>, <varname>D</varname>,
<varname>d</varname>, <varname>D</varname>, <varname>e</varname>,
<varname>v</varname>, <varname>q</varname>,
<varname>Q</varname>, <varname>C</varname>, <varname>x</varname>
and <varname>X</varname>. If omitted or set to
@@ -612,22 +622,63 @@
</refsect1>
<refsect1>
<title>Example</title>
<title>Examples</title>
<example>
<title>/etc/tmpfiles.d/screen.conf example</title>
<para><command>screen</command> needs two directories created at
boot with specific modes and ownership.</para>
<title>Create directories with specific mode and ownership</title>
<para>
<citerefentry><refentrytitle>screen</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
needs two directories created at boot with specific modes and ownership:</para>
<programlisting>d /run/screens 1777 root root 10d
d /run/uscreens 0755 root root 10d12h
t /run/screen - - - - user.name="John Smith" security.SMACK64=screen</programlisting>
<programlisting># /usr/lib/tmpfiles.d/screen.conf
d /run/screens 1777 root screen 10d
d /run/uscreens 0755 root screen 10d12h
</programlisting>
<para>Contents of <filename>/run/screens</filename> and /run/uscreens will
cleaned up after 10 and 10½ days, respectively.</para>
</example>
<example>
<title>/etc/tmpfiles.d/abrt.conf example</title>
<para><command>abrt</command> needs a directory created at boot with specific mode and ownership and its content should be preserved.</para>
<programlisting>d /var/tmp/abrt 0755 abrt abrt
x /var/tmp/abrt/*</programlisting>
<example>
<title>Create a directory with a SMACK attribute</title>
<programlisting>D /run/cups - - - -
t /run/cups - - - - security.SMACK64=printing user.attr-with-spaces="foo bar"
</programlisting>
<para>The direcory will be owned by root and have default mode. It's contents are
not subject to time based cleanup, but will be obliterated when
<command>systemd-tmpfiles --remove</command> runs.</para>
</example>
<example>
<title>Create a directory and prevent its contents from cleanup</title>
<para>
<citerefentry><refentrytitle>abrt</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
needs a directory created at boot with specific mode and ownership and its content
should be preserved from the automatic cleanup applied to the contents of
<filename>/var/tmp</filename>:</para>
<programlisting># /usr/lib/tmpfiles.d/tmp.conf
d /var/tmp 1777 root root 30d
</programlisting>
<programlisting># /usr/lib/tmpfiles.d/abrt.conf
d /var/tmp/abrt 0755 abrt abrt -
</programlisting>
</example>
<example>
<title>Apply clean up during boot and based on time</title>
<programlisting># /usr/lib/tmpfiles.d/dnf.conf
r! /var/cache/dnf/*/*/download_lock.pid
r! /var/cache/dnf/*/*/metadata_lock.pid
r! /var/lib/dnf/rpmdb_lock.pid
e /var/chache/dnf/ - - - 30d
</programlisting>
<para>The lock files will be removed during boot. Any files and directories in
<filename>/var/chache/dnf/</filename> will be removed after they have not been
accessed in 30 days.</para>
</example>
</refsect1>
+12 -7
View File
@@ -1135,14 +1135,19 @@ int open_terminal_in_namespace(pid_t pid, const char *name, int mode) {
}
bool colors_enabled(void) {
const char *colors;
static int enabled = -1;
colors = getenv("SYSTEMD_COLORS");
if (!colors) {
if (streq_ptr(getenv("TERM"), "dumb"))
return false;
return on_tty();
if (_unlikely_(enabled < 0)) {
const char *colors;
colors = getenv("SYSTEMD_COLORS");
if (colors)
enabled = parse_boolean(colors) != 0;
else if (streq_ptr(getenv("TERM"), "dumb"))
enabled = false;
else
enabled = on_tty();
}
return parse_boolean(colors) != 0;
return enabled;
}
+1 -1
View File
@@ -1338,7 +1338,7 @@ int main(int argc, char *argv[]) {
saved_argv = argv;
saved_argc = argc;
log_show_color(isatty(STDERR_FILENO) > 0);
log_show_color(colors_enabled());
log_set_upgrade_syslog_to_journal(true);
/* Disable the umask logic */
+3 -4
View File
@@ -2402,7 +2402,7 @@ static int help(int argc, char *argv[], void *userdata) {
" --kill-who=WHO Who to send signal to\n"
" -s --signal=SIGNAL Which signal to send\n"
" --uid=USER Specify user ID to invoke shell as\n"
" --setenv=VAR=VALUE Add an environment variable for shell\n"
" -E --setenv=VAR=VALUE Add an environment variable for shell\n"
" --read-only Create read-only bind mount\n"
" --mkdir Create directory before bind mounting, if missing\n"
" -n --lines=INTEGER Number of journal entries to show\n"
@@ -2470,7 +2470,6 @@ static int parse_argv(int argc, char *argv[]) {
ARG_FORCE,
ARG_FORMAT,
ARG_UID,
ARG_SETENV,
};
static const struct option options[] = {
@@ -2496,7 +2495,7 @@ static int parse_argv(int argc, char *argv[]) {
{ "force", no_argument, NULL, ARG_FORCE },
{ "format", required_argument, NULL, ARG_FORMAT },
{ "uid", required_argument, NULL, ARG_UID },
{ "setenv", required_argument, NULL, ARG_SETENV },
{ "setenv", required_argument, NULL, 'E' },
{}
};
@@ -2624,7 +2623,7 @@ static int parse_argv(int argc, char *argv[]) {
arg_uid = optarg;
break;
case ARG_SETENV:
case 'E':
if (!env_assignment_is_valid(optarg)) {
log_error("Environment assignment invalid: %s", optarg);
return -EINVAL;
+3 -4
View File
@@ -250,7 +250,7 @@ static void help(void) {
" the container\n"
" --overlay-ro=PATH[:PATH...]:PATH\n"
" Similar, but creates a read-only overlay mount\n"
" --setenv=NAME=VALUE Pass an environment variable to PID 1\n"
" -E --setenv=NAME=VALUE Pass an environment variable to PID 1\n"
" --share-system Share system namespaces with host\n"
" --register=BOOLEAN Register container as machine\n"
" --keep-unit Do not register a scope for the machine, reuse\n"
@@ -333,7 +333,6 @@ static int parse_argv(int argc, char *argv[]) {
ARG_TMPFS,
ARG_OVERLAY,
ARG_OVERLAY_RO,
ARG_SETENV,
ARG_SHARE_SYSTEM,
ARG_REGISTER,
ARG_KEEP_UNIT,
@@ -374,7 +373,7 @@ static int parse_argv(int argc, char *argv[]) {
{ "overlay-ro", required_argument, NULL, ARG_OVERLAY_RO },
{ "machine", required_argument, NULL, 'M' },
{ "slice", required_argument, NULL, 'S' },
{ "setenv", required_argument, NULL, ARG_SETENV },
{ "setenv", required_argument, NULL, 'E' },
{ "selinux-context", required_argument, NULL, 'Z' },
{ "selinux-apifs-context", required_argument, NULL, 'L' },
{ "quiet", no_argument, NULL, 'q' },
@@ -711,7 +710,7 @@ static int parse_argv(int argc, char *argv[]) {
break;
}
case ARG_SETENV: {
case 'E': {
char **n;
if (!env_assignment_is_valid(optarg)) {
+3 -4
View File
@@ -103,7 +103,7 @@ static void help(void) {
" --uid=USER Run as system user\n"
" --gid=GROUP Run as system group\n"
" --nice=NICE Nice level\n"
" --setenv=NAME=VALUE Set environment\n"
" -E --setenv=NAME=VALUE Set environment\n"
" -t --pty Run service on pseudo tty\n"
" -q --quiet Suppress information messages during runtime\n\n"
"Timer options:\n\n"
@@ -136,7 +136,6 @@ static int parse_argv(int argc, char *argv[]) {
ARG_EXEC_USER,
ARG_EXEC_GROUP,
ARG_NICE,
ARG_SETENV,
ARG_ON_ACTIVE,
ARG_ON_BOOT,
ARG_ON_STARTUP,
@@ -165,7 +164,7 @@ static int parse_argv(int argc, char *argv[]) {
{ "uid", required_argument, NULL, ARG_EXEC_USER },
{ "gid", required_argument, NULL, ARG_EXEC_GROUP },
{ "nice", required_argument, NULL, ARG_NICE },
{ "setenv", required_argument, NULL, ARG_SETENV },
{ "setenv", required_argument, NULL, 'E' },
{ "property", required_argument, NULL, 'p' },
{ "tty", no_argument, NULL, 't' }, /* deprecated */
{ "pty", no_argument, NULL, 't' },
@@ -266,7 +265,7 @@ static int parse_argv(int argc, char *argv[]) {
arg_nice_set = true;
break;
case ARG_SETENV:
case 'E':
if (strv_extend(&arg_environment, optarg) < 0)
return log_oom();
+35 -53
View File
@@ -94,6 +94,7 @@ typedef enum ItemType {
/* These ones take globs */
WRITE_FILE = 'w',
EMPTY_DIRECTORY = 'e',
SET_XATTR = 't',
RECURSIVE_SET_XATTR = 'T',
SET_ACL = 'a',
@@ -179,6 +180,7 @@ static bool needs_glob(ItemType t) {
IGNORE_DIRECTORY_PATH,
REMOVE_PATH,
RECURSIVE_REMOVE_PATH,
EMPTY_DIRECTORY,
ADJUST_MODE,
RELABEL_PATH,
RECURSIVE_RELABEL_PATH,
@@ -195,6 +197,7 @@ static bool takes_ownership(ItemType t) {
CREATE_FILE,
TRUNCATE_FILE,
CREATE_DIRECTORY,
EMPTY_DIRECTORY,
TRUNCATE_DIRECTORY,
CREATE_SUBVOLUME,
CREATE_SUBVOLUME_INHERIT_QUOTA,
@@ -1217,7 +1220,6 @@ static int create_item(Item *i) {
case CREATE_SUBVOLUME:
case CREATE_SUBVOLUME_INHERIT_QUOTA:
case CREATE_SUBVOLUME_NEW_QUOTA:
RUN_WITH_UMASK(0000)
mkdir_parents_label(i->path, 0755);
@@ -1276,11 +1278,11 @@ static int create_item(Item *i) {
if (IN_SET(i->type, CREATE_SUBVOLUME_NEW_QUOTA, CREATE_SUBVOLUME_INHERIT_QUOTA)) {
r = btrfs_subvol_auto_qgroup(i->path, 0, i->type == CREATE_SUBVOLUME_NEW_QUOTA);
if (r == -ENOTTY)
log_debug_errno(r, "Couldn't adjust quota for subvolume \"%s\" because of unsupported file system or because directory is not a subvolume: %m", i->path);
log_debug_errno(r, "Couldn't adjust quota for subvolume \"%s\" (unsupported fs or dir not a subvolume): %m", i->path);
else if (r == -EROFS)
log_debug_errno(r, "Couldn't adjust quota for subvolume \"%s\" because of read-only file system: %m", i->path);
log_debug_errno(r, "Couldn't adjust quota for subvolume \"%s\" (fs is read-only).", i->path);
else if (r == -ENOPROTOOPT)
log_debug_errno(r, "Couldn't adjust quota for subvolume \"%s\" because quota support is disabled: %m", i->path);
log_debug_errno(r, "Couldn't adjust quota for subvolume \"%s\" (quota support is disabled).", i->path);
else if (r < 0)
q = log_error_errno(r, "Failed to adjust quota for subvolume \"%s\": %m", i->path);
else if (r > 0)
@@ -1289,6 +1291,9 @@ static int create_item(Item *i) {
log_debug("Quota for subvolume \"%s\" already in place, no change made.", i->path);
}
/* fall through */
case EMPTY_DIRECTORY:
r = path_set_perms(i, i->path);
if (q < 0)
return q;
@@ -1298,7 +1303,6 @@ static int create_item(Item *i) {
break;
case CREATE_FIFO:
RUN_WITH_UMASK(0000) {
mac_selinux_create_file_prepare(i->path, S_IFIFO);
r = mkfifo(i->path, i->mode);
@@ -1535,47 +1539,20 @@ static int remove_item_instance(Item *i, const char *instance) {
}
static int remove_item(Item *i) {
int r = 0;
assert(i);
log_debug("Running remove action for entry %c %s", (char) i->type, i->path);
switch (i->type) {
case CREATE_FILE:
case TRUNCATE_FILE:
case CREATE_DIRECTORY:
case CREATE_SUBVOLUME:
case CREATE_SUBVOLUME_INHERIT_QUOTA:
case CREATE_SUBVOLUME_NEW_QUOTA:
case CREATE_FIFO:
case CREATE_SYMLINK:
case CREATE_CHAR_DEVICE:
case CREATE_BLOCK_DEVICE:
case IGNORE_PATH:
case IGNORE_DIRECTORY_PATH:
case ADJUST_MODE:
case RELABEL_PATH:
case RECURSIVE_RELABEL_PATH:
case WRITE_FILE:
case COPY_FILES:
case SET_XATTR:
case RECURSIVE_SET_XATTR:
case SET_ACL:
case RECURSIVE_SET_ACL:
case SET_ATTRIBUTE:
case RECURSIVE_SET_ATTRIBUTE:
break;
case REMOVE_PATH:
case TRUNCATE_DIRECTORY:
case RECURSIVE_REMOVE_PATH:
r = glob_item(i, remove_item_instance, false);
break;
}
return glob_item(i, remove_item_instance, false);
return r;
default:
return 0;
}
}
static int clean_item_instance(Item *i, const char* instance) {
@@ -1630,8 +1607,6 @@ static int clean_item_instance(Item *i, const char* instance) {
}
static int clean_item(Item *i) {
int r = 0;
assert(i);
log_debug("Running clean action for entry %c %s", (char) i->type, i->path);
@@ -1641,19 +1616,17 @@ static int clean_item(Item *i) {
case CREATE_SUBVOLUME:
case CREATE_SUBVOLUME_INHERIT_QUOTA:
case CREATE_SUBVOLUME_NEW_QUOTA:
case EMPTY_DIRECTORY:
case TRUNCATE_DIRECTORY:
case IGNORE_PATH:
case COPY_FILES:
clean_item_instance(i, i->path);
break;
return 0;
case IGNORE_DIRECTORY_PATH:
r = glob_item(i, clean_item_instance, false);
break;
return glob_item(i, clean_item_instance, false);
default:
break;
return 0;
}
return r;
}
static int process_item_array(ItemArray *array);
@@ -1879,6 +1852,7 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
case CREATE_SUBVOLUME:
case CREATE_SUBVOLUME_INHERIT_QUOTA:
case CREATE_SUBVOLUME_NEW_QUOTA:
case EMPTY_DIRECTORY:
case TRUNCATE_DIRECTORY:
case CREATE_FIFO:
case IGNORE_PATH:
@@ -2198,7 +2172,8 @@ static int parse_argv(int argc, char *argv[]) {
}
static int read_config_file(const char *fn, bool ignore_enoent) {
_cleanup_fclose_ FILE *f = NULL;
_cleanup_fclose_ FILE *_f = NULL;
FILE *f;
char line[LINE_MAX];
Iterator iterator;
unsigned v = 0;
@@ -2207,16 +2182,23 @@ static int read_config_file(const char *fn, bool ignore_enoent) {
assert(fn);
r = search_and_fopen_nulstr(fn, "re", arg_root, conf_file_dirs, &f);
if (r < 0) {
if (ignore_enoent && r == -ENOENT) {
log_debug_errno(r, "Failed to open \"%s\": %m", fn);
return 0;
}
if (streq(fn, "-")) {
log_debug("Reading config from stdin.");
fn = "<stdin>";
f = stdin;
} else {
r = search_and_fopen_nulstr(fn, "re", arg_root, conf_file_dirs, &_f);
if (r < 0) {
if (ignore_enoent && r == -ENOENT) {
log_debug_errno(r, "Failed to open \"%s\", ignoring: %m", fn);
return 0;
}
return log_error_errno(r, "Failed to open '%s', ignoring: %m", fn);
return log_error_errno(r, "Failed to open '%s': %m", fn);
}
log_debug("Reading config file \"%s\".", fn);
f = _f;
}
log_debug("Reading config file \"%s\".", fn);
FOREACH_LINE(line, f, break) {
char *l;