Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to write a shell script that runs some commands as superuser and some commands not as superuser, without having to babysit it?

Tags:

unix

sudo

I want to write a shell script to automate a series of commands. The problem is some commands MUST be run as superuser and some commands MUST NOT be run as superuser. What I have done so far is something like this:

#!/bin/bash  command1 sudo command2 command3 sudo command4 

The problem is, this means somebody has to wait until command1 finishes before they are prompted for a password, then, if command3 takes long enough, they will then have to wait for command3 to finish. It would be nice if the person could get up and walk away, then come back an hour later and be done. For example, the following script has this problem:

#!/bin/bash  sleep 310 sudo echo "Hi, I'm root" sleep 310 sudo echo "I'm still root?" 

How can I make it so that the user can just enter their password once, at the very start, and then walk away?

Update:

Thanks for the responses. I'm running on Mac OS X Lion and ran Stephen P's script and got different results: (I also added $HOME)

pair@abbey scratch$ ./test2.sh uid is 501 user is pair username is  home directory is /Users/pair pair@abbey scratch$ sudo ./test2.sh  Password: uid is 0 user is root username is root home directory is /Users/pair 
like image 366
speedarius Avatar asked Apr 19 '12 00:04

speedarius


People also ask

How do I run a shell script as a root user?

To give root privileges to a user while executing a shell script, we can use the sudo bash command with the shebang. This will run the shell script as a root user. Example: #!/usr/bin/sudo bash ....

What does $() mean in shell script?

$() – the command substitution. ${} – the parameter substitution/variable expansion.


2 Answers

File sutest

#!/bin/bash echo "uid is ${UID}" echo "user is ${USER}" echo "username is ${USERNAME}" 

run it: `./sutest' gives me

uid is 500 user is stephenp username is stephenp 

but using sudo: sudo ./sutest gives

uid is 0 user is root username is stephenp 

So you retain the original user name in $USERNAME when running as sudo. This leads to a solution similar to what others posted:

#!/bin/bash sudo -u ${USERNAME} normal_command_1 root_command_1 root_command_2 sudo -u ${USERNAME} normal_command_2 # etc. 

Just sudo to invoke your script in the first place, it will prompt for the password once.


I originally wrote this answer on Linux, which does have some differences with OS X

OS X (I'm testing this on Mountain Lion 10.8.3) has an environment variable SUDO_USER when you're running sudo, which can be used in place of USERNAME above, or to be more cross-platform the script could check to see if SUDO_USER is set and use it if so, or use USERNAME if that's set.

Changing the original script for OS X, it becomes...

#!/bin/bash sudo -u ${SUDO_USER} normal_command_1 root_command_1 root_command_2 sudo -u ${SUDO_USER} normal_command_2 # etc. 

A first stab at making it cross-platform could be...

#!/bin/bash # # set "THE_USER" to SUDO_USER if that's set, #  else set it to USERNAME if THAT is set, #   else set it to the string "unknown" # should probably then test to see if it's "unknown" # THE_USER=${SUDO_USER:-${USERNAME:-unknown}}  sudo -u ${THE_USER} normal_command_1 root_command_1 root_command_2 sudo -u ${THE_USER} normal_command_2 # etc. 
like image 117
Stephen P Avatar answered Sep 30 '22 20:09

Stephen P


You should run your entire script as superuser. If you want to run some command as non-superuser, use "-u" option of sudo:

#!/bin/bash  sudo -u username command1 command2 sudo -u username command3 command4 

When running as root, sudo doesn't ask for a password.

like image 39
Pavel Strakhov Avatar answered Sep 30 '22 21:09

Pavel Strakhov