115

I was wondering how to run a command as another user from a script.

I have the script's owner set as root. I also have the following command being run within the script to run the command as the hudson user:

su -c command hudson

Is this the correct syntax?

1
  • For other googlers: some users might have this ability disabled on purpose. You can run sudo cat /etc/passwd | grep user-abc. If you see something like this: user-abc:x:994:994::/home/user-abc:/bin/false then it won't work. That's because the last part "/bin/false" means that there is no shell for that user. Feb 26, 2019 at 21:32

2 Answers 2

109

Yes. Here's the --help:

$ su --help
Usage: su [options] [LOGIN]

Options:
  -c, --command COMMAND         pass COMMAND to the invoked shell
  -h, --help                    display this help message and exit
  -, -l, --login                make the shell a login shell
  -m, -p,
  --preserve-environment        do not reset environment variables, and
                                keep the same shell
  -s, --shell SHELL             use SHELL instead of the default in passwd

And some testing (I used sudo as I don't know the password for the nobody account)

$ sudo su -c whoami nobody
[sudo] password for oli: 
nobody

When your command takes arguments you need to quote it. If you don't, strange things will occur. Here I am —as root— trying to create a directory in /home/oli (as oli) without quoting the full command:

# su -c mkdir /home/oli/java oli
No passwd entry for user '/home/oli/java'

It's only read mkdir as the value for the -c flag and it's trying to use /home/oli/java as the username. If we quote it, it just works:

# su -c "mkdir /home/oli/java" oli
# stat /home/oli/java
  File: ‘/home/oli/java’
  Size: 4096        Blocks: 8          IO Block: 4096   directory
Device: 811h/2065d  Inode: 5817025     Links: 2
Access: (0775/drwxrwxr-x)  Uid: ( 1000/     oli)   Gid: ( 1000/     oli)
Access: 2016-02-16 10:49:15.467375905 +0000
Modify: 2016-02-16 10:49:15.467375905 +0000
Change: 2016-02-16 10:49:15.467375905 +0000
 Birth: -
3
  • With -c option, does su invoke a shell and execute the command in the shell? Or does it execute the command without additional shell?
    – rosshjb
    Jun 6, 2020 at 10:57
  • It's a sub-shell. Try it with sleep and look at pstree, group, etc
    – Oli
    Jun 6, 2020 at 17:19
  • 1
    It doesn't load the user's environment variables
    – caot
    Aug 30, 2020 at 14:27
68

Note: "I have the script's owner set as root" doesn't do anything; even if you have the setuid bit set it still doesn't work


Assuming you're actually running the script as root, however, you can use sudo. su is primarily for switching users, while sudo is for executing commands as other users. The -u flag lets you specify which user to execute the command as:

sudo -u hudson command
2
  • 2
    Many times I have faced (on the systems where sudoers is well-administered) that trying to use sudo you can just get this: root is not in the sudoers file. Which makes su - <username> -c "command to run" the only option.
    – RAM237
    Sep 3, 2018 at 12:26
  • 1
    Quotes not needed when executing a non-trivial command. (E.g., sudo -u kilgore mv this that)
    – toraritte
    May 23, 2019 at 21:10

You must log in to answer this question.

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