views:

822

answers:

7

I need an application to be running in the background on my web server, but I need to be able to start/stop the application with root privileges.

In order to do this, I want to have a service running that has root privileges, so that it can kill the application, and start it up again if need be.

Finally, I need to be able to send the start and kill commands to the service via Apache/PHP, so that it can be indirectly controlled through the web.

How do I create a Linux service?
How do I communicate with a Linux service in this manner?

Thanks in advance!

+5  A: 

Use the exec command in your PHP script to call shell files. The shell files can be setup with the "setuser" bit so it will run as its owner (instead of running with the web server's permissions).

Of course, you'll need to be very careful--lots of testing, monitoring, etc.

Finally, think about the service running as a dedicated user, not as root. Eg like apache and most other well done services do.

Added: Re: running a service in Linux. Depends on your flavor of Linux. If you want to be sure that your app service will be automatically re-started if it fails, plus logging, checkout Runit:

http://blogs.techrepublic.com.com/opensource/?p=202

http://smarden.org/runit

Added: Instead of setuid bit, I think Frank's suggestion (in comment) of using sudo system is better.

Larry K
Rather than the setuser bit, you can add a rule to allow execution of the script to /etc/sudoers, e.g.: apache ALL=(root) NOPASSWD: /bin/my.restart.script.sh -- then you just exec('sudo /bin/my.restart.script.sh');
Frank Farmer
+1 I agree with Frank. I think setting up sudoers for your specific cmds is better than setting the setuser bit. Also, sudo can log the times that the regular user (php server) invoked the sudo command to act as root.
Larry K
Thanks for the reply so far! Do you know how I would communicate with the service?
SkippyFire
The different linux service frameworks have commands to start/stop/get status from the services. Eg "service foo start|stop|status". Runit uses its "sv" command: sv start|stop|kill|status foo. Your php program would exec "sudo sv status foo" and report back the status to the web user.
Larry K
As an added note, in Fedora (and presumably some other distros) you also need to comment out the line 'Default requiretty' in the sudoers file.
dimo414
New link to runit - http://smarden.org/runit/
Pat
@Pat: +1; thanks, I've updated the answer.
Larry K
A: 

When doing this be very very careful. Never use any user submitted data from the web in the exec command. this could allow someone to arbitrarily execute commands on your machine.

Also I second Frank use a sudo rule so you can run that specific command with the permissions you need but nothing else. It will be more secure that way.

Jeremy Wall
Yes I know, that is why I said "indirectly". I just need start and kill commands, so I wont be passing on any text commands or anything complicated. The authentication will be handled by the PHP front end.
SkippyFire
+1  A: 

You can create a daemon which accepts the following commands:

  • daemon_name start
  • daemon_name stop
  • daemon_name restart
  • deamon_name reload

Starting the daemon should not be hard. Just executing daemon_name start from a PHP script should run it. After starting, you can write the PID of the process to a lock file (for stopping, restarting or reloading later). The daemon should handle signals.

In a PHP script, you can then invoke daemon_name stop. This should fire up a new daemon which would check the lock file and get the PID of the running daemon and send a signal which would be handled by the running daemon. The lock file should be removed/cleared and then the stop initiating daemon/process can quit.

Alan Haggai Alavi
+1  A: 

I think you should look at inetd, which can be configured to run all sorts of services, and it runs as root. You could then write a relatively simple program that is not itself root privileged, but which when run by root does the tasks you need done.

Jonathan Leffler
+1  A: 

As far as communicating with the service you did not say what type of service it is, however assuming you're writing it yourself the most common methods would be to comunicate via UNIX sockets or MMAP. Depends on your needs really.

Oh yeah, should point out there are already applications for web management of linux systems. Webmin is a really good one which can be configured to allow as much or as little control as you need.

SpliFF
+2  A: 

So, you have three pieces here :

  • Your web server without root privilege
  • An application
  • A daemon that is monitoring the application

Your problem is not launching the daemon, it is writing it, and communicating with it from the web server, without needing root privilege.

A daemon can be as simple as a non interactive application launched in the background :

# my_dameon &

I am not a php developper, but searching for message queue and php, I discovered beanstalkd
Looking at the example on the first page it seems you can use it to do the following :

  • The apache/php sends some message to beanstalkd
  • Your daemon reads the message from beanstalkd. Based on the command it starts or kill or reload the background application.

You can write your daemon in php, since there are client in many languages
You can also check this question

shodanex
+1  A: 

As @shodanex suggests, using Beanstalkd would be an excellent way to disconnect a web-front-end from a running-as-root command line worker. It could trivially be set to only run exactly what was required.

To run the worker, Pear's System_Daemon can generate and run a daemon-running script, with start/stop/restart.

Alister Bulman