How to sudo as a different user inside a script? - unix

I have a wrapper script which calls two scripts aaa.sh and bbb.sh. These two scripts should be executed as different users as
sudo -H -u user1
. /user/bin/scripts/aaa.sh
sudo -H -u user1
. /user/bin/scripts/bbb.sh
but the sudo command can't be executed inside a script. Need help...

If you just want to switch users, you should use 'su' not sudo, right?
su user1 -c ./user/bin/scripts/aaa.sh
(that is unless you actually do need elevated privileges)

sudo can be used inside a script, but is the user that executes this script actually allowed to use sudo? Check your /etc/sudoers file.

sudo can be used only if the user name is mapped in /etc/sudoers file as mentioned above. But he may not have the complete priveleges as compared to su user.

Related

sudo asks for a password instead of getting it from stdin

I have a script running in an open terminal window:
while sleep 345600; \
do pass="$(security find-generic-password -w -s 'service' -a 'account')"; \
sudo --stdin <<< "${pass}" head /etc/hosts; \
done
When for a test I manually run this script having set sleep to 1, it works as intended, sudo getting the pass without user's interaction. When I then run the script with the 4 days delay, it does not run the same say in a specified time, sudo waiting for the password from a user's terminal (i.e. typed manually!). I can even set the pass variable to contain the actual plain-text password, of no avail.
Why this difference?
It's probably safer to add the particular command you need to the sudoers config and allow it to be run without a password (see https://apple.stackexchange.com/q/398656 for an example of this on macOS).
If that's not an option, you can try using the --askpass option: it takes the path to a command that will output the user's password on stdout when called. Put the find-generic-password command in a helper script and pass that to --askpass.

Switch user as well as environment variable in Unix Shell Script

I'm currently working on a script that logs into another user account using
su username -c "comand1; comand2"
There's no sudo command in the shell.
However the environment variables do not change.
For example, the work directories are different with different users. So when the user is switched in the script, I expect that the $HOME variable should contain different work directories.
Does anyone know how to solve this problem?
You are probably looking for the -l (or just -) option to make it a login shell. See the manual for su(1).
One hack-ish kind of way would be put all env variables of the second user in a file (like .bashrc) and source it first in the list of the commands:
su username -c "source file_name; comand1; comand2"
There are two issues:
First: If you user " to delimit the argument for -c then everything in this argument is expanded by the calling shell and not by the executed shell. You can use ' instead of " to prevent this.
Second: By default su does not perform the same steps as during a real user login. Use the -l or - options. This may be required in your case or not - just try it.
Together:
> echo $HOME
/root
> su -c "echo $HOME" user -l
/root
> su -c 'echo $HOME' user -l
/home/user
> su -c 'echo $HOME' user
/home/user

ssh login without any prompt

I have to login more then 150 sever and execute some unix commands.
The problem is, if I create a script which will run from one server and ssh login to 150 server and execute cmds and exit.
How can i login with any password prompt.
due to some reason i should not use ssh-keygen public and private key method , or use of some extra tool with bash line like "expect".
is there any normal way to do login through ssh in single command consisting username/password#servername like we have option in sqlplus and ftp.
There is a utility called sshpass that allows you to specify a password in the commandline.
Under Ubuntu/Debian install by using sudo apt-get install sshpass
sshpass -p 'abcedf' ssh joe#myserver.domain.com "df > ~/test; cat ~/test; rm ~/test;"
hope this helps
You can try setting up either ~/.shosts or /etc/ssh/shosts.equiv on each of your remote hosts. See man ssh under "AUTHENTICATION" for details.

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

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
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.
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.
If you use this, check man sudo too:
#!/bin/bash
sudo echo "Hi, I'm root"
sudo -u nobody echo "I'm nobody"
sudo -u 1000 touch /test_user
Well, you have some options.
You could configure sudo to not prompt for a password. This is not recommended, due to the security risks.
You could write an expect script to read the password and supply it to sudo when required, but that's clunky and fragile.
I would recommend designing the script to run as root and drop its privileges whenever they're not needed. Simply have it sudo -u someotheruser command for the commands that don't require root.
(If they have to run specifically as the user invoking the script, then you could have the script save the uid and invoke a second script via sudo with the id as an argument, so it knows who to su to..)

Shell script and sudo

In my shell script i have the following line:
export PATH=$PATH:/home/$USER/somedir
Say im logged in as user mike. I need to execute the shell script as root, so i run it as sudo filename.sh, so $USER becomes root in my path in that case.
I want it to be that of the user running the script, i.e. mike instead of root. Is there a way to achieve this?
Thank You
Do you have to use /home/$USER, or will $HOME do the trick? IIRC, sudo doesn't override the value of $HOME.
Use $SUDO_USER (if you insist on using $USER directly, set its value as shown):
$ cat script.sh
#!/bin/bash
if [ "$SUDO_USER" != "" ]; then
USER=$SUDO_USER;
fi
export PATH=$PATH:/home/$USER/somedir
Or cheat using $USER as the first parameter to the script (error checking is an exercise for the reader):
$ cat script.sh
#!/bin/bash
USER=$1
export PATH=$PATH:/home/$USER/somedir
Then:
$ sudo ./script.sh $USER
Or use $HOME, as suggested by Chris Jester-Young. You could use bash to remove the "/home/" prefix, but that would be an ugly hack.
If you're willing to use su instead of sudo, you can do
su -cp filename.sh
to execute the command while preserving your environment.
You can try using $UID, which should still be set to the user's real ID number and retrieving their name out of the password database based on that.
If you need to preserve environnement, you can use the -E option of sudo. But it needs some configuration and security politics ... That applies if the $HOME solution proposed by Chris JY does not apply as it is simpler.
my 2 cents
sudo is different form "root" user. If any user has sudo privileges, that means he has the admin rights that are available with the user "root". That is, using sudo doesn't change the user to root.

Resources