Running interactive shell script in name of other user - bash

In my shell script (bash) I want to call other shell scripts. I run my script as user_A.
One of these scripts needs special handling:
It has to be run as different user
(user_B). Password needed here.
It is interactive, but not only asks
questions but runs another script in
name of another user (user_C) using
su. I have to enter a password here
as well.
I can use su calling this script but its questions have to be answered somehow. I can not enter anything because it prints for each questons "stty: : Not a typewriter"
I'm calling the special script this way
su user_B << ABC
...
special_script
...
ABC

#!/bin/bash
main_for_root(){
:
}
# ------------------------------------------------------------------------------
abs_path="$(readlink -f `dirname $0`)/$(basename $0)"
# if [ `id -u` != 0 ] ; then
if [ `whoami` != 'root' ] ; then
echo "[su -] run as root"
su -c"/bin/bash $abs_path $#"
exit 0
else
main_for_root $#
fi
It works for 1 user, so now add 'if ...' for second user

Another option for running scripts as other users is the 'sudo' command, think of it as 'superuser do:' for readability purposes. The -u parameter gives username information. So:
sudo -u user_B special_script
Will prompt for the password for user_B. I've never had a problem with running interactive programs using it. You can manage who can sudo to whom via the visudo command.

You can use sudo and create a sudoers file which allows user_A to run the script as user_B.
a line like:
user_A ALL = (user_B) NOPASSWD: /usr/share/stuff/ABC
would allow user_A to do something like
sudo -u user_B /usr/share/stuff/ABC
without asking for a password

su attempts to get a password from the terminal and needs a tty device so it can call ioctl to turn off key echoing. Since the standard input is coming from a "here document" (ABC), an attempt to call the ioctl on file descriptor 0 yields "not a tty".
If you must use a here document instead of a bona fide script, do:
cat > /tmp/myscript.$$ <<ABC
#!/bin/sh
...
ABC
chmod +x /tmp/myscript.$$
sudo -u user_B /tmp/myscript.$$

You may want to use expect. Its designed for scripted interaction.

Related

Usage of sudo in a shell script

When executing a shell script, how does sudo come into play in the following?
# script.sh
ls /root
sudo ls /root
Now, if I run $ sudo ./script.sh or $ ./script.sh what will be the difference? For example:
Do all commands that are run with sudo ./script.sh automatically prepend a "sudo" to that command?
Is the sudo ls /root line vlid? Or should the line instead of ls /root and require root invocation?
Basically, I'm trying to figure out the difference in a line-item being run as sudo, or the script itself being run as sudo.
If you have a script that requires elevated privileges for certain commands, one way to handle those commands is with sudo. Before using sudo, there are several considerations for configuring its use. For instance, if you have certain users you want to be able to run commands with sudo and further to run sudo without being prompted for a password, you need a bit of configuration first. sudo is configured through the visudo utility. For most uses of sudo you will simply need to uncomment options at the end of the file. However to allow users to run sudo without a password, you will also need to add those users to the wheel group (some distros now use a sudo group -- check). After adding users to the wheel group, to allow them to use sudo without a password, you would run visudo and uncomment the following line:
## Same thing without a password
%wheel ALL=(ALL) NOPASSWD: ALL
With sudo configured, then within a script, if elevated (root) privileges are needed you simply need to check whether the user UID (and/or EUID) are equal to zero indicating the user is root, if not, then you use sudo to run the command. You can structure the test in the negative or in the positive to fit your taste, e.g.
if [ "$UID" -eq 0 -o "$EUID" -eq 0 ]; then
command
else
sudo command
fi
or
if [ "$UID" -ne 0 -a "$EUID" -ne 0 ]; then
sudo command
else
command
fi
If your command is not a simple command, but instead contains redirections or pipelines, then you must run the entire command with sudo not just the first command in the list. To do so, just use sudo bash -c "your long command" to ensure elevated privileges are available to each part of a compound command that needs it. For example if you attempt:
sudo cat /etc/sudoers > sudoersbackup
The command will fail. While cat has the elevated privileges to read the file the > redirection is run as the regular user and will fail due to lack of permission. To handle that circumstance, you can do:
sudo bash -c "cat /etc/sudoers > sudoersbackup"
That ensures elevated privileges are available to the entire command.
SUDO stands for "super user do". Basically it is a keyword that when prefixed before any other command, will force that command to run with elevated privileges. Certain commands require elevated privileges. There should be a file located at /etc/sudoers which provides a list of users or user groups who have permission to execute privileged commands.
So if your shell script requires no special privileges to run (which I expect it does not), then sudo ./script.sh should be equivalent to bash script.sh or ./script.sh.

Running some parts of the script with root and other parts with normal user

To make sure my bash script runs as root I use:
if [ "$UID" -ne "0" ]; then
echo "You must root to run $0. Try following"
echo "sudo $0"
exit 9
fi
But in the script, there some commands that I want to run with sudo -u $USER, however, if I run the whole script as root it comes out as sudo -u root ($USER will be root, not the original USER).
How do I run the script as root but also run certain commands in the script as the default logged in user so I don't have to put in the password or do chmod to change permissions?
You need the non-evaluated user in some variable.
How you want to do this depends on your actual use case.
You can look at:
Nasty temp file:
echo "$USER" > /tmp/thatsme.tmp
su -
# Hmm, now hope nobody has changed the tmpfile doing the same trick
orguser=$(cat /tmp/thatsme.tmp)
rm /tmp/thatsme.tmp
Keep environment
export orguser="$USER"
su # Not su -
echo "orguser=${orguser}"
Proces ps -ef and look for original user on the same tty you are on. (not recommended)
Call su - -c script additional parameter and change your master script that it pulls the user from $1.
Within your bash script you'll need to use the 'su' command to switch user, then the -c command with your needed command/script.
If you run as root you won't need to put in the $USER password.
Example: su $USER -c "command"

How to switch users with script to run another script

I have a script that will be executed as root, part way through the script I would like to switch to a user (say, bob) and execute another script using that user's environment. At the end of the script I want to switch back to root and execute more commands. I would like to run this script without having to enter the password for bob.
This script will be provided to my AWS EC2 instance via the user-data feature at first time bootup.
I thought the way to do this was to use either sudo or su. However, I don't appear to have access to bob's environment with either of these methods.
In the stdout echo below, you'll see that the environment variable myvar is initialized to Inara but when this script is executed with sudo, that value is unset....
dave#bugbear:~/workspaces/sandbox$ su --login bob
Password:
bob#bugbear:~$ cat bin/echo.sh
#!/bin/bash
echo "In echo.sh.. myvar is {$myvar}"
echo "Now executing the ruby script"
. ~/.bashrc
~/bin/echo.rb
bob#bugbear:~$ cat bin/echo.rb
#!/usr/bin/env ruby
puts "$myvar is: #{ENV['myvar']}"
bob#bugbear:~$ bin/echo.sh
In echo.sh.. myvar is {Inara}
Now executing the ruby script
$myvar is: Inara
bob#bugbear:~$ exit
logout
dave#bugbear:~/workspaces/sandbox$ cat test.sh
#!/bin/bash
stty echo
sudo --login -u bob bin/echo.sh
dave#bugbear:~/workspaces/sandbox$ ./test.sh
In echo.sh.. myvar is {}
Now executing the ruby script
$myvar is:
You are probably looking for one of these:
Simulate the -i initial environment of -u user bob:
sudo -i -u bob [command]
Or, use sudo to gain the required privilege to use su and ask it to - start a login shell as bob (without the bare - you're not doing that) and -c run a command:
sudo su - bob -c [command]

Bash script : Login to postgres home from shell script

I have to take a data dump from my postgres database.
How do I log in to the postgres home ? . I have the following script but it doesn't work :
#!/bin/sh$
export PASSWORD= something
echo $PASSWORD | sudo -S su postgres
pg_dump somedb > dump.txt+`date +%Y-%m-%d`
However when I run this script I do not get logged to postgres#gauss:$ at the same time script doesn't throw an error. Is there something I am doing wrong here ?
The reason your script fails is that the line
echo $PASSWORD | sudo -S su postgres
causes su to fork a subordinate shell. That shell tries to read from the standard input which has already been exhausted by sudo -S in reading the password. When the shell finds no more input (EOF) it exits. The next line of your script then executes as if that quoted line never happened, and therefore runs under your UID.
See j.hloetzek's answer for a much better way to do what you want.
Also the script as pasted has a two syntax errors in it, but you shouldn't use that approach anyway.
You cannot pipe the password to the sudo command, but can allow in /etc/sudoers certain commands to be run without password (check exact syntax!)
username YOURUSERNAME = NOPASSWD: /sbin/su postgres

Changing to root user inside shell script

I have a shell script which needs non-root user account to run certain commands and then change the user to root to run the rest of the script. I am using SUSE11.
I have used expect to automate the password prompt. But when I use
spawn su -
and the command gets executed, the prompt comes back with root and the rest of the script does not execute.
Eg.
< non-root commands>
spawn su -
<root commands>
But after su - the prompt returns back with user as root.
How to execute the remaining of the script.
The sudo -S option does not help as it does not run sudo -S ifconfig command which I need to find the IP address of the machine.
I have already gone through these links but could not find a solution:
Change script directory to user's homedir in a shell script
Changing unix user in a shell script
sudo will work here but you need to change your script a little bit:
$ cat 1.sh
id
sudo -s <<EOF
echo Now i am root
id
echo "yes!"
EOF
$ bash 1.sh
uid=1000(igor) gid=1000(igor) groups=1000(igor),29(audio),44(video),124(fuse)
Now i am root
uid=0(root) gid=0(root) groups=0(root)
yes!
You need to run your command in <<EOF block and give the block to sudo.
If you want, you can use su, of course. But you need to run it using expect/pexpect that will enter password for you.
But even in case you could manage to enter the password automatically (or switch it off) this construction would not work:
user-command
su
root-command
In this case root-command will be executed with user, not with root privileges, because it will be executed after su will be finished (su opens a new shell, not changes uid of the current shell). You can use the same trick here of course:
su -c 'sh -s' <<EOF
# list of root commands
EOF
But now you have the same as with sudo.
There is an easy way to do it without a second script. Just put this at the start of your file:
if [ "$(whoami)" != "root" ]
then
sudo su -s "$0"
exit
fi
Then it will automatically run itself as root. Of course, this assumes that you can sudo su without having to provide a password - but that's out of scope of this answer; see one of the other questions about using sudo in shell scripts for how to do that.
Short version: create a block to enclose all commands to be run as root.
For example, I created a script to run a command from a root subdirectory, the segment goes like this:
sudo su - <<EOF
cd rootSubFolder/subfolder
./commandtoRun
EOF
Also, note that if you are changing to "root" user inside a shell script like below one, few Linux utilities like awk for data extraction or defining even a simple shell variable etc will behave weirdly.
To resolve this simply quote the whole document by using <<'EOF' in place of EOF.
sudo -i <<'EOF'
ls
echo "I am root now"
EOF
The easiest way to do that would be to create a least two scripts.
The first one should call the second one with root privileges. So every command you execute in the second script would be executed as root.
For example:
runasroot.sh
sudo su-c'./scriptname.sh'
scriptname.sh
apt-get install mysql-server-5.5
or whatever you need.

Resources