[systemd-devel] [PATCH V2] service: Support environment variable substition for PIDFile=

harald at redhat.com harald at redhat.com
Wed Apr 10 06:35:55 PDT 2013


From: Harald Hoyer <harald at redhat.com>

RFE: https://bugzilla.redhat.com/show_bug.cgi?id=840260

$ cat test.service
[Unit]
Description=test

[Service]
PIDFile=${PIDFILE}
EnvironmentFile=/etc/test-file
ExecStart=/bin/bash -c 'sleep 10000& jobs -p > $$PIDFILE; exit 0'
Type=forking

$ cat /etc/test-file
PIDFILE=/tmp/test.pid

$ systemctl status test.service
test.service - test
Loaded: loaded (/usr/lib/systemd/system/test.service; static)
   Active: active (running) since Mi 2013-04-10 15:06:42 CEST; 2s ago
  Process: 22407 ExecStart=/bin/bash -c sleep 10000& jobs -p > $$PIDFILE; exit 0 (code=exited, status=0/SUCCESS)
 Main PID: 22408 (sleep)
   CGroup: name=systemd:/system/test.service
           └─22408 sleep 10000

Apr 10 15:06:42 lenovo systemd[1]: Started test.
---
 man/systemd.service.xml               |  3 +++
 src/core/load-fragment-gperf.gperf.m4 |  2 +-
 src/core/service.c                    | 27 ++++++++++++++++++++++-----
 src/core/service.h                    |  1 +
 4 files changed, 27 insertions(+), 6 deletions(-)

diff --git a/man/systemd.service.xml b/man/systemd.service.xml
index b82a5c1..14ce395 100644
--- a/man/systemd.service.xml
+++ b/man/systemd.service.xml
@@ -276,6 +276,9 @@
                                 the daemon after start-up of the
                                 service. systemd will not write to the
                                 file configured here.</para>
+                                <para>Basic environment variable
+                                substitution is supported like in
+                                <varname>ExecStart=</varname>.</para>
                                 </listitem>
                         </varlistentry>
 
diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4
index d5e579f..4592f3d 100644
--- a/src/core/load-fragment-gperf.gperf.m4
+++ b/src/core/load-fragment-gperf.gperf.m4
@@ -140,7 +140,7 @@ Unit.ConditionHost,              config_parse_unit_condition_string, CONDITION_H
 Unit.ConditionACPower,           config_parse_unit_condition_string, CONDITION_AC_POWER,            0
 Unit.ConditionNull,              config_parse_unit_condition_null,   0,                             0
 m4_dnl
-Service.PIDFile,                 config_parse_unit_path_printf,      0,                             offsetof(Service, pid_file)
+Service.PIDFile,                 config_parse_unit_string_printf,    0,                             offsetof(Service, pid_file)
 Service.ExecStartPre,            config_parse_exec,                  SERVICE_EXEC_START_PRE,        offsetof(Service, exec_command)
 Service.ExecStart,               config_parse_exec,                  SERVICE_EXEC_START,            offsetof(Service, exec_command)
 Service.ExecStartPost,           config_parse_exec,                  SERVICE_EXEC_START_POST,       offsetof(Service, exec_command)
diff --git a/src/core/service.c b/src/core/service.c
index a104b30..fd4c183 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -275,6 +275,9 @@ static void service_done(Unit *u) {
         free(s->pid_file);
         s->pid_file = NULL;
 
+        free(s->pid_file_env);
+        s->pid_file_env = NULL;
+
 #ifdef HAVE_SYSV_COMPAT
         free(s->sysv_runlevels);
         s->sysv_runlevels = NULL;
@@ -703,7 +706,9 @@ static int service_load_sysv_path(Service *s, const char *path) {
                                 }
 
                                 free(s->pid_file);
+                                free(s->pid_file_env);
                                 s->pid_file = fn;
+                                s->pid_file_env = NULL;
                         }
 
                 } else if (state == DESCRIPTION) {
@@ -1376,18 +1381,27 @@ static int service_load_pid_file(Service *s, bool may_warn) {
         char _cleanup_free_ *k = NULL;
         int r;
         pid_t pid;
+        char _cleanup_strv_free_ **context_env = NULL;
+        char _cleanup_free_ *fe = NULL;
 
         assert(s);
 
         if (!s->pid_file)
                 return -ENOENT;
 
-        r = read_one_line_file(s->pid_file, &k);
+        if (!s->pid_file_env)
+                if (!exec_context_load_environment(&s->exec_context, &context_env))
+                        s->pid_file_env = replace_env(s->pid_file, context_env);
+
+        if (!s->pid_file_env)
+                s->pid_file_env = strdup(s->pid_file);
+
+        r = read_one_line_file(s->pid_file_env, &k);
         if (r < 0) {
                 if (may_warn)
                         log_info_unit(UNIT(s)->id,
                                       "PID file %s not readable (yet?) after %s.",
-                                      s->pid_file, service_state_to_string(s->state));
+                                      s->pid_file_env, service_state_to_string(s->state));
                 return r;
         }
 
@@ -1396,7 +1410,7 @@ static int service_load_pid_file(Service *s, bool may_warn) {
                 if (may_warn)
                         log_info_unit(UNIT(s)->id,
                                       "Failed to read PID from file %s: %s",
-                                      s->pid_file, strerror(-r));
+                                      s->pid_file_env, strerror(-r));
                 return r;
         }
 
@@ -1404,7 +1418,7 @@ static int service_load_pid_file(Service *s, bool may_warn) {
                 if (may_warn)
                         log_info_unit(UNIT(s)->id,
                                       "PID %lu read from file %s does not exist.",
-                                      (unsigned long) pid, s->pid_file);
+                                      (unsigned long) pid, s->pid_file_env);
                 return -ESRCH;
         }
 
@@ -2874,7 +2888,10 @@ static int service_demand_pid_file(Service *s) {
         if (!ps)
                 return -ENOMEM;
 
-        ps->path = strdup(s->pid_file);
+        if (s->pid_file_env)
+                ps->path = strdup(s->pid_file_env);
+        else
+                ps->path = strdup(s->pid_file);
         if (!ps->path) {
                 free(ps);
                 return -ENOMEM;
diff --git a/src/core/service.h b/src/core/service.h
index d1e53bf..ae491a8 100644
--- a/src/core/service.h
+++ b/src/core/service.h
@@ -122,6 +122,7 @@ struct Service {
 
         /* If set we'll read the main daemon PID from this file */
         char *pid_file;
+        char *pid_file_env;
 
         usec_t restart_usec;
         usec_t timeout_start_usec;
-- 
1.8.2



More information about the systemd-devel mailing list