systemd is not a shell, so it does not support shell-specific substitutions in environment files. Their format is simply KEY=VALUE
, with possible empty lines and comments in between.
To quote systemd.exec(5):
Settings from these files override settings made with Environment=. If the same variable is set twice from these files, the files will be read in the order they are specified and the later setting will override the earlier setting.
So, you can accomplish your task by either:
using multiple EnvironmentFile=
directives (they override each other in the order of specification)
using Environment=
in the service file to specify default values (any EnvironmentFile=
will override it)
Then answer is that sudo
has a bug. First, the workaround: I put this in my /etc/sudoers.d/zabbix file
:
zabbix ALL=(root) NOPASSWD: /bin/env SHELL=/bin/sh /usr/local/bin/zabbix_raid_discovery
and now subcommands called from zabbix_raid_discovery
work.
A patch to fix this will be in sudo 1.8.15. From the maintainer, Todd Miller:
This is just a case of "it's always been like that". There's not
really a good reason for it. The diff below should make the behavior
match the documentation.
- todd
diff -r adb927ad5e86 plugins/sudoers/env.c
--- a/plugins/sudoers/env.c Tue Oct 06 09:33:27 2015 -0600
+++ b/plugins/sudoers/env.c Tue Oct 06 10:04:03 2015 -0600
@@ -939,8 +939,6 @@
CHECK_SETENV2("USERNAME", runas_pw->pw_name,
ISSET(didvar, DID_USERNAME), true);
} else {
- if (!ISSET(didvar, DID_SHELL))
- CHECK_SETENV2("SHELL", sudo_user.pw->pw_shell, false, true);
/* We will set LOGNAME later in the def_set_logname case. */
if (!def_set_logname) {
if (!ISSET(didvar, DID_LOGNAME))
@@ -984,6 +982,8 @@
if (!env_should_delete(*ep)) {
if (strncmp(*ep, "SUDO_PS1=", 9) == 0)
ps1 = *ep + 5;
+ else if (strncmp(*ep, "SHELL=", 6) == 0)
+ SET(didvar, DID_SHELL);
else if (strncmp(*ep, "PATH=", 5) == 0)
SET(didvar, DID_PATH);
else if (strncmp(*ep, "TERM=", 5) == 0)
@@ -1039,7 +1039,9 @@
if (reset_home)
CHECK_SETENV2("HOME", runas_pw->pw_dir, true, true);
- /* Provide default values for $TERM and $PATH if they are not set. */
+ /* Provide default values for $SHELL, $TERM and $PATH if not set. */
+ if (!ISSET(didvar, DID_SHELL))
+ CHECK_SETENV2("SHELL", runas_pw->pw_shell, false, false);
if (!ISSET(didvar, DID_TERM))
CHECK_PUTENV("TERM=unknown", false, false);
if (!ISSET(didvar, DID_PATH))
Best Answer
No, FOO=bar; does not export the variable into my environment
A var is set in the (present) environment only if it was previously exported:
A variable is set in the environment of a command when it is placed before the command. Like
foo=bar command
. And it only exists while the command runs.The var is not set for the command line (in the present shell):
Above, the value of
$foo
is replaced with nothing by the present running shell, thus: no output.Your command:
is converted to the actual string:
by the present running shell.
If, instead, you set the variable (in the present running shell) with
foo=bar
before running the command, the line will be converted to:A variable set to the environment of a command is erased when the command returns:
Except when the command is a builtin in some conditions/shells: