I am in Ubuntu 9.04. Is there a way to make part of a script run as a different (non-root) user? If it helps, the part to be run as a different user occurs at the end of the script.
-
1possible duplicate of Howto switch / chage user id witin a bash script to execute commands in the same script? – Dan Dascalescu Jul 11 '14 at 10:35
7 Answers
Use the sudo command in the script.
In the form:
sudo -u username command
the sudo command runs command as the user username.
If the script is being run as root, I don't think it will prompt for a password. Otherwise, this article discusses how to use sudo with password in one command line?, and this article discusses how to use sudo without password?
- 3,761
-
9This is nice and easy, but is there a way to do this for a group of commands instead of one at a time? – Andrew Dec 05 '13 at 23:08
-
2write a bash script, make it executable
chmod +x script.shand then justsudo -u username script.sh– 55651909-089b-4e04-9408-47c5bf Jun 11 '14 at 15:05 -
1@Andrew I was wondering this myself and the following worked for me: sudo -u ic sh -c 'cmd1 && cmd2' – Karussell May 29 '17 at 14:26
-
Also include the
ioption if you want to acquire the user's environment – neoDev Nov 21 '17 at 06:17
# I=like:
#test if running bash as a different user works
sudo -u nobody bash -c : && RUNAS="sudo -u nobody"
echo 1: $USER
#Runs bash with commands between '_' as nobody if possible
$RUNAS bash<<_
echo 2: \$USER
_
echo 3: $USER
# ./run
1: root
2: nobody
3: root
- 777
-
17
-
Manish explains in the suggested edit: https://superuser.com/review/suggested-edits/1095251 – AXE Labs Dec 22 '21 at 18:39
-
This answer is good, but the serverfault advice is slightly dangerous - would allow anyone to run anything as root! So I'm posting here because I can't format the comment.
I would recommend using visudo to give the permissions you need as precisely as you can. Type visudo and add a line like:
username hostname = NOPASSWD: /full/path/to/command1, full/path/to/command2
If you do need to run this same thing on many hosts, you could open it up with:
username ALL = NOPASSWD: /full/path/to/command1, full/path/to/command2
But I would **not* use either:
username ALL=(ALL) NOPASSWD: ALL
or username hostname = ALL
The sudoer man page has lots of gory details
- 14,583
-
Would it work for a command available to a particular user only ? – Manish Mathai Jan 09 '10 at 09:42
-
You can specify that only particular users can run the command (in the examples above, replace
usernamewith the username who should be able to run the command). If the executable you want to run is only executable by one particular user, that's fine too - just pass that username in thesudo -u username commandlineline of the script. – James Polley Jan 09 '10 at 10:31 -
@Manish. Yes. What the sudoers file says is "Allow this username on this host to run command1 without having to provide a password. – DaveParillo Jan 09 '10 at 17:23
This way, end of a script will be executed by different user (root).
Please note the $[LINENO+2] and exit $? calls. These are required to make the end of the script to execute just once and to preserve the exit code of the sudo call.
#!/bin/bash
echo $USER
# pipe the rest of this script via a sudo call
tail -n +$[LINENO+2] $0 | exec sudo bash
exit $?
echo $USER
exit 1
- 51
not so sure about it, but if you want that ONLY the end of that script will run as a different user, you could add su someuser before the end of the script.
Am I missing something?
Hope that helps,
Regards
- 1,934
-
1I think this is the most appropriate answer, having all other answers suggesting sudo, which is often not installed by default on some minimal linux installations. – Tim Jan 07 '18 at 03:04
-
5
su someuserwill start a new shell, it won't execute the rest of the script. – Just a student Feb 14 '20 at 15:43 -
1Yeah this won't work, it'll just go into a new shell then do nothing forever, the rest of the script won't be executed – Shardj Jan 25 '22 at 12:43
I had a similar need as the OP, I had a good sized shell script that needs to be run as root, but a good portion of which I need to have run as another user. My solution was to put the entire contents of script (both the part that needs to be run by root, and the part that needs to be run as "other_user") in an if/elif block:
if [ $USER = "other_user" ]
then
## Run commands as user other_user
:
exit
elif [ $USER = "root" ]
then
## Run some commands as root
:
## Next, run this script as other_user
sudo -i -u other_user $0 "$@"
## Then run more commands as root
:
else
## Nobody else should run this script
echo "Permission denied"
exit 1
fi
- 11