55

For some reason I need, as user, to run without sudo a script script.sh which needs root privileges to work.
I saw as the only solution to put sudo INSIDE script.sh. Let's take an example :

script.sh :

#!/bin/sh
sudo apt-get update

Of course, if I execute this script, I get a prompt asking me for a password. Then I added to my sudoers file (at the end to override everything else) :

user ALL=(ALL:ALL) NOPASSWD:/path/to/script.sh

By the way, I also tried the line :

user ALL=(ALL) NOPASSWD:/path/to/script.sh

(I think I didn't fully understand the difference)

But this doesn't solve my problem if I don't use sudo to execute this script :

# ./script.sh
[sudo] password for user: 
# sudo ./script.sh
Starts updating...

Well, so I say to myself "Ok, that means that if I have a file refered in sudoers as I did, it will work without prompt only if I call him with sudo, what is not what I want".
So, ok, I create another script script2.sh as following :

script2.sh

#!/bin/sh
sudo /path/to/script.sh

In fact it works. But I am not truly satisfied of this solution, particularly by the fact that I have to use 2 scripts for every command.

This post is then for helping people having this problem and searching for the same solution (I didn't find a good post on it), and perhaps have better solutions coming from you guys.

Feel free to share your ideas !


EDIT 1 :

I want to insist on the fact that this "apt-get update" was just an example FAR from whhat my script actually is. My script has a lot of commands (with some cd to root-access-only config files), and the solution can't be "Well, just do it directly with apt-get".

The principle of an example is to help the understanding, not to be excuse to simplify the answer of the general problem.

Nilexys
  • 633
  • 1
  • 5
  • 10

8 Answers8

26

From my blog: IDMRockstar.com:

The kicker is that sometimes, I need to run commands as root. Here's the quick and dirty way I accomplish that without divulging the passwords:

#! /bin/bash
read -s -p "Enter Password for sudo: " sudoPW
echo $sudoPW | sudo -S yum update

This way the user is prompted for the password (and hidden from terminal) and then passed into commands as needed, so I'm not running the entire script as root =)

If you have a better, way, I'd love to hear it! I'm not a shell scripting expert by any means.

Cheers!

.: Adam

Adam
  • 360
  • 3
  • 4
  • 1
    This answer is very similar to the one by Eaton Emmerich a year earlier, maybe the `read -s -p` part could be added to it as an alternative approach to storing the password in the file. – Bob Apr 18 '17 at 15:54
  • Note that the -s option to read isn't supported in Bourne, but bash only, so don't confuse yourself by prefixing your script with the wrong shebang. – Russ Bateman Oct 18 '18 at 20:53
21

If you want to run sudo /usr/bin/apt-get update without a password, you need to have the sudoers entry:

user ALL=(ALL:ALL) NOPASSWD:/usr/bin/apt-get update

where user should be replaced by the name or id of the user. (In more complex cases, user could be replaced by a group or alias. See man sudoers for details.)

For the larger issue of the script as a whole, there are two possible approaches:

Approach 1

For each command in the script that needs sudo, create a line in sudoers specifically for that command. In this case, the script can be called normally:

./script1.sh

Approach 2

Place a line in sudoers for the script as a whole. When this is done, the individual commands do not need sudo. However, sudo must be used to start the script as in:

sudo ./script.sh
John1024
  • 109,961
  • 14
  • 137
  • 171
  • 2
    apt-get was an example. In fact, my script has a lot of commands... I am not dumb enough to make a script doing exactly what apt-get does ! – Nilexys Aug 09 '14 at 08:05
  • I added the line `user ALL=(ALL:ALL) NOPASSWD:/path-to-script` which seemed to work for `sudo sshfs ...` commands inside that script – FreelanceConsultant Jul 04 '16 at 19:57
  • 1
    Just in case it's not obvious, you must replace the `user` at the beginning of the `sudoers` entry with the username of the actual person who you want to be able to run the command, or a `%group` to allow all users in that group (for example, `%sudo` will allow anyone in the `sudo` group to execute the command w/o a password) – Tobias J Mar 16 '23 at 04:14
  • 1
    @TobiasJ Good points. I've updated the answer to mention groups and aliases. – John1024 Mar 20 '23 at 22:23
12

If your password isn't something you want to be very secure about, (maybe some testing server in the company etc.) you can elevate to sudo in the script via echo like:

echo YourPasswordHere | sudo -S Command

The prompt still prints the "enter password" text to output though. So don't expect it to be neat.

See this Askubuntu post

Eaton Emmerich
  • 452
  • 4
  • 17
7

As you noted, the file that must appear in the sudoers configuration is the one that is launched by sudo, and not the one that runs sudo.

That being said, what we often do, is having something like

user ALL=(ALL:ALL) NOPASSWD:/path/to/script.sh

in the sudo configuration, where script.sh has all the commands that the script has to do.

Then we define either a Bash function or an alias so that script.sh is actually

sudo /path/to/script.sh

The only issue is if some commands must not be run as root, you need to insert some su - user -c "command" commands in the script.

damienfrancois
  • 52,978
  • 9
  • 96
  • 110
2

In new /etc/sudoers.d/apt-get file, put single line:

user ALL=(ALL:ALL) NOPASSWD:/usr/bin/apt-get update

Fully qualified path to executable is required here.

Then use following in your script:

sudo apt-get update

Here, fully specified name is not required. Sudo uses PATH environment variable for executable resolution.

While changing and checking sudoers configuration, be sure to keep another root session open for error recovery.

Basilevs
  • 22,440
  • 15
  • 57
  • 102
  • Instead of using a second root, you should just use `visudo`. That's what it's for. Also, this approach allows anyone to update the system without password. – Ingo Bürk Feb 04 '17 at 00:53
2

I suggest you look at the sudo environment variables - specifically you can use (and check for) $SUDO_USER. Call your script with sudo (1 entry in sudoers), then do user stuff as SUDO_USER and root stuff as root.

bryn
  • 3,155
  • 1
  • 16
  • 15
1

As mentioned by Basilevs you need to add your user to the sudoers file in order to avoid that sudo commands in the script get stuck awaiting the password.

On Ubuntu 16, there is a simpler way: just add the user to the sudo group, like this:

sudo usermod -aG sudo *username*

From then on, it should work like a charm.

Note:

This works only on the condition that the following line is in file /etc/sudoers:

%sudo ALL=NOPASSWD: ALL

(such line gives passwordless sudo privileges at group level, in this case to the sudo group)

(if this line is not present and you want to add it, make sure you use visudo)

Varus Septimus
  • 1,510
  • 20
  • 13
  • 1
    Still prompts for password – keith Nov 13 '17 at 16:54
  • There are 2 distinct things at play here: (1) Command 'sudo usermod -aG sudo *username*' gives sudo privileges to user *username*. (2) However, it does not, by itself give sudo passwordless privileges to that user. For that to happen, the following line must be present in the /etc/sudoers file: '%sudo ALL=(ALL:ALL) ALL' (this line gives passwordless privileges at group level). This was the presupposition of my post. I hope this clarifies. – Varus Septimus Nov 14 '17 at 20:31
  • Thanks for the clarification. If you can update your answer, it will unlock my downvote so I can turn it into an upvote :-) – keith Nov 14 '17 at 21:53
0

Simply, in order to execute commands as root you must use su (even sudo uses su) As long as you execute sudo ./script2.sh successfully just instead : sudo su "#" //commands as root here "#" exit //commands as use here you can make it a shell function with the name sudo, but no other better way i think,however it's the case with scripts inti,rc android ..etc must be tidy ;)

however this requires you to put NOPASSWD: su wich is totaly secure indeed

any way here just lacks POISX permissions principle which is filtering so dont enable something to all users or vice versa simply, call sudo as much as you want with no additional thing then:

chown root script.sh
chmod 0755 script.sh
chgrp sudo script.sh

"make root owner of .sh" "make it read only and exec for others" "and put it in sudo group" of course under sudo that's it

Youssef
  • 17
  • 2