Search code examples
linuxbashmultilineubuntu-18.04

Run some commands as one user, and access variables set by another user


What I'm aiming for:

I want to run:

  1. multiple lines at once
  2. under another user
  3. with access to the variables set by the user I'm running from

So from this:

ROOT_VAR='var-set-from-root'

cmd="
 echo $ROOT_VAR
 echo `whoami`
 echo $HOME
"

the DESIRED RESULT would be:

var-set-from-root
UserA
/home/UserA

What I've tried so far:

1 run with bash; commands contained in double quotes:

cmd="
 echo $ROOT_VAR
 echo `whoami`
 echo $HOME
"

sudo -u UserA bash -c "{$cmd}"

# result (has access to root var but still running as root):
var-set-from-root
root
/root

2 run with bash with commands in heredoc

sudo -u UserA bash -c<<EOF
 echo $ROOT_VAR
 echo `whoami`
 echo $HOME
EOF

# result (error):
bash: -c: option requires an argument

3 run with su and commands in heredoc with single quote

su UserA <<'EOF'
 echo $ROOT_VAR
 echo `whoami`
 echo $HOME
EOF

# result (no access to root var but running as correct user):

UserA
/home/UserA

4 run with su and commands in heredoc without quotes

su UserA <<EOF
 echo $ROOT_VAR
 echo `whoami`
 echo $HOME
EOF

# result (has access to root var but still running as root):
var-set-from-root
root
/root

5 run with bash; commands in double quotes; root var passed as param:

cmd="
 echo $1
 echo `whoami`
 echo $HOME
"

sudo -u UserA bash -c "{$cmd}" $ROOT_VAR

# result (no access to root variable parameter):

root
/root

None of them can access the variable set from the root user while at the same time running under the non-root user. Is it possible even by using parameters?


Solution

  • A slight modification of your first example should work:

    cmd="
     echo $ROOT_VAR
     echo \`whoami\`
     echo \$HOME
    "
    
    sudo -H -u UserA bash -c "{$cmd}"
    

    -H is needed to set the $HOME variable of the user based on this.

    Regarding the backslashes, the distinction here between \$HOME and $ROOT_VAR is quite tricky. When the command is parsed, $ROOT_VAR is actually expanded to it's real value. In other words, the value of cmd is the following:

    cmd="
      echo var-set-from-root
      echo `whoami`
      echo $HOME
    "
    

    You need to use backslashes to avoid parsing of whoami and $HOME in the root's environment and instead pass on the execution of the command to the user's bash itself.