Changing to root user inside shell script
Asked Answered
C

6

26

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

Cowpoke answered 24/7, 2012 at 18:13 Comment(1)
If you are using bash, you can create a function and pass the definition to sudo: unix.stackexchange.com/questions/269078/…Proletariat
C
29

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.

Cerelia answered 24/7, 2012 at 18:20 Comment(0)
C
13

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.

Coldiron answered 7/8, 2015 at 8:14 Comment(4)
Be careful; "$0" may not be what you think it is.Quechua
@Quechua That is interesting, but I am making the assumption here that $0 is the command to start the current process, not the path to the current file, so it's a little less fragile. Still, a good point, and very helpful link.Coldiron
for password prompt just use echo $PASSWORD | sudo -S su -c "$0"Marasmus
maybe we should add exec in front of sudo to avoid creating another subprocess.Nels
K
6

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
Killdeer answered 12/11, 2018 at 19:31 Comment(0)
T
3

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
Tellus answered 25/12, 2019 at 5:58 Comment(1)
Upvoted this untested. See also https://mcmap.net/q/81501/-block-comments-in-a-shell-script which says the same. I guess that this might help since I did have weird behaviour of vars using the accepted answer. I chose another workaround (switch the permissions for the task only) and will not make the effort to rerun it, but this seems a good try.Ashlan
C
2

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.

Colucci answered 16/3, 2013 at 13:13 Comment(2)
What if, instead of root, lets call it $USERNAME2? Thanks in advance.Steinman
Hi, Thanks for your answer but It should be sudo su -c'bash scriptname.sh' There should be whitespace between su and -cBlabbermouth
H
0

You can use this function that will call the script again as root passing the first argument to the new call:

A=$1
run_with_sudo() {
    local prompt

    prompt=$(sudo -nv 2>&1)
    if [ $? -eq 0 ]; then
        # the current user has sudo and the password is already set
        if [ "$(whoami)" != "root" ]; then
            # restart script as root
            exec sudo su - <<EOF
                "$0" "$A"
EOF
            exit
        fi
    elif echo $prompt | grep -q '^sudo:'; then
        echo "the current user has sudo but needs the password entered"
        return 1
    else
        echo "the current user has no sudo rights"
        return 1
    fi
}

note that "$0" may not be what you think it is]

Hemihedral answered 19/4, 2023 at 23:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.