4

Using CentOs, I want to run a script as user 'training' as a system service. I use daemontools to monitor the process, which needs a launcher script that is run as root and has no tty standard in.

Below I give my five different attempts which all fail.

  1. :

    #!/bin/bash
    exec >> /var/log/training_service.log 2>&1
    setuidgid training training_command
    

    This last line is not good enough since for training_command, we need environment for trqaining user to be set.

  2. :

    su - training -c 'training_command' 
    

    This looks like it (Run a shell script as a different user) but gives 'standard in must be tty' as su making sure tty is present to potentially accept password. I know I could make this disappear by modifying /etc/sudoers (a la https://superuser.com/questions/119376/bash-su-script-giving-an-error-standard-in-must-be-a-tty) but i am reluctant and unsure of consequences.

  3. :

    sudo -u training -i bash -c 'source $HOME/.bashrc; training_command'
    

    A variation on the same theme: 'sudo: sorry, you must have a tty to run sudo'

  4. :

    runuser - training -c 'training_command'  
    

    This one gives runuser: cannot set groups: Connection refused. I found no sense or resolution to this error.

  5. :

    ssh -p100 training@localhost 'source $HOME/.bashrc; training_command'
    

    This one is more of a joke to show desparation. Even this one fails with Host key verification failed. (the host key IS in known_hosts, etc).

Note: all of 2,3,4 work as they should if I run the wrapper script from a root shell. problems only occur if the system service monitor (daemontools) launches it (no tty terminal I guess).

I am stuck. Is this something so hard to achieve?

I appreciate all insight and guidance to best practice.

(this has also been posted on superuser: https://superuser.com/questions/434235/script-calling-script-as-other-user)

Viktor Trón
  • 141
  • 1
  • 1
  • 5

7 Answers7

6

You will need to disable the requiretty setting in /etc/sudoers for root. Add the following line via visudo:

Defaults:root !requiretty

You will also need the following line in /etc/sudoers so root can do everything (this should be enabled by default, but check to be sure):

root ALL=(ALL) ALL

Then you can do the following:

sudo -u training /path/to/training_command
Urist McDev
  • 491
  • 5
  • 5
2

This seems to be essentially a special case of this question; we can use script -c to fake a tty. The only problem is that I can't get that trick to work directly with su for some reason, and sudo is a bit ugly if you really have to source ~/.bashrc before training_command. Try:

echo password | script -c "sudo su - training -c training_command" 
gmatht
  • 149
  • 6
  • 1
    I use `script -c "su username scriptFile.sh"` with success with [a user that does not need a password to su to another user](http://unix.stackexchange.com/questions/113754/allow-user1-to-su-user2-without-password) – Jonathan Drapeau Feb 17 '16 at 15:55
0

Choose the first one and set the environment variables you need.

If you already use daemontools then you do not create or mess with the log files manually. Daemontools does that job for you.

This is the script for the applicatoin run script

#!/bin/bash
exec 2>&1
exec setuidgid training sh -c 'YOURVARIABLE=yourvalue exec training_command'

Then you create a log directory run script with its own runscript.

Refer to this entry for setting up a log: http://cr.yp.to/daemontools/faq/create.html#runlog

cstamas
  • 6,607
  • 24
  • 42
  • Thanks Tamas. But. Setuidgid only sets the owner of the process not the environment. I really do need to be training user with its environment to run the command. your solution of putting 'YOURVARIABLE=yourvalue' does not do justice to this. I need to replicate exactly what a login shell sets and do not want to rely on knowing anything about the command beyond that. I can't believe there is no solution to this simple problem and how come noone ever ran into it. I think I am missing something... – Viktor Trón Jun 12 '12 at 18:48
  • 2
    @ViktorTrón: Log in as training. Execute the command `set >training.set` Log out. edit cstamas' script above to insert the line `. /home/training/training.set` right before the last line. It should set every environment variable that was set by the login process to the same value it had when you logged in manually. You may need to edit that file and remove one or two variables that might mislead your program, but you probably don't even need to do that. – Monty Harder Jul 15 '13 at 14:06
  • You want to also unset variables that are not part of the training environment. I'd use "su training /bin/sh -c ". ; runcommand". That works for me for setting up system services. – mpez0 Aug 12 '13 at 20:21
0

Plagiarising my answer here: Starting a script as another user

You could use start-stop-daemon something like this:

/sbin/start-stop-daemon --background --start --exec /path/to/training.sh --user training --pidfile=/path/to/training.pid --make-pidfile

where training.sh is something like this:

#!/bin/sh
exec >> /var/log/training_service.log 2>&1
source /home/training/.bashrc
training_command
Mr Shark
  • 346
  • 3
  • 10
0

Under SSH, you can run command foo.sh in normal user:

$ ssh normal_user@1.2.3.4 bash /path/to/foo.sh

if one of foo.sh's command need root privilege, for example, netstat, wrap it within su command like this (replace original raw netstat -tunple):

su -c "netstat -tunpl" root

and run foo.sh like this:

$ ssh -t normal_user@1.2.3.4 bash /path/to/foo.sh

This will prompt tow password, the first is for normal_user, and the second is for root.

coanor
  • 191
  • 2
  • 6
0

Run your command with SSH.

  1. make ssh key configuration to login without password for other user. Here is a tutorial for this purpose: https://www.digitalocean.com/community/tutorials/how-to-set-up-ssh-keys--2

  2. Run the command with ssh: ssh -l training -i key_file "training_command"

Ebru Yener
  • 121
  • 6
-1

Try this:

#!/bin/bash
sudo -u training training_command > /var/log/training_service.log 2>&1

If this fails, please post the output of /var/log/training_service.log.

AlexT
  • 141
  • 4
  • thanks Alex. Alas, sudo does not set the environment only if used with -i option. plus it still complains about missing tty if invoked by supervise. see my edited question including a variant of this. – Viktor Trón Jun 09 '12 at 11:34
  • You are right. Then `su - training --session-command=training_command >> /var/log/training_service.log 2>&1` should do it. – AlexT Jun 09 '12 at 17:47
  • Thanks Alex but as said su gives 'standard in must be a tty' if called from script. – Viktor Trón Jun 12 '12 at 18:38
  • I tried the above on a RHEL 6.2 box (before recommending it) as a cron script, and it worked perfectly. You tried it and it didn't work? – AlexT Jun 13 '12 at 02:49