tags:

views:

1147

answers:

16

Hello all,

I wish to create a background process and I have been told these are usually written in C or something of that sort. I have recently found out PHP can be used to create a daemon and I was hoping to get some advice if I should make use of PHP in this way.

Here are my requirements for a daemon.

  • Continuously check if a row has been added to MySQL database table
  • Run FFmpeg commands on what was retrieved from database
  • Insert output into MySQL table

I am not sure what else I can offer to help make this decision. Just to add, I have not done C before. Only Java and PHP and basic bash scripting.

Does it even make that much of a performance difference?

Please allow for my ignorance, I am learning! :)

Thanks all

A: 

I wouldn't recommend it. PHP is not designed for longterm execution. Its designed primarily with short lived pages.

In my experience PHP can have problems with leaking memory for some of the larger tasks.

Kent Fredric
PHP's garbage collection is excellent so long as you adequately plan your scope.
Nolte Burke
well, apart from self-referencing array structures, where it leaks memory and spews messages to the console. woops.
Kent Fredric
+17  A: 

I would be inclined to perform this task with a cron job, rather than polling the database in a daemon.

It's likely that your FFmpeg command will take a while to do it's thing, right? In that case, is it really necessary to be constantly polling the database? Wouldn't a cronjob running each minute (or every five, ten or twenty minutes for that matter) be a simpler way to achieve the same thing?

Domster
Good line of thought. But from what I understand, the daemon will continue to create child process for anything new that is added to the db. Therefore, FFmpeg can take as long as it likes and this wouldn't matter, right?
Abs
You might check out using launchd (next gen cron)
Nerdling
Depends on the activity level. Launching a process is much heavier than running a timer in a single process, plus you need to add logic to deal with multiple jobs if it's too frequent. The cron job is going to need to duplicate the polling logic in any case.
le dorfier
+6  A: 

Php isn't any better or worse for this kind of thing than any of the other common scripting languages. It has fairly complete access to all of the system calls and library utilities you would need to do this sort of work. If you are most comfortable using PHP for scripting, then php will do the job for you.

The only down side is that php is not quite as ubiquitous as, say, perl or python, which is installed on almost every flavor of unix. Php is only found on systems that are going to be serving dynamic web content. Not that a Php interpreter is too large or costly to install also, but if your biggest concern is getting your program to many systems, that may be a slight hurdle.

TokenMacGuy
Most distros include PHP as much as perl and python
Nerdling
Yes, but not as often installed by default.
TokenMacGuy
A: 

You might want to consider making a mysql trigger that executes a system command (i.e. FFmpeg) instead of a daemon. If some lag isn't a problem, you could also put something in cron that executes every few minutes to check. Cron would be my choice, if it is an option.

To answer your question, php is perfectly fine to run as a daemon. It does not have to be done in C.

gpojd
Ah, I did not know about mysql triggers. Yes cron job is an option too, so is mysql triggers now. :)
Abs
Bad idea in general: triggers would be synchronous, adding locks for the duration of a transaction; they make transactions take longer (obviously); and are more difficult to test and debug.
le dorfier
I agree about the trigger, I was just mentioning it as an alternative to a daemon. It actually wouldn't be that bad though if it just spawns a new process and exits. My preference would still probably be using cron.
gpojd
+1  A: 

If you combine the answers from Kent Fredric, tokenmacguy and Domster you get something useful.

php is probably not good for long execution times, so let's keep every execution cycle short and make sure the OS takes care of the cleanup of any memoryleaks. As a tool to start your php script cron can be a good tool. And if you do it like that, there is not much difference between languages.

However, the question still stands. Is php even capable to run as a normal daemon for long times (some years)? Or will assorted memoryleaks eat up all your ram and kill the system?

/Johan

Johan
+1  A: 

A cron job and a little bit of bash scripting should be everything you need by the sounds of it. You can do things like:

$file=mysqlquery -h server < "select file from table;" ffmpeg $file -fps 50 output.a etc.

so bash would be easier to write, port and maintain IMHO than to use PHP.

Philluminati
+6  A: 

I'll be contrary and recommend you try the php daemon. It's apparently the language you know the best. You'll presumably incorporate a timer in any case, so you can duplicate the querying frequency on the database. There's really no penalty as long as you aren't naively looping on a query.

If it's something not executed frequently, you could alternatively run the php from cron, letting youor code drain the queue and then die.

But don't be afraid to stick with what you know best, as a first approximation.

Try not to use triggers. They'll impose unnecessary coupling, and they're no fun to test and debug.

le dorfier
+1  A: 

If you do so, pay attention to memory leaks. PHP 5.2 has some problems with its garbage collector, according to this (fixed in 5.3). Perhaps its better to use cron, so the script starts clean every run.

Fede F
A: 

Cron job? Yes.

Daemon which runs forever? No.

PHP does not have a garbage collector (or at least, last time I checked it did not). Therefore, if you create a circular reference, it NEVER gets cleaned up - at least not until the main script execution finishes. In daemon process this is approximately never.

If they've added a GC in new versions, then yes you can.

MarkR
+2  A: 

Hi Abs,

Running as a cron job with sensibly determined periodicity, a PHP script can do the job, and production stability is certainly achievable. You might want to limit the number of simultaneous FFMpeg instances, and be sure to have complete application logging and exception handling. I have implemented continuously running polling processes in Java, as well as the every-ten-minute cron'd PHP script, and both do the job nicely.

karim79
Hi Karim, thank you for that reply. :)
Abs
+1  A: 

For what you've described, I would go with a daemon. Make sure that you stick a sleep in the poll loop, so that you don't bombard the database when there are no new tasks. A cronjob works better for workflow/report type of jobs, where there isn't some particular event that triggers the next run.

As mentioned, PHP has some problems with memory management. You need to be sure that you test your code for memory leaks, since these would build up over time, in a long running script. PHP doesn't have real garbage collection - It relies on reference counting, which means that cyclic references will cause leaks. If you're aware of this, you can code around it.

troelskn
+3  A: 

A cron-job would probably work just fine, if near-instant actions is not required.

I'm just about to put live, a system I've built, based on the queueing daemon 'beanstalkd'. I send various small messages from (in this case, PHP) webpage calls to the daemon, and a PHP script then picks them up from the queue and performs various tasks, such as resizing images or checking databases (often passing info back via a Memcache-based store).

To avoid long-running processes, I've wrapped it in a BASH script, that, depending on the value returned from the script ("exit(1);") will restart the script, for every (say) 50 tasks it's performed. If it's restarting because I plan it to, it will do so instantly, any other exit value (the default is 0, so I don't use that) would pause a few seconds before it was restarted.

Alister Bulman
Thank you for your example.
Abs
+10  A: 

As others have noted, various versions of PHP have issues with their garbage collectors. Of course, if you know that your version does not have such issues, you eliminate that problem. The point is, you don't know (for sure) until you write the daemon and run it through valgrind to see if the installed PHP leaks or not on any given machine. So on that hand, you may write it just to discover that what Zend thinks is fixed may might still be buggy, or you are dealing with a slightly older version of PHP or some extension. Icky.

The other problem is somewhat buggy signals. In my experience, signal handlers are not always entered correctly with PHP, especially when the signal is queued instead of merged. That may not be an issue for you, i.e. if you just need to handle SIGINT/SIGUSR1/SIGUSR2/SIGHUP.

So, I suggest:

If the daemon is simple, go ahead and use PHP. If it looks like its going to get rather complex, or allocate lots of memory, you might consider writing it in C after prototyping it in PHP.

I am a pretty die hard C person. However, I see nothing wrong with hammering out something quick using PHP (beyond the cases that I explained). I also see nothing wrong with using PHP to prototype something that may or may not be later re-written in C. For instance, handling DB stuff is going to be much simpler if you use PHP, vs managing callbacks using other interfaces in C. So in that instance, for a 'one off', you will surely get it done much faster.

Tim Post
A: 

Go for it. I had to do it once also. Like others said, it's not ideal but it'll get-er-done. Using Windows, right? Good.

If you only need it to run occasionally (Once per hour, etc). Make a new shortcut to your firefox, place it somewhere relevant. Open up the properties for the shortcut, change "Target" to:

"C:\Program Files\Mozilla Firefox\firefox.exe" http://localhost/path/to/script.php

Go to Control Panel>Scheduled Tasks Point your new scheduled task at the shortcut.

If you need it to run constantly or pseudo-constantly, you'll need to spice the script up a bit.

Start your script with

set_time_limit(0);
ob_implicit_flush(true);

If the script uses a loop (like while) you have to clear the buffer:

$i=0;
while($i<sizeof($my_array)){
     //do stuff
     flush();     
     ob_clean();
     sleep(17);
     $i++;
}
A: 

One problem with properly daemonizing a PHP script is that PHP doesn't have interfaces to the dup() or dup2() syscalls, which are needed for detaching the file descriptors.

janneb
+1  A: 

If you do decided to go down the daemon route, there is a great PEAR module called System_Daemon which I've recently used successfully on a PHP v5.3.0 installation. It is documented on the authors blog: http://kevin.vanzonneveld.net/techblog/article/create_daemons_in_php

If you have PEAR installed, you can install this module using:

pear install -f System_Daemon

You will also need to create a initialisation script: /etc/init.d/<your_daemon_name>

Then you can:

  • Start Daemon: /etc/init.d/projNotifMailDaemon start
  • Stop Daemon: /etc/init.d/projNotifMailDaemon stop

Logs are kept at: /var/log/<your_daemon_name>.log

Tom