]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
log: skip reading the kernel command line if the process is invoked by a script 18375/head
authorYu Watanabe <watanabe.yu+github@gmail.com>
Tue, 26 Jan 2021 07:12:41 +0000 (16:12 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Sun, 31 Jan 2021 16:19:57 +0000 (01:19 +0900)
CLI tools may be used in a script. E.g., a script for monitoring a
service may use `systemctl`. Previously, if the kernel command line has
e.g. systemd.log-level=debug, then systemctl in the script produces
debugging logs when the script is invoked by a .service unit, but does
not when the script is running in a terminal. Then,
https://github.com/systemd/systemd/pull/18281#discussion_r561697482,
> I expect users to be (negatively) surprised.

In the previous commit, $SYSTEMD_EXEC_PID= is introduced. Then, we can
now detect whether a command is directly invoked by systemd or through
a script. Let's skip reading the kernel command line when a command is
invoked through a script.

src/basic/log.c

index f2cd1c30410568d2d5667e7430eb0937fe46dd6d..6a86fab3986c88299b370e7ab0fd446102aaa700 100644 (file)
@@ -1157,15 +1157,37 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
         return 0;
 }
 
+static bool should_parse_proc_cmdline(void) {
+        const char *e;
+        pid_t p;
+
+        /* PID1 always reads the kernel command line. */
+        if (getpid_cached() == 1)
+                return true;
+
+        /* If the process is directly executed by PID1 (e.g. ExecStart= or generator), systemd-importd,
+         * or systemd-homed, then $SYSTEMD_EXEC_PID= is set, and read the command line. */
+        e = getenv("SYSTEMD_EXEC_PID");
+        if (!e)
+                return false;
+
+        if (streq(e, "*"))
+                /* For testing. */
+                return true;
+
+        if (parse_pid(e, &p) < 0)
+                /* We know that systemd sets the variable correctly. Something else must have set it. */
+                log_debug("Failed to parse \"$SYSTEMD_EXEC_PID=%s\". Ignoring.", e);
+
+        return getpid_cached() == p;
+}
+
 void log_parse_environment(void) {
         const char *e;
 
         /* Do not call from library code. */
 
-        if (getpid_cached() == 1 || get_ctty_devnr(0, NULL) < 0)
-                /* Only try to read the command line in daemons. We assume that anything that has a
-                 * controlling tty is user stuff. For PID1 we do a special check in case it hasn't
-                 * closed the console yet. */
+        if (should_parse_proc_cmdline())
                 (void) proc_cmdline_parse(parse_proc_cmdline_item, NULL, PROC_CMDLINE_STRIP_RD_PREFIX);
 
         e = getenv("SYSTEMD_LOG_TARGET");