115

All I need to do is to run a specific script as a particular user who does have the nologin/false shell indicated in /etc/passwd.

I would run the script as root and this should run as another user. Running:

~# su -c "/bin/touch /tmp/test" testuser

would work, but I need a valid shell for the testuser. I know I can disable the password with passwd -d testuser and leave the shell to /bin/bash this way would secure a little bit but I need to have nologin/false shell.

Basically what I need is what crontab does when we set jobs to be running as a particular user, regardless this one has nologin/false shell.

p.s I found this thread Executing a command as a nologin user, but I have no idea how to concatenate the command su -s /bin/sh $user to the script I need to run.

8 Answers 8

152

You can use the -s switch to su to run a particular shell

su -s /bin/bash -c '/path/to/your/script' testuser

(Prepend sudo to the above if testuser is a passwordless user.)

10
  • What if su is root:root -rwsr-x--- ?
    – Patryk
    Mar 10, 2015 at 0:24
  • 2
    What if the user doesn't have a password? May 18, 2015 at 10:12
  • 3
    @Wesley Found out that you need to be root to run that command for passwordless user. Aug 16, 2015 at 10:53
  • 1
    @lain, If the user is supposed to not have a shell, the process related to the command should not be a child of a bash process. Thus, you should also use exec to replace the shell with the script. And if you like to make the script a child of init, you just use &, as an example su -s /bin/bash -c 'exec /path/to/your/script &' test Apr 27, 2016 at 12:59
  • 1
    Since I have spent last 20 minutes working out how to achieve the same result using runuser, I'd like to point out that su -s SHELL parameter renders runuser command pretty much useless :) Thanks Jan!
    – Jiri
    Jul 21, 2016 at 18:06
15

You can do this with sudo -u if you have it installed:

# whoami
root
# sudo -u apache whoami
apache
# getent passwd apache
apache:x:48:48:Apache:/var/www:/sbin/nologin
3
  • How do you pass parameters to sudo -u apache whoami? May 18, 2015 at 10:11
  • @CMCDragonkai Any parameters after the command will be passed along. You can think of it like "sudo [-u apache] [whoami <param1> <param2>]".
    – Handyman5
    May 19, 2015 at 6:27
  • I think using sudo -u is probably not a good idea for running commands as a nologin user, because it exposes the SUDO_USER in the environment who is the real one invokes the command. Maybe I am just overthinking it.
    – Meow
    Apr 30, 2016 at 15:36
7

By providing the script as the argument to execute to /bin/sh:

su -s "/bin/sh /your/script/location" username
2

just realized :

su -s "/bin/bash" -c "/bin/touch /tmp/testuser" testuser

maybe there is a better way ?!

2

actually, the best way to do this is via runuser

see the man page for details

this tool is used to deal with the situation as the developer said in his bolg

Whenever an service is running as root and wants to change UID using the shell it should use runuser.

http://danwalsh.livejournal.com/55588.html

i've post this answer in many palaces, forgive me if you find this annoying

2
  • 1
    Please do not post link-only answers to prevent link rot. Instead, add the most relevant information from the link to your answer or alternatively, post the link as a comment instead of an answer. See this serverfault.com/help/how-to-answer help center article for further information. Feb 16, 2018 at 10:01
  • 1
    @FedericoGalli the most relevant information is already added, there is no need to copy and paste the usage, the man page provides enough information
    – Y00
    Feb 20, 2018 at 8:27
-1

Use sudo -u to specify the user. Also use the -i flag to set environment variables of the target user too.

sudo -i -u user command
1
  • 1
    this gives This account is currently not available.
    – knocte
    Apr 19, 2017 at 9:43
-1

All you need is sudo:

sudo -u <user> -g <group> -- <command>

-2

Use su command with shell -s and -c command. As shown below

 su  exec -l -c '/bin/bash /etc/update_conf.sh' -s /bin/bash
1
  • 2
    That's exactly the solution from the highest rated answer. Sep 17, 2019 at 6:55

You must log in to answer this question.

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