Running a script as root in the script

hi all,

i think i have got the solution for this but want to run it past you guys first

when i run a script sometimes its necassary to sudo to root so it can create users, chmod etc etc, the normal way for me doing this is just to simply run the script as root

but i have created a user and that user can sudo up to root level so im thinking of doing the "if/then" statement with the "id" command

if [ id -u root -ne 0 ]; then
su
echo "type in the root password"

rest of the commands go here

is this a good way?

thanks,

rob

should be with the echo statement before su:

if [ id -u root -ne 0 ]; then

echo "type in the root password"
su  # or sudo
fi
1 Like

thanks jim

instead of

-ne 0

can i use

!

instead

also the reason i want to do su instead of sudo is because i just want to run the script as root when the user runs it from there user enviroment

I'm confused by several things in this thread...

The command id -u root will return the string 0 on any UNIX system. The current real or effective UID of the person running the script has no effect on the results produced by this command.

The test command [ id -u root -ne 0 ] does not run the id command; it invokes test with the five arguments id , -u , root , -ne , and 0 . And that is not a valid set of arguments to be given to the test utility.

Nothing in your script after invoking su will be run with root privileges. The su utility, if given a proper password, will start a shell and nothing in the rest of your script will be run until that shell exits.

If you were running the id command, the exit code of that utility is not related to the uid or euid of the user running the process; it only tells you whether or not the user you name with the -u option is known on your system.

Would something more like:

if [ "$LOGNAME" != "root" ]
then	echo 'type in root password'
	su <<EOF
		sh command_file
EOF
else	sh command_file
fi

where command_file is the pathname of a file containing the commands you want this script to run with root privileges.

So, do you want anybody to be able to start the script, however if you detect that you are not the super-user account, you want to restart the script as the super-user instead?

Two quick options I can think of:-

  1. Make the script owned by root and set the SUID flag. Use chmod but add a leading 1 to the numeric description, e.g. if the file is rwxr-x--- , then chmod 1750 filename
  2. Set everyone you want to up as a sudo user with NOPASSWD for this script, then add this to the top of your script:-
    text if [ $(id -u) -ne 0 ] then exec sudo $0 "$@" # Will overwrite this process so script does not continue as self fi # Arguments are passed ass supplied

    Be very careful to explicitly grant users access to the script rather than a blanket 'run anything' else they will do things you don't want them to.

Do either of these help?

Robin

thanks Don, i will try out your script

Robin - yes i want anyone to run the script and if they are not root it will log in as root or sudo up to root level and then it will run the rest of the commands in the script

so why wont this command work then

if [ id root -ne 0 ]; then
echo "type in the root password"
read pwd
su $pwd
fi

If you use the su command, it will try to Switch User to the name given. If no name is given then it assumes the super-user account is desired. What you have coded as su $pwd will try to become the user in the $pwd variable. If (somehow) it is successful, you will be dropped to a shell prompt and you script will pause until the shell exits, whereupon you script (as an ordinary user) will continue.

It is the same effect as this short script:-

echo "I am here 1"
sh
echo "I am here 2"

If you run this, it will display I am here 1 and drop to a shell prompt. Exiting the shell in the normal way should then display I am here 2

You cannot feed a password into the su command because that would make it very unsafe, hence why authorisation processes like sudo were developed. This allows someone responsible to grant privileges rather than users just getting whatever they feel like.

As an analogy, if I walked into a bank an identified myself then said, "I'd like to access another account" there would be some pretty stern questions and checks. Gifting privileges comes with risk and as the system owner, you are responsible for making sure that the server is secure. If you are happy to grant access to allow them to run a locked-down script, that's fine.

What is it that your script needs to do as the super-user anyway? There may be a safer way to achieve it.

Kind regards,
Robin

i just want the user to run this simple script that i made to create an ftp user account with a home directpry and i thought a normal user cannot add directorys and make a user chmod chown etc etc -

#!/bin/bash

dir=/mnt/sftp
group=sftp_users

    echo "Enter UserName:"
    read user

    if id $user ; then
        echo "$user already exists as you can see above, please re-run the script"
        exit
        else
        echo "$user not in system, ok to continue"
    fi

    echo "Enter Password:"
    read passwd
    echo "$user:$passwd" >> /ftp_details/accounts.csv
    echo "is this a normal user (press 1) ?"
    read choice
    
    case $choice in
        1)
            useradd -g $group -d $dir/$user -s /sbin/nologin $user
            mkdir -p $dir/$user/data
            chown root $dir/$user
            chmod 755 $dir/$user
            chown $user $dir/$user/data
            chmod 755 $dir/$user/data
            touch $dir/$user/data/WARNING_everything_in_here_will_get_removed_in_14_days_time.txt
            ;;
        *)
            echo "invalid selection, please re-run the script"
            exit
            ;;
    esac

    echo $user:$passwd | chpasswd
1 Like

Well I can see that you have thought about what you want to achieve. Whilst we could organise to grant access to the specific powerful commands, the problem would then be that they could run them anytime, so i think you probably have it about right to only run the whole script as root. I presume you plan to expand it from a single choice later.

I notice that you don't have an audit trail in here to say who did what and when, just in case it goes wrong or needs to be shown. Whilst within the script if started as root through sudo, you can get the calling user as $SUDO_USER so you can write that in your message.

I hope that this helps, but I think have everything you need. Does it make sense or have I/we left you confused?

Robin

Hi Robin yes im confused, what do you mean sudo_user

do you mean for every command i have in my script put sudo infront of it

then i thought instead of putting sudo infront of every command just make the user type su and job done ie from there it will run all the commands as root

I thought I explained this in post #4 in this thread when I said:

Once a user types the root password in response to invoking the command su (without operands), they can then type any commands into the shell that su starts for them and it will run those commands with all of the privileges of someone who logged in as root. When they exit that super-user shell, your script will then continue running with the same privileges as the user who invoked that utility had when they invoked your script. No commands in your script after the shell started by su exits will run with root privileges unless it was root who invoked your script to being with.

The here-document trick I also showed you in that post can be used to feed commands into that super-user shell. The text in that here-document is just read and executed by the shell that su starts; it is not that su is running commands in your script.

The logical easy way to do this (if a user who is going to run your script knows the root password and wants to run your script with root privileges) is for them to run su and then while in the shell that su starts have them run your script and do whatever else they need to do as root before exiting that super-user shell.

Gluing everything in this thread together, we have (my insertions in green):-

#!/bin/bash

if [ $(id -u) -ne 0 ]
then
   exec sudo $0 "$@"             # Will overwrite this process so script does not continue as self
fi                               # Any arguments are passed on as supplied

# A superuser will carry on through here

LOGFILE=/var/lib/creation.log    # .... or whatever suits you

dir=/mnt/sftp
group=sftp_users	

echo "Enter UserName:"
read user

if id $user ; then
        echo "$user already exists as you can see above, please re-run the script"
        exit
else
        echo "$user not in system, ok to continue"
fi

echo "Enter Password:"
read passwd
echo "$user:$passwd" >> /ftp_details/accounts.csv
echo "is this a normal user (press 1) ?"
read choice
    
case $choice in
        1)
            echo "$(date) : User $SUDO_USER creating $user" >> $LOGFILE
            useradd -g $group -d $dir/$user -s /sbin/nologin $user
            mkdir -p $dir/$user/data
            chown root $dir/$user
            chmod 755 $dir/$user
            chown $user $dir/$user/data
            chmod 755 $dir/$user/data
            touch $dir/$user/data/WARNING_everything_in_here_will_get_removed_in_14_days_time.txt
            ;;
        *)
            echo "invalid selection, please re-run the script"
            exit
            ;;
esac

echo $user:$passwd | chpasswd

You would then need to add a rule using visudo to allow your selected user(s)/group(s) to run this script. You will need to be a super-user to run visudo
Add the lines like these:-

#Individual users
robert1			ALL = NOPASSWD: /path/to/this_script
trusted1		ALL = PASSWD: /path/to/this_script

#Group members are trusted
%trustedgroup		ALL = PASSWD: /path/to/this_script

The account robert1 will just pass into the script, but trusted1 and members of the group trustedgroup will have to enter their own password to continue. This means they don't need to know the all-powerful account password. If they do, then there is no way to control them.

Using sudo means that you can grant them privileges they need for just when they are doing what you want and nothing more, i.e. you trust them to run this script, but not to become the super-user because they might remove /etc/passwd by mistake.

How far does this get you now?

Am I just more confusing? Apologies if I am.
Robin