Web Hosting Talk







View Full Version : daemon script


=-D
02-16-2005, 04:52 PM
Hello, I'd like to run a daemon programmed with a php script.

I would like only one instance checking for database updates and then triggering a response.

How would i go about doing this?

=-D
02-16-2005, 05:09 PM
Just further details:

Only one instance of the script can be allowed to run at one time.

innova
02-16-2005, 08:02 PM
I think thats a little too vague.

Set the timeout to 0?

Without more details on what this thing is doing I cant help you. What does this daemon do? Why does it have to be a daemon, as opposed to run from cron, etc?

=-D
02-17-2005, 12:51 AM
Hello! :)

Sorry for the vagueness. If i set the time out to 0, im afraid if it might die, then it wont process anymore requests.

What it is doing is reading the database for any new mail and then sending it via smtp.

I need it to be always checking the database and dispensing the emails.

If it ever goes down, i need it to respawn.

Any ideas? Thanks.

innova
02-17-2005, 04:05 PM
Two ways I can imagine this working.

1) Set timeout = 0, and run it in a while loop, having the loop sleep for X seconds between updates.

2) Run it from cron every X minutes.

error404
02-17-2005, 04:18 PM
When the program starts, save it's PID in a file. If the file exists, check to see if that PID is running (and optionally if it's an instance of PHP). If it is, then terminate, the daemon is already running. If it's not running, then continue with normal startup. Cron the script to run every minute or however often you need. If it's already running, it won't start a new instance; if it is running, it will restart itself.

I'm not entirely sure it's possible to do this with PHP. It may not have the OS-level functions required (though you *could* use the output of 'ps' to check, that's kinda lame-ish; the process's PID can be obtained with posix_getpid()). It's definitely possible with Perl, and there's a CPAN module that does exactly this (checks if the process is running, only starts if it isn't) called Proc::PID_File (http://search.cpan.org/~sharyanto/Proc-PID_File-0.05/PID_File.pm).

Note: This is for a standalone script executed on the command line. This process will not apply if you're accessing it over the web, as the PID will be equal to the Apache PID, which isn't guaranteed to be different, and will likely be running still even if the PHP script has finished execution. But it's also silly to expect that any script started over a web browser be persistent.

pphillips
02-17-2005, 06:29 PM
I've done this before in PHP. You can write a program like this to run from cron every x minutes to check if it's running, and if not restart it:

$out = shell_exec('ps -d | grep nameofscript.php');
if($out) {
// do something if its running
}
else
{
// Restart nameofscript.php
shell_exec('path/to/script/nameofscript.php > /dev/null 2>&1 &');
}

zupanm
02-17-2005, 09:34 PM
or just use a


while (1) {
// sleep 2 seconds so we don't hammer the system
sleep(2);

// commands here
}


you can then php file.php from the shell and it should always run in that loop doing what you want

mfonda
02-17-2005, 10:18 PM
This article might help you out:
php-mag.net/itr/online_artikel/psecom,id,484,nodeid,114.html

pphillips
02-18-2005, 02:14 AM
Originally posted by zupanm
or just use a


while (1) {
// sleep 2 seconds so we don't hammer the system
sleep(2);

// commands here
}


you can then php file.php from the shell and it should always run in that loop doing what you want

He will need to do this anyway for his actual script. The code I posted will auto-restart his script if it fails, which inevitably happens.

Angelo
02-18-2005, 11:06 AM
PHP can be daemonized with pcntl_fork() function. Your php version must be compiled with "--enable-pcntl" option to build Process Control Functions library in.

Refer to also posix_setsid(), posix_setuid() for session/child controls.

EXOWorks
02-18-2005, 11:16 AM
You can also use nohup from commandline ...

nohup /usr/bin/php /path/to/php/file.php &

Use the while(true) and sleep(1) ...

=-D
02-20-2005, 03:17 AM
wow, thankyou all you guys.

the information has been excellent!

CHEEERS!!!

brianoz
02-20-2005, 09:33 AM
The right way to do this is to use flock() on a file. That way the system will prevent you from starting multiple copies, and you can't get it wrong. If the script dies for any reason the lock will automatically go away. No checking for processes via ps or pid files, let your nice kernel do all the work for you!

So, if the file doesn't exist create it using O_EXCL or similar. Then lock it with flock and then do whatever the script is going to do. If you can't get the lock immediately die, with an error message saying "already running".

I personally use daemontools for this purpose. It automatically restarts the process if it dies, it allows only one instance, and it's free. Interface is a little antiquated but there are clones around too. If you have to write this stuff often read up on daemontools, it will make your life easy. And of course, with daemontools, no need to lock anything as only one instance can run at once!