I basically need to do this:

DUMMY=dummy
sudo su - ec2-user -c 'echo $DUMMY'

This doesn't work. How can I pass the env variable $DUMMY to su? -p doesn't work with -l.

up vote 30 down vote accepted

You can do it without calling login shell:

sudo DUMMY=dummy su ec2-user -c 'echo "$DUMMY"'

or:

sudo DUMMY=dummy su -p - ec2-user -c 'echo "$DUMMY"'

The -p option of su command preserve environment variables.

  • 3
    I think "-E" preserves environment variables sudo.ws/man/sudo.man.html – Andy May 9 '15 at 8:42
  • 1
    @Andy But it's often forbidden by the sudo configuration. – Gilles May 9 '15 at 16:10
  • @cuonglm - thanks. This works. Shouldn't have called the login shell. – Umang May 11 '15 at 5:26
  • 1
    @kenorb: No, -p is option of su, not sudo in this case – cuonglm Dec 24 '15 at 1:43

Pro tip: There is never really a good reason to run sudo su. To run a command as a different user, use sudo -u username command. If you want a root shell, run sudo -i or sudo -l. If you have activated the root account, you can also run su alone, but sudo su is just not useful. And yes, I know you see it everywhere.

That said, sudo has the -E switch which will preserve the environment of the user's session:

 -E, --preserve-env
        Indicates to the security policy that the user wishes to preserve 
        their existing environment variables.  The security policy may
        return an error if the user does not have permission to 
        preserve the environment.

So, you will first need to export your variable, and then run sudo -E:

$ export DUMMY=dummy
$ sudo -Eu bob bash -c 'echo $DUMMY'
dummy

The bash -c is not needed. However, if I run sudo -Eu bob echo "$DUMMY", the variable is expanded before the root shell is launched so it doesn't demonstrate that the command actually works:

$ sudo -u bob echo $DUMMY  ## looks like it works but doesn't
dummy
$ sudo -u bob bash -c 'echo D:$DUMMY' ## now we see it failed
D:
$ sudo -Eu bob bash -c 'echo D:$DUMMY'  ## works as expected
D:dummy
  • 2
    A better way to preserve an environment variable is to add it to env_keep in sudoers. Perhaps like this: Defaults env_keep += "DUMMY". – lcd047 May 9 '15 at 9:58
  • @lcd047 but that will preserve the environment for all invocations of sudo. It is also more cumbersome for a single variable. That is only useful for something that should always be exported. – terdon May 9 '15 at 11:37
  • Yes, it's a trade-off, but not all environment variables are equally harmful. There's a substantial difference between carrying over LD_PRELOAD and carrying over LESSCHARDEF. I don't think convenience should be the winning argument here... – lcd047 May 9 '15 at 13:54
  • @lcd047 your suggestion is certainly worth posting as an answer. My point is that it's not practical for exporting arbitrary variables. Yes, if there's a specific variable you always want exported, that's the way to go but not if you want to do this once and for a variable defined in the same session. – terdon May 9 '15 at 17:24

-E does the job for me. From man sudo -

-E, --preserve-env
Indicates to the security policy that the user wishes to pre‐ serve their existing environment variables. The security policy may return an error if the user does not have permis‐ sion to preserve the environment.

  • Unfortunately it will only do the job if your admin did not restrict you from using -E. – TorstenS Aug 16 '17 at 10:12

What follows is a solution that does not need one to change the security policy.

I will ignore the su part, as we can use the --user option of sudo.

We want to pass environment variables to a command run via sudo. However sudo will not allow environment variables to be passed to a command (there are valid security reason for this, some variables can be dangerous). A shell can be used to set environment variables, and sudo can run a shell with a script passed to it. Therefore tell sudo to run a script that sets the environment variables.

var_a=someThing
var_b=someOtherThing

sudo bash -c "
    export var_a=\"${var_a}\"
    export var_b=\"${var_b}\"

    the_command some_args
"

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.