247

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?

0

15 Answers 15

194

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).

7
  • 3
    ex to go root from jhon with sudo su an no pass -----> john ALL=(ALL) NOPASSWD: /bin/su
    – bortunac
    Commented Jul 13, 2014 at 14:05
  • 7
    @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. Commented Jul 13, 2014 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. Commented Oct 10, 2017 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). Commented Oct 10, 2017 at 18:51
  • 2
    @alper No. Very few things require rebooting. After changing sudoers, you don't need to do anything special: sudo checks it each time. Commented Mar 18, 2019 at 19:02
122

You have another entry in the sudoers file, typically located at /etc/sudoers, 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.

6
  • 8
    would this still work if the /path/to/my/program was a python script? Commented Mar 3, 2014 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. Commented Aug 5, 2016 at 16:11
  • 2
    Nikos - no it cannot be an alias. It must point to a real path. Commented Jan 31, 2019 at 10:14
  • sudoers? where is? heawy to use your answer ( Commented Apr 10, 2019 at 14:07
  • 1
    @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. Commented Apr 10, 2019 at 14:20
28

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/

5
  • 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
    Commented Sep 14, 2013 at 5:37
  • 24
    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
    Commented Jul 19, 2014 at 8:36
  • 1
    @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
    Commented May 23, 2016 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. Commented Jun 13, 2018 at 14:57
  • 1
    to address the insecure aspect, you could create the script file (create_dir.sh) in /root/bin for instance, default ownership should be root:root; even adjust permissions to chmod 740; then visudo as in the answer, adjusting the filename to /root/bin/create_dir.sh; you could even make an alias in your (non-root user) ~/.bashrc such as alias create_root_dir='/root/bin/create_dir.sh' Just check that the script file in /root/bin has the ownership / permissions as specified; as well as that /root/bin itself has standard root:root ownership, no write permissions from non-root
    – Mark
    Commented Apr 12 at 10:23
14

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.

5
  • Wow, I never heard of this solution before, mind boggling Commented Nov 10, 2018 at 14:18
  • 3
    @RyanNerd: This is not a secure solution. Not only can the OP now run the command as root without a password, buy anybody can now run the command as the root user. Commented Feb 7, 2020 at 16:36
  • 2
    "chmod 4775 filename" is one way. Second, maybe better way to SETUID, without re-defining whole file permissions is "chmod u+s filename"
    – 16851556
    Commented Feb 9, 2020 at 11:12
  • sudo chmod 005 is safe. You don't wanna give writing permissions to the current user. Otherwise anyone in your session could do anything with your script. Commented Sep 9, 2020 at 13:01
  • Most shells today ignore setuid for scripts
    – Mark
    Commented Apr 12 at 10:28
13

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

myusername ALL=(ALL) NOPASSWD: /path/to/executable
3
  • 7
    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. Commented May 12, 2011 at 11:39
  • +1 for sudo for this command and nothing else! No reason to break the entire system...
    – Johan
    Commented May 12, 2011 at 11:40
  • 3
    @Johan: That was already in the question. Commented May 12, 2011 at 12:13
8

If you have an distro like Manjaro, you must deal first with a file that overrides the definition of /etc/sudoers; you may delete it or work directly with that file to add your new configurations.

This file is:

sudo cat /etc/sudoers.d/10-installer

The ONLY way to see it is under root privileges; you cannot list this directory without it. This file is Manjaro specific: you may find this configuration with a different name, but in same directory.

In your file of choice, you can add the following line(s) to get your desired configuration(s):

Ignore authentication for a group:

%group ALL=(ALL) NOPASSWD: ALL

or Ignore authentication for a user:

youruser ALL=(ALL) NOPASSWD: ALL

or Ignore authentication on a specific executable for a user:

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

QUICK NOTE: You are opening a door to use sudo without authentication, which means you can run everything modifying everything on your system; use it with responsibility.

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.

3
  • 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
    Commented Jul 19, 2014 at 8:18
  • 3
    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
    Commented Jul 19, 2014 at 22:50
  • 1
    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
    Commented Jul 24, 2014 at 22:45
3

In the script sudoers which is inside /etc/ uncomment the line given below:

#includedir /etc/sudoers.d

Create one file with any name inside /etc/sudoers.d/ directory and add the content as given in the maximum answers. Like for all users as root

#!/bin/bash
ALL    ALL = NOPASSWD: /path/of/the/script/which/you/want/to/run/as/root

This is the safest way to run the script with root permission.

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.

2
  • 7
    Do not make shell scripts setuid. See Allow setuid on shell scripts. Commented May 12, 2011 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
    Commented May 12, 2011 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.

5
  • The second paragraph had the answer to my problem Commented Sep 13, 2013 at 8:02
  • @MuhammadAhmadZafar Glad it helped!
    – Luc
    Commented Sep 13, 2013 at 10:53
  • 4
    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
    Commented Jul 19, 2014 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 Commented Nov 28, 2017 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
    Commented Nov 29, 2017 at 7:24
2

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.

Be aware that on Linux, application code interact with the Linux kernel using syscalls(2). Most of them could fail, see errno(3). A lot of Linux applications (e.g. GNU bash, GNU make, GNU gdb, GNOME) are open source : you are allowed to download then study and contribute to their source code.

2
  • Advanced Linux Programming is a dead link.
    – RyanNerd
    Commented Feb 2, 2021 at 9:08
  • "you could code (in C) a small setuid-binary wrapping it." AFAIK when you call the wrapping binary from a shell, the shell logic identifies that it is a shell calling a script (whether or not there is the wrapping binary as an intermediary) thus ignores the setuid at that stage; this is as of 2024 at least
    – Mark
    Commented Apr 12 at 10:33
1

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.

1
  • 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
    Commented Mar 2, 2019 at 17:19
1

Alternately you can use python pudo package.

Installation:

user$ sudo -H pip3 install pudo # you can install using pip2 also

Below is the code snippet for using in python automation for running commands under root privilege:

user$ python3 # or python2
>>> import pudo
>>> (ret, out) = pudo.run(('ls', '/root')) # or pudo.run('ls /root')
>>> print(ret)
>>> 0
>>> print(out)
>>> b'Desktop\nDownloads\nPictures\nMusic\n'

Below is the cmd example for running commands under root privilege:

user$ pudo ls /root
Desktop  Downloads  Pictures  Music
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

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 

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .