Search code examples
bashsudo

Why sudo -H needs an extra command?


I found this related question What does sudo -H do? that demonstrates the usage of -H with

sudo -H bash -c 'echo $HOME $USER'

But I don't understand is why is bash necessary, because the echo command can stand on its own, but running

sudo -H echo $HOME $USER

will display instead current user variables (and not root's).

So why is (in this case) bash needed for the commands ran as sudo arguments to take in the -H flag?

This is also true if one specifies another user, like sudo -H -u anotheruser echo $HOME $USER.


Solution

  • When you run the command:

    sudo -H echo $HOME $USER 
    

    the variables $HOME and $USER are evaluated by the current shell. They are replaced with their values and the command line adjusted this way is passed to sudo.

    F.e. if your username is foo and your home is /home/foo, the command above is the same thing as:

    sudo -H echo /home/foo foo
    

    It's not necessarily bash that is required to get what you want. It's required a way to evaluate the environment variables by the command that is executed by sudo, not by the current shell.

    When you run:

     sudo -H bash -c 'echo $HOME $USER'
    

    the $HOME and $USER environment variables are not evaluated by the current shell, because they are enclosed in single quotes.

    sudo receives the command line as it is written here (it's fourth argument is the string echo $HOME $USER as a single word). It then launches bash with two arguments: -c and the string mentioned above.

    bash interprets -c as "execute a command" that is provided as the next argument. It then tries to run echo $HOME $USER (notice that the variables are not enclosed in quotes here) and, before running echo it replaces $HOME and $USER with their values (that belong to the new user now).

    Running bash (or any other shell) is needed to do the variables expansion in the execution environment of the new user.