5

I am trying to make sure when a script is run it is run as a specific user without having to su to that user before the script is run. Also the script is run with a couple of flags for example

./myscript.sh -e dev -v 1.9

I have tried the following

[ `whoami` = myuser ] || exec sudo -S su - myuser -c "bash `pwd`/`basename $0` $@"

But the -v flag which is supposed to be an input to my script is being fed as input to su. So it complains of an invalid option, is there a way to correct the above?

NB: The person running the script has sudo privileges.

7
  • 3
    The [ and ] must have spaces after and before them, respectively. Why do you need sudo su? Is not sudo enough? Do you really need to start an interactive or login shell? And if the user has sudo access, why use -S (used for passing a password over standard input)? Related: Is there ever a good reason to run sudo su?
    – Kusalananda
    Jun 10, 2019 at 8:36
  • The spaces was a typo. And I've found with just sudo su it asks for password input whereas -S doesn't
    – PDStat
    Jun 10, 2019 at 8:40
  • No, it still asks for one with -S, that just allows you to do something like echo password | sudo -S command. If it didn't ask for a password, that's because you've recently run another sudo command so it still remembers the password. Run sudo -k to forget it and try again and it will ask for a password.
    – terdon
    Jun 10, 2019 at 8:45
  • As per my comment to terdon it looks like the sudoers file is set to not require a password prompt for su. That isn't the case however for doing an su from a script, it still prompts unless I use -S
    – PDStat
    Jun 10, 2019 at 8:59
  • 1
    @Kusalananda no, but you can set up su to be run with sudo su without needing a password through sudoers. That said, I have absolutely no idea how or why the -S flag could possibly be relevant.
    – terdon
    Jun 10, 2019 at 9:03

3 Answers 3

6

The current user is already in the variable $USER. So all you need is:

[ "$USER" = "myuser" ] || sudo -u myuser $0 "$@"

There is no need for sudo su, sudo can do everything you require. You also don't need pwd or basename, the $0 variable already has the full path to the script.

Your original command was starting a login shell (su -). If that's really needed (which seems strange), you can do:

[ "$USER" = "myuser" ] || sudo -iu myuser $0 "$@"
5
  • Doing just sudo -u myuser will ask for the password. I don't wish for this to happen
    – PDStat
    Jun 10, 2019 at 8:51
  • @PDStat How do you wish to provide the password (which has to be provided)?
    – Kusalananda
    Jun 10, 2019 at 8:53
  • 1
    @PDStat there is no option of sudo or su that will let you do this without a password. Your approach also asks for a password. If it didn't that's because your user had already authenticated. Try running sudo -k and then your command again and you'll see it will ask for a password. If you really need to do it without a password, you will need to set that up in the sudoers file.
    – terdon
    Jun 10, 2019 at 8:53
  • It looks like the sudoers files is already set like that as I can do sudo -k followed by sudo su - myuser without the prompt for a password. That's not the case however from a script without the -S flag.
    – PDStat
    Jun 10, 2019 at 8:58
  • 1
    @PDStat that... makes no sense to me. I believe you, I just don't have any idea how that could possibly happen. I cannot imagine how the -S would ever be relevant.
    – terdon
    Jun 10, 2019 at 9:05
3

There are two problems with your script:

1) You forgot the spaces in the test command [`whoami` = myuser]

2) Due to the expansion of the variable "$@" in two steps the quoting is lost.

The following seems to work on my system:

[ `whoami` = myuser ] || exec sudo -S -u myuser bash -- "$0" "$@"
2
  • This just gives me invalid option: --e
    – PDStat
    Jun 10, 2019 at 9:12
  • @PDStat: Try with the updated version, if it doesn't work edit your question with the entire script you are running, it could be a problem somewhere else.
    – user000001
    Jun 10, 2019 at 9:17
3

If the whole script would need to be run by a specific user, then I would leave it up to the user running the script to arrange with changing into the correct user identity in any way that they see fit (whether through su, sudo, or some other means).

This would simplify your script and would make it easier to use. In particular, it would avoid having to "correct" for the inability of the user to assume the right identity. Personally, I would treat this as an error in its invocation, similar to failing to use the correct command line options.

The script could still check to make sure that it's being run by the correct user, obviously:

if [ "$USER" != "correctuser" ]; then
    echo 'Must be run by "correctuser"' >&2
    exit 1
fi

An ordinary user would then run the script using

sudo -u correctuser ./script.sh -e dev -v 1.9

while the root user may want to do

su correctuser -c ./script.sh -e dev -v 1.9

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .