`sudo -u user` in shebang line

shebangsudo

I'd like to be able to run a script as another user, and only as that user.

The way I currently have this set up is to have

alice   ALL = (bob) NOPASSWD: /home/alice/script.sh

in the sudoers file and

alice@foo:~$ ls script.sh
-rwxr-xr-x  1 root  root ..... script.sh

alice@foo:~$ lsattr script.sh
----i----------- script.sh

alice@foo:~$ head -1 script.sh
#!/bin/bash

alice@foo:~$ sudo -u bob ./script.sh
ok

Is there a way to have the shebang line be something like

#!/usr/bin/sudo -u bob -- /bin/bash

so that alice could just run

alice@foo:~$ ./script.sh
ok

?

If I try this I simply get the error message

sudo: unknown user:  blog -- /bin/bash
sudo: unable to initialize policy plugin  

Best Answer

Linux (like many other Unix variants) only supports passing a single argument to the interpreter of a script. (The interpreter is the program on the shebang line.) A script starting with #!/usr/bin/sudo -u bob -- /bin/bash is executed by calling /usr/bin/sudo with the arguments -u bob -- /bin/bash and /home/alice/script.sh.

One solution is to use a wrapper script: make /home/alice/script.sh contain

#!/bin/sh
exec sudo -u bob /home/alice/script.real

and put the code in /home/alice.script.real starting with #!/bin/bash and make the sudo rule refer to /home/alice.script.real.

Another solution is to make the script reexecute itself. You need to be careful to detect the desirable condition properly, otherwise you risk creating an infinite loop.

#!/bin/bash
if ((EUID != 123)); then
  exec sudo -u \#123 /home/alice/script.sh
fi

(where 123 is the user ID of bob)

A simple solution is to tell people to run sudo -u bob /home/alice/script.sh instead of running the script directly. You can provide shell aliases, .desktop files, etc.

Related Question