154

I need to run something as sudo without a password, so I used visudo and added this to my sudoers file:

MYUSERNAME ALL = NOPASSWD: /path/to/my/program

Then I tried it out:

$ sudo /path/to/my/program
[sudo] password for MYUSERNAME: 

Why does it ask for a password? How can I run/use commands as root with a non-root user, without asking for a password?

13 Answers 13

83

You have another entry in the sudoers file which also matches your user. The NOPASSWD rule needs to be after that one in order for it to take precedence.

Having done that, sudo will prompt for a password normally for all commands except /path/to/my/program, which it will always let you run without asking for your password.

  • 5
    would this still work if the /path/to/my/program was a python script? – sadmicrowave Mar 3 '14 at 20:29
  • Can the program instead be an alias, set for bash (ie in .bashrc)? Or even a shell script inside /usr/local/sbin? To try out. – Nikos Alexandris Aug 5 '16 at 16:11
  • Nikos - no it cannot be an alias. It must point to a real path. – Paul Hedderly Jan 31 at 10:14
  • sudoers? where is? heawy to use your answer ( – Vasilii Suricov Apr 10 at 14:07
  • @VasiliiSuricov: It's usually in /etc, but some systems put it elsewhere. If you can't find it, try man sudoers. The local location for that file should be substituted into the man page at the time sudo was built for that system. – Warren Young Apr 10 at 14:20
122

If there are multiple matching entries in /etc/sudoers, sudo uses the last one. Therefore, if you can execute any command with a password prompt, and you want to be able to execute a particular command without a password prompt, you need the exception last.

myusername ALL = (ALL) ALL
myusername ALL = (root) NOPASSWD: /path/to/my/program

Note the use of (root), to allow the program to be run as root but not as other users. (Don't give more permissions than the minimum required unless you've thought out the implications.)

Note for readers who aren't running Ubuntu or who have changed the default sudo configuration (Ubuntu's sudo is ok by default): Running shell scripts with elevated privileges is risky, you need to start from a clean environment (once the shell has started, it's too late (see Allow setuid on shell scripts), so you need sudo to take care of that). Make sure that you have Defaults env_reset in /etc/sudoers or that this option is the compile-time default (sudo sudo -V | grep env should include Reset the environment to a default set of variables).

  • 2
    ex to go root from jhon with sudo su an no pass -----> john ALL=(ALL) NOPASSWD: /bin/su – bortunac Jul 13 '14 at 14:05
  • 4
    @adrian If you want to allow arbitrary commands as root, make that john ALL=(ALL) NOPASSWD: all. There's no point in going via su. – Gilles Jul 13 '14 at 14:08
  • Question: should I alter the permissions of my shell script so that it can get modified and read by root user only, for security? I'm thinking about an attacker modifying the script, which has all the permissions granted without the need of a password, so that it does what he/she wants. Obviously, the attacker can't even read sudoers file to know which scripts have this privilege, but can still try with all my custom scripts once he/she finds the folder in which they are stored in hope some are allowed, or something like that. – Jeffrey Lebowski Oct 10 '17 at 18:13
  • 1
    @JeffreyLebowski If you have a sudo rule that runs the script (directly or indirectly) then it's vital that only root (or people who have root privileges anyway) can write to the script file, and to the directory containing the script file, and to its parent directory and so on. It doesn't matter that anyone can read the script file (unless it contains a password or something, but that's a bad idea, if there's a password it should be in its own file, otherwise there's too much risk of accidentally leaking it e.g. by copy-pasting that section of the code in a question on this site). – Gilles Oct 10 '17 at 18:51
  • 1
    @alper No. Very few things require rebooting. After changing sudoers, you don't need to do anything special: sudo checks it each time. – Gilles Mar 18 at 19:02
21

WARNING: This answer has been deemed insecure. See comments below

Complete Solution: The following steps will help you achieve the desired output:

  1. Create a new script file (replace create_dir.sh with your desired script name):

    vim ~/create_dir.sh
    

    The script will be created in the user’s home directory

  2. Add some commands that only a root or sudo user can execute like creating a folder at the root directory level:

    mkdir /abc
    

    Note: Don’t add sudo to these commands. Save and exit (using :wq!)

  3. Assign execute permissions to it using:

    sudo chmod u+x create_dir.sh
    
  4. Make changes so that this script doesn’t require a password.

    1. Open the sudoers file:

      sudo visudo -f /etc/sudoers
      
    2. Add the following line at the end:

      ahmad ALL=(root) NOPASSWD: /home/ahmad/create_dir.sh
      

      Replace ahmad with whatever your username is. Also make sure this is the last line. Save and exit.

  5. Now when running the command add sudo before it like:

    sudo ./create_dir.sh
    

    This will run the commands inside the script file without asking for a password.

Follow the easy steps mentioned here http://step4wd.com/2013/09/14/run-root-commands-in-linux-ubuntu-without-password/

  • It would be better if you provided the relevant steps here and used the link as a backup for more detailed information. That way your answer retains possible value even if that link would not be valid anymore. – Anthon Sep 14 '13 at 5:37
  • 14
    This advice is insecure. The sudo part of sudo chmod u+x create_dir.sh is unnecessary as the user has (presumably) ownership over his/her home dir. Since the user can write to create_dir.sh, you have effectively given a free root shell to that user. – Lekensteyn Jul 19 '14 at 8:36
  • @Lekensteyn Which means also to any program running as the user. Might as well just allow the user to run anything with sudo without a password. – pydsigner May 23 '16 at 1:41
  • 2
    Am I missing something? I believe that the entire chmod is unnecessary, since you’re relying on sudo to elevate your privileges. – G-Man Jun 13 '18 at 14:57
8

I think your syntax is wrong. At least I use the following which works for me:

myusername ALL=(ALL) NOPASSWD: /path/to/executable
  • 6
    The (ALL) part is optional, leaving it out has exactly the same effect. Having (root) would be better though, but its absence doesn't explain the problem. – Gilles May 12 '11 at 11:39
  • +1 for sudo for this command and nothing else! No reason to break the entire system... – Johan May 12 '11 at 11:40
  • 3
    @Johan: That was already in the question. – Gilles May 12 '11 at 12:13
4

Verify that sudo is not aliased. Run like this

/usr/bin/sudo /path/to/my/program

For example a shell alias like this one:

alias sudo="sudo env PATH=$PATH"

may cause this behaviour.

  • You are right, my comment was out of order here, sorry for that. Nevertheless I'm intrigued - how do you expect aliasing to change the processing of sudoers by sudo. Or are you talking about redirecting sudo to something that always prints this error message to scoop passwords? That is unlikely the case here... – peterph Jul 19 '14 at 8:18
  • 2
    I was having the same problem as the OP. It turned out to be caused by having alias sudo="sudo env PATH=$PATH" in my ~/.bashrc. Rather than just solving it for myself and blindly just going about my business, I submitted my answer as a possible solution for anyone else that comes along this thread. – Sepero Jul 19 '14 at 22:50
  • That's fine, but when it is not obvious (which in this case isn't at least to some people) it is good to put an explanation into the answer to provide some context and prevent people from blindly using magic incantations. +2 (-(-1) + +1). :) – peterph Jul 24 '14 at 22:45
4

In some distros, Manjaro in my case, there is a file that overrides the /etc/sudoers file

sudo cat /etc/sudoers.d/10-installer
  • the ONLY way to see it is under root privilegies, you cannot list this directory without it.

There you will find something like this:

youruser ALL=(ALL)

You can delete that file, and will use cfg in /etc/sudoers file


/etc/sudoers:

In the sudoers file you must put something like:

%group ALL=(ALL) NOPASSWD: ALL

or

youruser ALL=(ALL) NOPASSWD: ALL

or

youruser ALL=(ALL) NOPASSWD: /path/to/executable
3

If you want to avoid having to use sudo nor have to change the sudoers config file, you can use:

sudo chown root:root path/to/command/COMMAND_NAME
sudo chmod 4775 path/to/command/COMMAND_NAME

This will make the command run as root without the need of sudo.

  • Wow, I never heard of this solution before, mind boggling – somethingSomething Nov 10 '18 at 14:18
  • Why is that I need to scroll to the bottom of these things to find the best answer? Thanks for this simple secure solution. – RyanNerd May 12 at 19:12
2

When you execute your script you need to run it as sudo /path/to/my/script.

Edit: Based on your comment to another answer, you want to run this from an icon. You will need to create a .desktop file that executes your program with sudo, just like on the terminal.

You could also consider using gtk-sudo for a visual password prompt.

You should probably consider the idea that you shouldn't be running things as root and that changing the system farther down the road so that you don't need root permissions at all would be a better way to go.

  • 7
    Do not make shell scripts setuid. See Allow setuid on shell scripts. – Gilles May 12 '11 at 11:38
  • I considered not even mentioning it because it's such a bad option. I just deleted it because I'm worried this asker might use the advice even with the warning that it was bad advice! – Caleb May 12 '11 at 11:41
2

This solved the issue for me (also tried some of the other answers, that might have helped):

The script I was calling was in /usr/bin, a directory that I don't have write permissions to (though I can usually read any files there). The script was chmodded +x (executable permisison), but it still didn't work. Moving this file to a path in my home directory, instead of /usr/bin, I was finally able to call it with sudo without entering a password.

Also something I doubted about (clarifying for future readers): You need to run your script as sudo. Type sudo when calling the script. Don't use sudo for the command inside your script that actually needs root (changing keyboard backlight in my case). Perhaps that also works, but you don't need to, and it seems like a better solution not to.

  • The second paragraph had the answer to my problem – M. Ahmad Zafar Sep 13 '13 at 8:02
  • @MuhammadAhmadZafar Glad it helped! – Luc Sep 13 '13 at 10:53
  • 3
    Actually using sudo inside of a script is perfectly fine provided you have the appropriate rights (set in sudoers) to run the command in question without a password. It makes things a bit more secure. – peterph Jul 19 '14 at 8:21
  • could really use this answer re-written as a step-by-step 'this is how you do it' rather than as a dialogue with the other answers – Walrus the Cat Nov 28 '17 at 22:31
  • @WalrustheCat Good point. Re-reading my answer, I think I might have been confused a little myself. Right now though, I don't remember what the exact situation was so I can't really do a better writeup. If you figure it out, perhaps a combination of several answers, by all means submit a new answer! – Luc Nov 29 '17 at 7:24
1

Another possibility might be to install, configure, then use the super command to run your script as

super /path/to/your/script

If you want to run some binary executable (e.g. that you have compiled into ELF binary from some C source code) -which is not a script- as root, you might consider making it setuid (and actually /bin/login, /usr/bin/sudo and /bin/su and super are all using that technique). However, be very careful, you could open a huge security hole.

Concretely, your program should be paranoically coded (so check all arguments and the environment and outside conditions before "acting", assuming a potentially hostile user), then you could use seteuid(2) and friends (see also setreuid(2)) carefully (see also capabilities(7) & credentials(7) & execve(2)...)

You'll use chmod u+s (read chmod(1)) when installing such a binary.

But be very careful.

Read many things about setuid, including Advanced Linux Programming, before coding such a thing.

Notice that a script, or any shebang-ed thing, cannot be setuid. But you could code (in C) a small setuid-binary wrapping it.

0

Ideally if you are customizing what commands can be run via sudo you should be making these changes in a separate file under /etc/sudoers.d/ instead of editing the sudoers file directly. You should also always use visudo to edit the file(s). You should NEVER grant NOPASSWD on ALL commands.

Example: sudo visudo -f /etc/sudoers.d/mynotriskycommand

Insert your line granting permission: myuser ALL= NOPASSWD: /path/to/your/program

Then save and exit and visudo will warn you if you have any syntax errors.

You can run sudo -l to see the permissions that your user has been granted, if any of the user specific NOPASSWD commands appear BEFORE any %groupyouarein ALL=(ALL) ALL command in the output you will be prompted for your password.

If you find yourself creating lots of these sudoers.d files then perhaps you will want to create them named per user so they are easier to visualize. Keep in mind that the ordering of the FILE NAMES and of the RULES within the file is very important, the LAST one loaded wins, whether it is MORE or LESS permissive than the previous entries.

You can control the file name ordering by using a prefix of 00-99 or aa/bb/cc, though also keep in mind that if you have ANY files that don't have numeric prefix, they will load after the numbered files, overriding the settings. This is because depending on your language settings the "lexical sorting" the shell uses sorts numbers first and then may interleave upper and lowercase when sorting in "ascending" order.

Try running printf '%s\n' {{0..99},{A-Z},{a-z}} | sort and printf '%s\n' {{0..99},{A-Z},{a-z}} | LANG=C sort to see whether your current language prints AaBbCc etc or ABC then abc to determine what the best "last" letter prefix to use would be.

0

To allow any user to execute program as sudo without asking password you can add following line

%sudo ALL=(root) NOPASSWD: /path/to/your/program

in /etc/sudoers

Note that %sudo make it.

  • While that's one way to accomplish a sudo rule, it doesn't answer the question about why setting the NOPASSWD flag on this rule still resulted in a password prompt. See the accepted answer for an idea why it happened. – Jeff Schaller Mar 2 at 17:19
0

The following is for the case where you want to run a command without password only if it has a specific set of options, where a part of the options is variable. AFAIK it is not possible to use variables or value ranges in sudoers declarations, i.e. you can allow access explicitly to command option1 but not command option2 using:

user_name ALL=(root) /usr/bin/command option1

but if the structure is command option1 value1, where value1 can vary, you would need to have explicit sudoers lines for each possible value of value1. Shell script provides a way around it.

This answer was inspired by M. Ahmad Zafar's answer and fixes the security issue there.

  1. Create a shell script where you call the command without sudo.
  2. Save the script in a root-privileged folder (e.g. /usr/local/bin/), make the file root-owned (e.g. chown root:wheel /usr/local/bin/script_name) with no write access for others (e.g. chmod 755 /usr/local/bin/script_name).
  3. Add the exception to sudoers using visudo:

    user_name ALL=(root) NOPASSWD: /usr/local/bin/script_name.

  4. Run your script sudo script_name.

For example, I want to change display sleep timeout on macOS. This is done using:

sudo pmset displaysleep time_in_minutes

I consider changing the sleep timeout an innocent action that doesn't justify the hassle of password typing, but pmset can do many things and I'd like to keep these other things behind the sudo password.

So I have the following script at /usr/local/bin/ds:

#!/bin/bash
if [ $# -eq 0 ]; then
        echo 'To set displaysleep time, run "sudo ds [sleep_time_in_minutes]"'
else
        if [[ $1 =~ ^([0-9]|[1-9][0-9]|1[0-7][0-9]|180)$ ]]; then
                pmset displaysleep $1 
        else
                echo 'Time must be 0..180, where 0 = never, 1..180 = number of minutes'
        fi
fi

At the end of sudoers file I have the following line:

user_name ALL=(root) NOPASSWD: /usr/local/bin/ds

To set the timeout at 3 minutes, I run my script from the ordinary user account user_name:

sudo ds 3

PS Most of my script is input validation, which is not mandatory, so the following would also work:

#!/bin/bash
pmset displaysleep $1 

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.