» Create daemons in PHP
Everyone knows PHP can be used to create websites. But it can also be used to create desktop applications and commandline tools. And now with a class called System_Daemon, you can even create daemons using nothing but PHP. And did I mention it was easy?
What is a Daemon?
A daemon is a Linux program that run in the background, just like a
'Service' on Windows. It can perform all sorts of tasks that do not
require direct user input. Apache is a daemon, so is MySQL. All you ever
hear from them is found in somewhere in /var/log, yet they silently power
over 40% of the Internet.
You reading this page, would not have been possible without them. So clearly: a daemon is a powerful thing, and can be bend to do a lot of different tasks.
Why PHP?
Most daemons are written in C. It's fast & robust. But if you are in a LAMP oriented company like me, and you need to create a lot of software in PHP anyway, it makes sense:
- Reuse & connect existing code Think of database connections, classes that create customers from your CRM, etc.
- Deliver new applications very fast PHP has a lot of build in functions that speed up development greatly.
- Everyone knows PHP (right?) If you work in a small company: chances are there are more PHP programmers than there are C programmers. What if your C guy abandons ship? Admittedly it's a very pragmatic reason, but it's the same reason why Facebook is building HipHop.
Possible use cases
- Website optimization If you're running a (large) website, jobs that do heavy lifting should be taken away from the user interface and scheduled to run on the machine separately.
- Log parser Continually scan logfiles and import critical messages in your database.
- SMS daemon Read a database queue, and let your little daemon interface with your SMS provider. If it fails, it can easily try again later!
- Video converter (think Youtube) Scan a queue/directory for incoming video uploads. Make some system calls to ffmpeg to finally store them as Flash video files. Surely you don't want to convert video files right after the upload, blocking the user interface that long? No: the daemon will send the uploader a mail when the conversion is done, and proceed with the next scheduled upload
Deamons vs Cronjobs
Some people use cronjobs for the same Possible use cases. Crontab is fine but it only allows you to run a PHP file every minute or so.
- What if the previous run hasn't finished yet? Overlap can seriously damage your data & cause siginificant load on your machines.
- What if you can't afford to wait a minute for the cronjob to run? Maybe you need to trigger a process the moment a record is inserted?
- What if you want to keep track of multiple 'runs' and store data in memory.
- What if you need to keep your application listening (on a socket for example) Cronjobs are a bit rude for this, they may spin out of control and don't provide a
framework for logging, etc. Creating a daemon would offer more elegance & possibilities. Let's just say: there are very good reasons why a Linux OS isn't composed entirely of Cronjobs :)
How it works internally
(Nerd alert!) When a daemon program is started, it fires up a second child process, detaches it, and then the parent process dies. This is called forking. Because the parent process dies, it will give the console back and it will look like nothing has happened. But wait: the child process is still running. Even if you close your terminal, the child continues to run in memory, until it either stops, crashes or is killed.
In PHP: forking can be achieved by using the Process Control Extensions. Getting a good grip on it, may take some studying though.
System_Daemon
Because the Process Control Extensions' documentation is a bit rough, I decided to figure it out once, and then wrap my knowledge and the required code inside a PEAR class called: System_Daemon. And so now you can just:
require_once "System/Daemon.php"; // Include the Class System_Daemon::setOption("appName", "mydaemon"); // Minimum configuration System_Daemon::start(); // Spawn Deamon!
And that's all there is to it. The code after that, will run in your
server's background. So next, if you create a while(true) loop around
that code, the code will run indefinitely. Remember to build in a sleep(5)
to ease up on system resources.
Features & Characteristics
Here's a grab of System_Daemon's features:
- Daemonize any PHP-CLI script
- Simple syntax
- Driver based Operating System detection
- Unix only
- Additional features for Debian / Ubuntu based systems like:
- Automatically generate startup files (init.d)
- Support for PEAR's Log package
- Can run with PEAR (more elegance & functionality) or without PEAR (for standalone packages)
- Default signal handlers, but optionally reroute signals to your own handlers.
- Set options like max RAM usage
Download
You could download the package from PEAR, or, if you have PEAR installed on your system: just run this from a console:
pear install -f System_Daemon
You can also update it using that last command.
Beta
Though I have quite some daemons set up this way, it's officially still beta. So please report any bugs over at the PEAR page. Other comments may be posted here.
Complex Example
Ready to dig a little deeper? This example program is called 'logparser', it takes a look at a more complex use of System_Daemon. For instance, it introduces command line arguments like:
--no-daemon # just run the program in the console this time
--write-initd # writes a startup file
Read this source to get the picture. Don't forget the comments!
#!/usr/bin/php -q <?php /** * System_Daemon turns PHP-CLI scripts into daemons. * * PHP version 5 * * @category System * @package System_Daemon * @author Kevin <kevin@vanzonneveld.net> * @copyright 2008 Kevin van Zonneveld * @license http://www.opensource.org/licenses/bsd-license.php * @link http://github.com/kvz/system_daemon */ /** * System_Daemon Example Code * * If you run this code successfully, a daemon will be spawned * but unless have already generated the init.d script, you have * no real way of killing it yet. * * In this case wait 3 runs, which is the maximum for this example. * * * In panic situations, you can always kill you daemon by typing * * killall -9 logparser.php * OR: * killall -9 php * */ // Allowed arguments & their defaults $runmode = array( 'no-daemon' => false, 'help' => false, 'write-initd' => false, ); // Scan command line attributes for allowed arguments foreach ($argv as $k=>$arg) { if (substr($arg, 0, 2) == '--' && isset($runmode[substr($arg, 2)])) { $runmode[substr($arg, 2)] = true; } } // Help mode. Shows allowed argumentents and quit directly if ($runmode['help'] == true) { echo 'Usage: '.$argv[0].' [runmode]' . "\n"; echo 'Available runmodes:' . "\n"; foreach ($runmode as $runmod=>$val) { echo ' --'.$runmod . "\n"; } die(); } // Make it possible to test in source directory // This is for PEAR developers only ini_set('include_path', ini_get('include_path').':..'); // Include Class error_reporting(E_ALL); require_once 'System/Daemon.php'; // Setup $options = array( 'appName' => 'logparser', 'appDir' => dirname(__FILE__), 'appDescription' => 'Parses vsftpd logfiles and stores them in MySQL', 'authorName' => 'Kevin van Zonneveld', 'authorEmail' => 'kevin@vanzonneveld.net', 'sysMaxExecutionTime' => '0', 'sysMaxInputTime' => '0', 'sysMemoryLimit' => '1024M', 'appRunAsGID' => 1000, 'appRunAsUID' => 1000, ); System_Daemon::setOptions($options); // This program can also be run in the forground with runmode --no-daemon if (!$runmode['no-daemon']) { // Spawn Daemon System_Daemon::start(); } // With the runmode --write-initd, this program can automatically write a // system startup file called: 'init.d' // This will make sure your daemon will be started on reboot if (!$runmode['write-initd']) { System_Daemon::info('not writing an init.d script this time'); } else { if (($initd_location = System_Daemon::writeAutoRun()) === false) { System_Daemon::notice('unable to write init.d script'); } else { System_Daemon::info( 'sucessfully written startup script: %s', $initd_location ); } } // Run your code // Here comes your own actual code // This variable gives your own code the ability to breakdown the daemon: $runningOkay = true; // This variable keeps track of how many 'runs' or 'loops' your daemon has // done so far. For example purposes, we're quitting on 3. $cnt = 1; // While checks on 3 things in this case: // - That the Daemon Class hasn't reported it's dying // - That your own code has been running Okay // - That we're not executing more than 3 runs while (!System_Daemon::isDying() && $runningOkay && $cnt <=3) { // What mode are we in? $mode = '"'.(System_Daemon::isInBackground() ? '' : 'non-' ). 'daemon" mode'; // Log something using the Daemon class's logging facility // Depending on runmode it will either end up: // - In the /var/log/logparser.log // - On screen (in case we're not a daemon yet) System_Daemon::info('{appName} running in %s %s/3', $mode, $cnt ); // In the actuall logparser program, You could replace 'true' // With e.g. a parseLog('vsftpd') function, and have it return // either true on success, or false on failure. $runningOkay = true; //$runningOkay = parseLog('vsftpd'); // Should your parseLog('vsftpd') return false, then // the daemon is automatically shut down. // An extra log entry would be nice, we're using level 3, // which is critical. // Level 4 would be fatal and shuts down the daemon immediately, // which in this case is handled by the while condition. if (!$runningOkay) { System_Daemon::err('parseLog() produced an error, '. 'so this will be my last run'); } // Relax the system by sleeping for a little bit // iterate also clears statcache System_Daemon::iterate(2); $cnt++; } // Shut down the daemon nicely // This is ignored if the class is actually running in the foreground System_Daemon::stop();
Console action: Controlling the Daemon
Now that we've created an example daemon, it's time to fire it up!
I'm going to assume the name of your daemon is logparser. This can
be changed with the statement:
System_Daemon::setOption('appName', 'logparser').
But the name of the daemon is very important because it is also used
in filenames (like the logfile).
Execute
Just make your daemon script executable, and then execute it:
chmod a+x ./logparser.php
./logparser.php
Check
Your daemon has no way of communicating through your console, so check for messages in:
tail /var/log/logparser.log
And see if it's still running:
ps uf -C logparser.php
Kill
Without the start/stop files (see below for howto), you need to:
killall -9 logparser.php
Autch.. Let's work on those start / stop files, right?
Start / Stop files (Debian & Ubuntu only)
Real daemons have an init.d file. Remember you can restart Apache with
the following statement?
/etc/init.d/apache2 restart
That's a lot better than killing. So you should be able to control your own daemon like this as well:
/etc/init.d/logparser stop
/etc/init.d/logparser start
Well with System_Daemon you can write autostartup files using the
writeAutoRun() method, look:
$path = System_Daemon::writeAutoRun();
On success, this will return the path to the autostartup file:
/etc/init.d/logparser, and you're good to go!
Run on boot
Surely you want your daemon to run at system boot.. So on Debian & Ubuntu you could type:
update-rc.d logparser defaults
Done your daemon now starts every time your server boots. Cancel it with:
update-rc.d -f logparser remove
Logrotate
Igor Feghali shares with us a logrotate config file to keep your
log files from growing too large. Just place a file in your
/etc/logrotate.d/.
/var/log/mydaemon.log {
rotate 15
compress
missingok
notifempty
sharedscripts
size 5M
create 644 mydaemon_user mydaemon_group
postrotate
/bin/kill -HUP `cat /var/run/mydaemon/mydaemond.pid 2>/dev/null` 2> /dev/null || true
endscript
}
Obviously, replace the mydaemon occurances with values corresponding
to your environment. Thanks Igor!
Troubleshooting
Here are some issues you may encounter down the road.
- Don't use echo() **Echo writes to the STDOUT of your current session. If you logout, that will cause fatal errors and the daemon to die. Use System_Daemon::log() instead.
- Connect to MySQL after you start() the daemon. Otherwise only the parent process will have a MySQL connection, and since that dies.. It's lost and you will get a 'MySQL has gone away' error.
- Error handling
Good error handling is imperative. Daemons are often mission critical applications and you don't want an uncatched error to bring it to it's knees.
- Reconnect to MySQL A connection may be interrupted. Think about network downtime or lock-ups when your database server makes backups. Whatever the cause: You don't want your daemon to die for this, let it try again later.
- PHP error handler
As of 0.6.3, System_Daemon forwards all PHP errors to the log() method, so keep an eye on your logfile. This behavior can be controlled using the
logPhpErrors(true||false) option.
- Monit Monit is a standalone program that can kickstart any daemon, based on your parameters. Should your daemon fail, monit will mail you and try to restart it.
- Watch that memory Some classes keep a history of executed commands, sent mails, queries, whatever. They were designed without knowing they would ever be used in a daemonized environment. Cause daemons run indefinitely this 'history' will expand indefinitely. Since unfortunately your server's RAM is not infinite, you will run into problems at some point. This makes it's very important to address these memory 'leaks' when building daemons.
- Statcache will corrupt your data
If you do a
file_exists(), PHP remembers the results to ease on your disk until the process end. That's ok but since the Daemon process does not end, PHP will not be able to give you up to date information. As of 0.8.0 you should callSystem_Daemon::iterate(2)instead of e.g.sleep(2), this will sleep & clear the cache and give you fresh & valid data.
I know I'm saying MySQL a lot, but you can obviously replace that with Oracle, MSSQL, PostgreSQL, etc.
Stay up to date
You can track my blog
articles and
comments. You may also find my
bookmarks interesting. Or
Follow me on Twitter
Like this Article?
|
Your money is no good here, but you can boost morale by spreading the word! : ) |
tags: programming, php, daemon, PEAR
category: Programming - PHP - PEAR
read: 115,918 times






tagcloud
#173. Kevin on 12 August 2010
I want to build protection against this but I'm gonna need some code samples cause by the looks of it, Options.php already has it:
So I'm wondering how exactly you got passed that..
@ Tom Dexter: I'm having a hard time trying to grasp your problem without being able to look at & play with code. Have any?
You could also fork http://github.com/kvz/system_daemon, make the required changes, and send me a pull request.
That would work very well, actually.
#172. utahcon on 30 July 2010
I am sorry I didn't come back to report but I found the same thing as @chris. The init.d script that was written on Ubuntu was bad as it called the wrong name, or something (I don't recall now).
I had to puttz with the init.d to make it work properly.
#171. .: Pampa :. on 26 July 2010
I came here looking for PHP daemons (actually written in pure PHP code) and found a really easy to understand tut!
Hardly I've learned your troubleshoot tips, but good to let the newbies know.
... [more]
Congrats :)
#170. chris on 12 July 2010
are there any known problems with filelength? The appName in both cases was "logparser", just the filename/length differs..
#169. chris on 12 July 2010
First many kudos to your work, we've been playing around with some hand-written process controll mechanism here..
i'm experiencing the same behaviour as @Utahcon.. i'm using Ubuntu 8.04 and latest Version of System_Daemon from pear (0.10.3)
When i call
a 2nd instance is created, and so on.. the script also switches from background mode into non-background, according to the logfile..
i can reproduce this behaviour with your example snipped above, just removed the 3-run-limitation.
the script runs with user/group "0/0", got +x for execution.. and is started with root privileges..
hope this gives you an idea how to track this down.. :)
#168. Tom Dexter on 04 July 2010
By the way...I tried implementing an option to override that restart_syscalls parameter of pcntl_signal in System_Daemon as I discussed previously. The change wasn't difficult, but for reasons I can't figure out, it doesn't behave as it does in scripts not using System_Daemon (even scripts forked as children of a daemon). Here's the behavior I wanted:
If my daemon gets a TERM signal while it's waiting for a child process with pcntl_wait or pcntl_waitpid, I want to immediately cancel the wait call and jump to my TERM signal handler which can kill the child process. This is exactly how it works in other scripts (again, even is child scripts spawned from a script running System_Daemon).
... [more]
For some reason however in the script using System_Daemon, when the wait call is interrupted by the receipt of the TERM signal, the script continues past the pcntl_wait call through the current iteration loop. Worse yet, in the code past that wait call, calls to pcntl_wifexited() and pcntl_wexitstatus() using the status from the wait all act as though the child ended normally when it actually hasn't exited at all!...totally perplexing.
I finally gave up...that one has me totally stumped.
#167. ppafford on 30 June 2010
Running on CentOS 5, how do I fix this?
I have the script (No running as daemon) and is triggered by incoming SOAP request which I want to kick off the daemon to process this.
#166. Tom Dexter on 30 June 2010
System_Daemon::setSigHandler currently has no way to use that option. In the project I'm working on I was able to work around that by not using pcntl_wait, but rather relying on a SIGCHLD handler and a loop. It'd be a nice feature to allow for that. Again, I'd be willing to help with that if you want to email me. Thanks!
#165. Kevin on 29 June 2010
#164. Utahcon on 24 June 2010
I did a --write-initd and all went well.
start works just fine
but when I try to stop the script with
it seems to change reporting from the log to STDOUT and my Daemon keeps running.
Ideas?
#163. Kevin on 10 June 2010
@ Mike: pcntl extensions are essential for the forking to work. You need PHP to support that.
@ Tom Dexter: Good catch, awesome! Fixed it here: http://github.com/kvz/system_daemon/commit/d9c1ef4cbdee037d250ec614c6f56e25f77d6524 and will be part of next release cycle.
#162. Tom Dexter on 28 May 2010
Thanks again!
#161. Mike on 26 May 2010
<CODE="text">PHP Warning: PHP Startup: Unable to load dynamic library 'usr/lib/php5/20060613/pcntl.so' - /usr/lib/php5/20060613/pcntl.so: cannot open shared object file: No such file or directory in Unknown on line 0</CODE>
The pcntl.so file does not appear to exist in that directory. Any idea why it is trying to call this file? And, why it doesn't exist there?
#160. ilovebonnie.net on 24 May 2010
Thanks much for the great PEAR class. I found this to be incredibly useful and well-written. Unfortunately, I had a hard time figuring out what options I needed to set in order to get permissions issues dealt with. Particularly, I found it hard to find information about how to set the location of the log file or the pid file that you wanted the daemon to use.
I wanted to come here to let you know I wrote a little blog post about how users can set those options in case they are having similar problems due to permissions:
... [more] http://www.ilovebonnie.net/2010/05/23/log-file-location-and-pid-file-location-settings-for-the-php-system_daemon-pear-class/
Thanks again!
-ilovebonnie.net
#159. steve on 23 May 2010
I modified the script to with the following:
#158. Student Brands on 22 May 2010
#157. Daniele Palumbo on 20 May 2010
i wish to know the best way to execute System_Daemon from web (exec? directly via browser?).
with system() seems not to fork, going into timeout after a while (php timeout).
... [more]
Also, i HAVE to set "runAppAsGID" and "...UID", but i am starting it from web...
thanks,
s.
#156. Kevin on 15 May 2010
removing that should make them 0 as well.
#155. Petri on 09 May 2010
By default:
'appRunAsGID' => 1000,
'appRunAsUID' => 1000,
... [more]
In CentOS, I had to change these to:
'appRunAsGID' => 0,
'appRunAsUID' => 0,
root has id and group = 0.
Now, this could potentially be a security risk if the daemon runs as root, therefore I suggest using the 0 values only when creating the startup script, and then use some other user values in actual run.
#154. Brian René Jensen on 02 May 2010
I just wanted to thank you.
Great post - Very useful to me.
... [more]
I'm great at PHP, but bash doesn't really apeal to me. This way, I can write a ton of code to monitor my Ubuntu server with email statistics.
Thanks allot.
Bwyan
#153. Kevin on 29 April 2010
#152. Manuel de Ruiter on 24 April 2010
Without: 99.9% CPU is in use and with 0.0% CPU is in use. Also did some checks with sleep and usleep and now it works like a charm. Thank you Kevin!
#151. Kevin on 24 April 2010
@ Rsk: And this does not happen when you run the init.d file it from the console?
@ Manuel de Ruiter: I don't see a sleep, let a alone a System_Daemon::iterate in your while loop. That will definitely exhaust your system's resources
#150. Manuel de Ruiter on 21 April 2010
#149. Manuel de Ruiter on 20 April 2010
It's been a while since I visited you're tech-blog, but I'm facing the problem that the 'daemon' that I create consumes to much CPU.
I've got a VPS with Debian Lenny installed and default the load of that machine is ~0.15 (5 minutes). But when I activate the daemon the load of the machine goes up to 100% CPU usage. (Got one VCPU clocked at 1.8Ghz and have 2048MB RAM). The weird part is that it doesn't consume that much RAM (0.1% to 0.2%).
Here a little example of the output:
I'm running the daemon under the lighttpd user cause that area is chrooted. Let me describe what I've done so far.
- Used the iterate and raised it up to 60s
- Checked my codes for leaks
- Modified the daemon code to minimum
- Made a blank daemon (only with the while)
- Set options manually
- Changed System_Daemon version
Example: http://pastebin.com/3HytDKpp
Let me know!
#148. Rsk on 20 April 2010
I used the example script and added the php code as mentioned. And made it as a daemon and restarted the machine. On booting time the system waits for this process to execute , it keeps waiting over there until i remove it from the init.d.
Am i doing it right ?
#147. haguey on 06 April 2010
Thanks for you reply, it turns out the problem is that procfs on debian stores truncated process names...
so that if the daemon process name goes over 16 characters, start-stop-daemon will not find it using the -name option...
... [more]
check /proc/<pid>/stat to see if the processname is truncated. I guess other people unable to stop their daemon might have this problem.
#146. Kevin on 04 April 2010
@ Adi: Too bad.. If you share code we might be able to actually establish what's going wrong and maybe fix bugs whether on your or my part.
#145. Adi on 01 April 2010
#144. Haguey on 29 March 2010
when I issue ps ax I see my daemon running as:
/usr/bin/php -q /home/haguey/hagueyd.php
... [more]
The problem is that when I try to use /etc/init.d/haguey to start and stop the damon it never gets the correct process name.
it's trying to do TERM hagueyd and not TERM /usr/bin/php -q /home/haguey/hagueyd.php
Any ideas what I could be doing wrong?
thanks in advance!!
#143. Kevin on 24 March 2010
@ Jocko: While I cannot reproduce this, this has been reported as a bug:
http://pear.php.net/bugs/bug.php?id=17254
... [more] And this is my proposed fix:
http://github.com/kvz/system_daemon/commit/11abe6dfb10888c82087c89554bf4db169a23cc7
#142. dave on 24 March 2010
#141. Jock0 on 23 March 2010
Thank you for this helpful guide. I am trying to run a socket listener as a daemon, but get the following lines in the log file:
[Mar 23 16:30:00] notice: Starting socketdaemon daemon, output in: '/var/log/socketdaemon.log'
[Mar 23 16:30:00] info: Changed identify to 'root':'root'
[Mar 23 16:30:00] warning: [PHP Error] pcntl_signal(): Error assigning signal [l:1304]
... [more] [Mar 23 16:30:00] emerg: Unable to reroute signal handler: 0 [l:1308]
[Mar 23 16:30:03] notice: Starting socketdaemon daemon, output in: '/var/log/socketdaemon.log'
[Mar 23 16:30:03] info: Changed identify to 'root':'root'
[Mar 23 16:30:03] warning: [PHP Error] pcntl_signal(): Error assigning signal [l:1304]
[Mar 23 16:30:03] emerg: Unable to reroute signal handler: 0 [l:1308]
What is the problem, and how could it be fixed?
#140. Kevin on 18 March 2010
To circumvent you can either use the force argument -f, or append the state like: System_Daemon-beta so the installer knows that you know what you are doing : )
#139. Menderezz on 18 March 2010
Here is the actual shell output:
pear upgrade System_Daemon
... [more]
Failed to download pear/System_Daemon within preferred state "stable", latest release is version 0.10.2, stability "beta", use "channel://pear.php.net/System_Daemon-0.10.2" to install
Cannot initialize 'System_Daemon', invalid or missing package file
Package "System_Daemon" is not valid
upgrade failed
Regards
#138. Kevin on 17 March 2010
http://github.com/kvz/system_daemon/blob/master/examples/signals.php#L56
#137. Gareth on 17 March 2010
#136. Kevin on 17 March 2010
@ Gareth: Looking at the code samples you've provided so far, I only see you routing signals to the default handler, instead of your own. Did you have a look at the logparser example? It shows you how to route signals to your own functions.
@ Menderezz: Monit can look at pid file & check if the socket is open. I don't know but maybe that's already enough for your purpose? Check this sample config:
#135. Menderezz on 17 March 2010
it is a socket application that awaits connections and that's why it was timing out when I tried to stop, so I made a checkup in the script so before it starts to listen again, it will check if it's time to sleep :D
All I have to do now is to make this code report it's status, so I can at least use MONIT and restart it, if it stops for some reason.
#134. Gareth on 16 March 2010
#133. Nathan on 15 March 2010
#132. Kevin on 15 March 2010
Hey guys: "Version 0.10.2 of System_Daemon has been successfully released, and its promotion cycle has started."
I hope this fixes all of your issues. Please come back to me if it doesn't, and thanks for your time reporting this!
#131. Austin B on 15 March 2010
@Bucanero: I got the same error and found the cause not sure how to fix but commenting it out seemed to work. Check out the bugs listing on the Pear project page.
#130. Gareth on 15 March 2010
I have also used various different constants to try and catch the correct signal but it just seems to ignore them all.
#129. Kevin on 14 March 2010
About the init.d file not working, that's weird. If you're sure it's not your code and you're running the latest version of System_Daemon you may file a bug report against PEAR and we'll take it from there.
@ Gareth: Yes it will do that automatically, if you want any other behavior you can overrule the signal handlers to perform any task you like.
... [more]
Ah ok. About your Array,Array error; this is in the latest version? If so, please file a bug report at PEAR
@ Bucanero: Agreed, you should be able to upgrade. To troubleshoot, it would help a lot to echo which signal it is trying to bind, that doesn't work on your system.
@ Ulrich: Awesome!
@ Edmund: There's nothing like that in System_Daemon at the moment. It just does a straight forward fork of itself and that's it. You may want to look at PEAR's Fork class, or use the pcntl functions to build it yourself. If you have clear ideas on how to implement this in System_Daemon I'd be happy to review any patches you may (or may not) build.
#128. Edmund on 03 March 2010
I need to query a DB and each record that is returned needs to be processed individually but timing is important so I need the ability to asynchronously process each record.
If this is possible, are there any function calls specifically for this purpose?
... [more]
Thanks in advance for any info on this topic.
#127. Ulrich on 02 March 2010
a little feedback for my issue (#107)
It works !
... [more]
the problem come from the face I use __autoload and not spl_autoload_functions(). So my autoload function is ignored after I include the Daemon file
thanks for your help.
#126. Gareth on 02 March 2010
Can only overrule on of these signal handlers: 'Array, Array, Array, Array, Array, Array, Array, Array, Array, Array, Array, Array, 1, Array, Array, Array, Array, Array, Array, Array, Array, Array, Array, Array, Array, Array, Array, Array, Array, Array, Array, Array, Array, Array, Array, Array'
My code now is :
[code="php]
require_once("System/Daemon.php");
System_Daemon::setOption("appName", "name");
System_Daemon::setOption("appDescription", "Description");
System_Daemon::setOption("authorName", "Name");
System_Daemon::setOption("authorEmail", "mail@mail.com");
System_Daemon::setSigHandler(SIGKILL, array("System_Daemon","defaultSigHandler"));
if (!System_Daemon::isInBackground() && !System_Daemon::isRunning())
{
$init_path = System_Daemon::writeAutoRun(true);
System_Daemon::start();
$sleep_time = 5;
while (!System_Daemon::isDying())
{
//Code to run per loop
}
System_Daemon::notice("Termination signal recieved, exiting");
}
[/code]
#125. Gareth on 02 March 2010
#124. Bucanero on 01 March 2010
I will like to stay up to date, how can I troubleshoot this on my dev servers, any clues what to look for first ?
And again, thanks for your great work
... [more]
Bucanero
#123. Menderezz on 01 March 2010
When the php script gets started as a daemon, and if it has the command to autocreate the script in /etc/init.d/app_name it's not showing the status of the daemon. For my example, it says that app_name is stopped.
The question is: is it possible and how, to make the php daemon report it's state, if it's working or not, and I always have to "kill -9 PID" the "/etc/init.d/app_name stop" command doesn't work and it times out.
... [more] Once again, this project is just perfect, I only need some help with mentioned things.
Cheers!
#122. Kevin on 28 February 2010
#121. Bucanero on 28 February 2010
I'm getting the following error on the logs:
[Feb 27 19:03:32] info: Changed identify to 'daemon':''
... [more] [Feb 27 19:03:32] warning: [PHP Error] pcntl_signal(): Error assigning signal [l:1289]
[Feb 27 19:03:32] emerg: Unable to reroute signal handler: 0 [l:1293]
Any clues ?
Thanks
Bucanero
#120. Kevin on 26 February 2010
Checkout the signal handling stuff.
Or just let system_daemon generate an init.d script and and let that send the POSIX signals for you.
#119. David James on 26 February 2010
One question I have, is there any way to signal the daemon to shutdown or a graceful way of shutting it down, instead of kill or Ctl-C (for no-daemon variety)?? I'm thinking you could have a "flag" file that the daemon monitors, if the file is deleted then the daemon finishes up and exits. Any other ideas?
#118. Kevin on 24 February 2010
Changing socket paths of your Mysql server has Nothing to do whatsoever with my PEAR class and should be avoided if you are indeed a newbie.
#117. juan on 24 February 2010
I found it very useful!!
I'll try more and send you some feedback.
#116. nadir on 24 February 2010
where should i do that??
pls help.... its quite urgent too..
(sorry i am a newbie,excuse my mistakes)
#115. Kevin on 24 February 2010
It's in this commit:
http://github.com/kvz/system_daemon/commit/e82ba977cc71cf490f4ede4f58f2be30a757f6e9
and will be part of the next release.
If you can't wait just could download the source files directly from github, but remember to download all of them as they are dependent & I changed some more things in them
#114. Kevin on 21 February 2010
Was there anything in particular you wanted to see comitted?
@ Peter: Does this happen during a restart or something?
... [more] @ Ben: What if you don't set the SIGCONT handler?
@ helpful guy: Thanks, and there is no way to have the different pid location? Cause yours creates problems on itself (related to permissions, it needs to be inside an owned subdirectory)
@ Ulrich: __autoload functions are stacked. So if System_Daemon's can't load your class, the autoload function that was registered before that is called. Maybe somehow our autoloads conflict. You could add debugging information to the Daemon.php file inside the static public function autoload($className) function, and in yours, to see what paths are traversed in order to include the classfiles.
@ Diana: You could have a look at node.js, seems perfect for what you are trying to achieve.
@ Urda: You should be able to do that, something is wrong. Do you have more debugging output?
@ Warren Trucker: Any chance you have more details on that, or maybe you can share your code somewhere?
@ bertoli: You should run it as root, not sudo, but thanks for sharing!
#113. sameer on 21 February 2010
#112. bertoli on 14 February 2010
I did a:
chmod a+w /etc/init.d
... [more]
so the init.d file for the script was sucessfully written. Later changed back to:
chmod go-w /etc/init.d
to keep persions as before...
#111. bertoli on 13 February 2010
Directory: '/etc/init.d' is not writable. Maybe run as root?
Unable to create startup file. [l:835]
unable to write init.d script
... [more]
my 'etc/init.d' directory is:
drwxr-xr-x 2 root root 4.0K Feb 10 20:25 init.d
my script is root owned, as I did:
chown root myscrip.php
I also used: sudo to run the script but same error got and init.d is never generated...
any suggestion?
#110. Warren Tucker on 08 February 2010
#109. Urda on 03 February 2010
I get FATAL ERROR: CALL TO UNDEFINED FUNCTION if I try that. How can I get around this and still log to the system Daemon?
#108. Diana on 02 February 2010
I would like to help me or guide me, my question is this I hear dmonio create a port and turn the information as received by the port to be stored in a database or text file. Any of you could guide me? Se los agradeceria enough, I thank you very much Greetings advance Diana
#107. Ulrich on 27 January 2010
Congratulations for System_Daemon, great job !
I have encountered an issue, maybe stupid, but I can't find why.
... [more]
I try to use System_Daemon inside my class system which used __autoload() to get the classes. I need to because of our environment
But if I call a class right after the require_once "System/Daemon.php", even if the deamon is not started, I can't call any of my classes. Is that something wrong (I mean, using Daemon and __autoload?)
#106. helpful guy on 26 January 2010
wasnt working for me on fedora 9
I added the option
"appPidLocation" => "/var/run/mydaemon.pid"
... [more]
and removed the arbitrary restriction from
/usr/share/pear/System/Daemon.php in _isValidPidLocation where it does an arbitrary check to force the pid file to a location which isnt checked by /etc/init.d/functions 'status' function.
Anyway, now it works great :)
#105. Ben on 18 January 2010
[code=dtest.php]#!/usr/bin/php -q
<?php
require_once "System/Daemon.php";
System_Daemon::setOption("appName", "Daemon_test");
// Overrule the signal handler with any function
System_Daemon::setSigHandler(SIGCONT, array("System_Daemon",
"defaultSigHandler"));
System_Daemon::start();
while (!System_Daemon::isDying()) {
System_Daemon::iterate(3);
}
// Shut down the daemon nicely
// This is ignored if the class is actually running in the foreground
System_Daemon::stop();
?>[/code]
#104. Peter on 13 January 2010
This only occurs when the same daemon script is called again, while a child process is still running. It seems non-nonsensical to me, since it acts like the parent was still running, and wants to kill it. Then right after that discovers the parent wasn't running and no longer wants to kill it.
Why is it doing this?
#103. Urda on 12 January 2010
#102. Kevin on 13 December 2009
php ./daemon.php?
If it works, you need to chmod u+x daemon.php and maybe put /usr/bin/php in your /etc/shells and maybe put #!/usr/bin/php -q in the head of your script.
#101. David Heremans on 10 December 2009
I'm very impressed with this article (in fact had it in my favourites to check out for a long time already...)
I decided to go give it a go now, but I can't get it to work.
It's giving me the following error:
Any idea what might be causing this?
#100. Kevin on 06 December 2009
You can change it and write another file. be sure to use the latest version
#99. jatrn on 18 November 2009
Check line "PIDFILE=/var/run/$NAME.pid" (in /etc/init.d/whatever). I had to manually change it to /var/run/$NAME/$NAME.pid, verify location of pid file in /var/run
#98. rana on 09 November 2009
#!/usr/bin/php -q
<?php
require_once "System/Daemon.php"; // Include the Class
... [more]
System_Daemon::setOption("appName", "ct"); // Minimum configuration
System_Daemon::start(); // Spawn Deamon!
$path = System_Daemon::writeAutoRun();
while(1)
{
sleep(5);
}
?>
why i cant start/stop the daemon using sudo /ect/init.d/ct start or stop ??
i'm using ubuntu 8.10 and daemon is running nicely using sudo ./daemon.php
#97. Kevin on 08 November 2009
#96. Sun Location on 07 November 2009
I've try the application but I have this error : MySQL has gone away
#95. jatrn on 26 October 2009
thanks a lot
#94. Kevin on 25 October 2009
http://article.gmane.org/gmane.comp.php.pear.devel/48419
After that, life should be sweet for you guys
@ Kees: There has to be some logging or something otherwise growing going on in your code. Cause if you run System_Daemon without custom code, this does not happen.
... [more]
@jatrn: I will change the log level to DEBUG, so that you can then choose to turn off debug logging, how does that sound?
#93. jatrn on 24 October 2009
info: phpvoices daemon received signal: child.
Since my PHP script is a constant loop (with 1 second sleep), I'm getting entry to the log every second. Is there any way to turn this notification off?
... [more] Thanks again for this package.
jatrn
#92. aeuglein on 20 October 2009
#91. wregen on 18 October 2009
Can you provide a simple example? This will help me a lot.
Thank you.
#90. Kees on 17 October 2009
I'm using our solution to create several daemons ( 20 + ) which communicate with each other thru spread (ipc), however, when creating more then 12 daemonson one server, it seems that the cpu usage dramaticly increases(measured thru 'top' ), is that something you are aware of, or is this something php specific ?
#89. Kevin on 09 October 2009
@ Joe: Thanks for the comments, np. Would it be possible for you to share the code somewhere? maybe pastebin? I'm having a hard time doing all this in my head. Give me something to test with and we can take it from there
#88. Joe on 30 September 2009
First, I tried putting some cleanup immediately after the main loop. Even if I send SIGTERM to the main pid, I never seem to make it out of the loop to do any cleanup. Nothing gets logged.
Second, I set up my own handler for SIGTERM. In here, I look at the value of $child which points to our child process object (wherein there is a shutdown function). However, $child is null!
... [more]
This could be a result of the process forking, and the handler is really occurring in the pre-daemon world. If that's so, how do I communicate to the other side to shut things down gracefully?
(Apologies for the multiple stream-of-consciousness posts! Maybe someone else is having the same issue though, so this might help.)
#87. Joe on 30 September 2009
#86. Joe on 30 September 2009
I did try setSigHandler for SIGTERM, and my function _does_ get called, but the loop keeps on going. I guess I could set runningOkay to TRUE but this isn't an error condition we're bailing out of. :-o
Clues welcome/appreciated!
#85. Joe on 30 September 2009
In my case I'm using this for a monitor that dips into a data store every ten seconds. The monitor launches a child process to munch on said data. Now, this process is best kept open for a prolonged period, only to be closed after 60 minutes of inactivity (although if we absolutely have to shut it down, that's fine too).
That's where the problem is, shutting it down. If I send TERM to the monitor, it won't go away until that child process shuts down. However, in the monitor, the last thing I do (once isDying() is true) is exit my loop and check for that child process. If it's around, we tell it to exit. I never get to that part though. It' s as if isDying() isn't returning TRUE after sending TERM to the daemon. Hmm ...
#84. David on 23 September 2009
Good lib. Just wondering if you can give me some advice about spawning children from within the daemon. Essentially I want to start x instances of the daemon, that run (looking for jobs from a Gearman server) for the entire time the daemon is running.
This may not be the best approach. I imagine that spawning children AS work/jobs come into the daemon would be a more efficient, however I haven't been able to get that working with System_Daemon yet.
So far this is what I'm doing (and seems to be working) and I'm wondering if there are any problems with something like the following:
I understand that potentially if the children exit they could become zombies, however I'm not sure if that applies in this situation as I want the children to run for the life of the parent (daemon).
Any help / guidance would be greatly appreciated.
#83. Kevin on 17 September 2009
You could even also leave out the operating systems you're not planning on using.
But on the other hand: if you're going to need multiple files anyway, why not just add the entire dir. It will really only add a few kbs.
#82. Remiko on 12 September 2009
#81. Kevin on 22 August 2009
@ Kris: Autch.. Love your gravatar though :)
#80. Kris on 13 August 2009
#79. Kris on 13 August 2009
Extension './daemon.php' not present
I have no clue how to solve this... the script ran the first time.
#78. Jason on 12 August 2009
#77. Kevin on 12 August 2009
http://brian.moonspot.net/php-fork
#76. Peter on 08 August 2009
I'd like to use your class for as job scheduler daemon in PHP where I have the daemon run various jobs throughout different times of the day. I'd like the daemon to simply spawn each job in a child process and go back to being a daemon without each job running within the daemon's process. How hard would this be to do without interfering with your class?
Thanks
... [more]
How hard would it be to have some of the code running with the daemon
#75. Sean Hess on 04 August 2009
#74. Kevin on 04 August 2009
#73. Easy Daemons in PHP on 03 August 2009
#72. Kevin on 29 July 2009
#71. Bucanero on 29 July 2009
Thanks for your reply
I figure out the "Who are you?", it was because on my box I did not have a user with uid 1000 or group with id 1000. As your example had
... [more]
Another question, How can I know from php that my daemons are running ?
Running ps uf -C from the console I can see they are running, is there a way to have this info via php ? I need to write a monitoring script
Thanks again
Bucanero
#70. Kevin on 28 July 2009
Start your daemon with an argument like:
./yourdaemon.php a
... [more] and configure your appName at runtime to adhere the argument 'a'. Now when you write an init.d file or pidfile, 'a' will be used.
This way you can have as many daemons as you want with own logfiles, pidfiles & init.d files, but with 1 script.
#69. Bucanero on 28 July 2009
I was wondering how to create "multiple email generation daemons", My idea is to have 10 (or more if we have bigger loads) of this all the time running and looking for emails to create and send.
The problem I was encountering is that if I try to run the same file again (starting another one from the console) I receive and error message. One option is to have files from to 1 to x (example daemon1.php ... deamon2.php) do you think this make sense ? Is this the way to go ?
... [more]
Also running your example, I got 3 times on the console " Who are you?"
Thanks again for this
Bucanero
#68. Kevin on 15 July 2009
http://trac.plutonia.nl/projects/system_daemon/changeset/228
It will be included in the next package release.
... [more] If for follow ups on things like these you could use the official PEAR bug system, that would be awesome.
#67. AkEdEv on 13 July 2009
I just run your example on php 5.3.0 and appears this line.
PHP Deprecated: Function eregi() is deprecated in /usr/share/pear/System/Daemon/Options.php on line 250
#66. Kevin on 07 July 2009
If you want to control a daemon's start / stop you typically would do that with a script inside /etc/init.d (os dependent, for some OSes, System_Daemon can generate such a script for you)
So, yes in theory you could then use a PHP script to control run the init.d script and control your daemon process. But I'd hardly recommend it because of
... [more] - bad practice
- security risks involved
#65. dulig on 07 July 2009
Thanks for this great article.
I think about using your daemon in my web application.
This might be a stupid question, but since the daemon can only be started out of command line, will it be possible, to do a shell_exec to start the daemon out of a web application?
... [more] Thanks in advance
dulig
#64. Kevin on 26 June 2009
But I'd rather have people use my iterate() function so that I can implement additional fixes as I find more issues.
@ Martijn: You could also use cron combined with solo (http://timkay.com/solo/) to prevent overlap and do what you want. If you need more control / intelligence on the other hand, you may need to fire actions and keep track of time yourself.
I have once seen a full table-based cron implementation in PHP, I'm sure you'll find it if that is what you need. Or maybe a simple
#63. Martijn on 21 June 2009
I think it's better solution then using cronjobs. Only wondering, i have to do a daily job, processing books. (about 2.000.000 records) Maybe i missing something, how to do a daily update, depending the content of a certain folder?
I'm istill depending on cron or can you give some hints to solve the problem?
... [more]
regards Martijn
#62. jonathan on 19 June 2009
is clearstatcache () broken?
I've been using this successfully, but did I miss something?
#61. Kevin on 18 June 2009
#60. Adam Charnock on 15 June 2009
This is really great work, thank you very much. We are going to be using it extensively in the backend of the next version of walltweet.org.
I did notice this:
... [more]
"On success, this will return the path to the autostartup file: /etc/init.d/logparser, and you're good to go!"
... which isn't actually correct. It seems to return boolean, not a string. Just a minor point!
Thanks again :D
Adam Charnock
#59. Kevin on 15 May 2009
#58. vince on 15 May 2009
thanks for the reply. I haven't yet installed the pear class because I think that I have to install first the pcntl support. But maybe it's unnecessary... Your pear class isn't based on php-pcntl functions?
#57. Kevin on 14 May 2009
@ Mike: Sorry I don't know PHP_Fork, I only know of it.
@ mikesta: thank you :)
... [more]
@ vince: I've tested up until Ubuntu Intrepid and those all work out of the box. Can you give me some exact output/errors?
#56. vince on 13 May 2009
I would like to start creating some funny daemons in php so I have installed a LAMP + php5-cli on an ubuntu 9.04 system.
But I have no support for pcntl yet! How can I do? Can you suggest me a guide?
vince.
#55. mikesta on 02 May 2009
#54. James on 01 May 2009
#53. Mike on 30 April 2009
Thanks for your help!
#52. Mike on 30 April 2009
@Kevin - I looked at that php_fork PEAR package. I'm pretty new to PEAR, but I couldn't even get the basic.php to run - doesn't even throw an error I can diagnose.... I know PEAR is good on my server as I'm able to execute your sample code fine.
Thanks very much for any help you can provide, but I don't want to be a bother...
#51. James on 30 April 2009
To control those forked daemons, it seems possible to do the following: insert each daemon's PID into a MySQL table, and have each daemon update MySQL every several minutes informing you of what it's up to. You could then see what's going on with each daemon child via a browser interface, and kill the child if needed.
At least, in my head, that makes sense. But I haven't committed those thoughts to code.
#50. Kevin on 29 April 2009
@ Mike Stackhouse: I've found an unmaintained PEAR package: Fork. Maybe that can do what you want. I didn't have plans to make this a system_daemon feature as I've always felt that it should be a simple and basic building block. What do you think?
#49. Mike Stackhouse on 27 April 2009
We have the requirement to have a daemonized server process that would fork off children based on control records in a database. Does your class have functionality to fork off children, keep track of their process id's and kill them if need be?
Still trying to wrap my head arounc pcntl - I might be over-thinking the problem. Could it be as simple as implementing in a database reading loop, and when a new child is needed execute the fork at that time? There are some good examples on the web for managing child processes from that point forward - this one seems to make sense - http://www.van-steenbeek.net/?q=php_pcntl_fork.
... [more]
Might you know of any examples that would have functionality such as we require?
Thank you very much!
#48. James on 25 April 2009
#47. Tech Blog on 20 April 2009
#46. Kevin on 19 April 2009
That way I could implement self checks from within the ping method, depending on the configuration you specify.
It could be an interesting addition. As far as advanced communication goes. You could look into Net_Socket (also pear) and/or go for TCP/IP.
Another method would be a central memcached server or actual shared memory using shmop (but that's limited to 1 machine).
Non of these things and methods are standard in System_Daemon however. It merely provides the most fundamental brick for others to build upon.
But if you like to share what you've come up with, give me a ping. I'm not sure yet but maybe we could generalize it and add a little sauce on top of the daemon.
#45. Saso on 19 April 2009
Well, it doesn't help me much :)
Probably I will use Ur project and upgrade it with my ideas and send it back to U, for U to make world use of it :)
I would need sync and async communication between processes, so front-end and daemons can 'talk' with each other. Self-observing would also be necessary, to avoid wild daemons eating resources.
I, for example, need this to make chat bot, which will be daemonized and frontend interfaces (IRC, PHP, what-ever..) will ise it for 'chat API'.
... [more] This is great to avoid the overhead of creating and killing all the objects in heavy front end.
But I agree, for mass mailing, writing to DB is enough.
Regards, Saso
#44. Kevin on 19 April 2009
@ Janitha Karunaratne: An ideal daemon in an ideal world would not be written in PHP, I make that clear in the article already. But you actually make it sound immoral :D
Don't be alarmed.. My house is built with good old bricks: not forks & spoons. And yes some of my daemons are created with PHP. Why? Because it works. Because I can use my existing classes and take away load from front-end processes built on the same technology.
... [more]
I feel like using 4 different languages to solve 1 problem is really about creating 1 thing and 1 thing only: a maintenance hell.
If I am to redo my existing classes in C (or perl or python), I will have to duplicate my patches & improvements for the rest of my programming career...
To justify this decrease in productivity there would have to be some very convincing reasons for that. And your (funny but) dogmatic metaphor is not going to cut it.
I don't believe you're not basing your opinion on actual results.
I have PHP daemons running for over 2 years now without a problem. I understand you may get an unary feeling but I'm pragmatic and this is actually working very well.
Anyway, nobody is forcing you to use this, so Happy compiling :)
@ Saso: You could work with a database queue, storing heavy jobs and having daemons eat them away using the same DB class as your frontend process.
Deamons are already limited to 1 per 'appName', and for simple communication you could use POSIX signals. Does this help you out a bit?
#43. Saso on 18 April 2009
I am searching for IPC (Inter Process Communicating) for using with Ur Daemon.
I would like to change architecture of my app. to lighten frontend and have heavy duty daemons to do all the work.
... [more] What I find missing (from my point of standing) is automated limiting daemon loops, number of daemons and some mechanism for maintaining pre-forked processes, ready to use (similar as Apache2).
This is needed just due bad PHP-coding practices, to avoid leaked code eating all resources.
And I miss Remote Procedure Call, as stated above: It would be great to have daemoned API, which we 'just use' in our PHP frontend.
Regards, Saso
ps: dont get me wrong, Ur work is just great, I just give U some new ideas.. :)
(aka. being lazy-constructive)
#42. Janitha Karunaratne on 16 April 2009
PHP is meant to be started quickly and killed quickly (such as a page view) and that's what it's memory management is optimized for for the duration of the script... if you run it for prolonged periods of time, expect some seriously nasty memory usage and leaks.
Your reasoning for this is that everyone knows it and it's availability everywhere... this is where I have to disagree. That's like saying "Hey, lets build this house using spoons and forks, because everyone knows how to use them and their everywhere!". It's possible, but it's a very poor choice.
... [more]
Just because it's the only thing a person knows or just because it exists everywhere doesn't make it the proper tool to use.
#41. Yılmaz Uğurlu on 13 April 2009
But i still didn't create startup script correctly. I tried mant things, i guess i have problem with my ubuntu box, whatever.
I wrote feed crawler daemon for test. It's fecthing and writing feed items to databse. I watched very long, and everyting went well. Cpu usage, memory usage, all my concerns are gone. Thank you so much this is really great application.
#40. Kevin on 12 April 2009
It looks though as if you really really don't have permission to write anything to init.d
What if you 'su -' first and then really run it as root instead of sudo-ing it?
About the 3 times thing. Are you using the logparser example? That shuts down because it's only a test.
If you just put a
It should run indefinitely. Unless you run into any problems like stated in the troubleshooting section
#39. Yılmaz Uğurlu on 12 April 2009
First:
in OS.php line 297 and line 299 must be self::isWritable(...)
because i get this error fist:
and i changed these lines.
So, after i run my daemon just like: sudo ./myDaemon.php
It went well but, when i looked at the log file i showed these errors
I have one question more, i didn't add the System_Daemon::stop(); line to end of my file.
Bu after 3 times loop my daemon is stopped. i guess i didn't understand how to write endless daemon, how can i do that?
#38. Kevin on 12 April 2009
#37. Kevin on 12 April 2009
http://svn.plutonia.nl/projects/system_daemon/browser/trunk/System/Daemon/OS.php
Are you able to confirm this works? If so than I can release a new PEAR package for System_Daemon
#36. Yılmaz Uğurlu on 11 April 2009
I have question about startup file. I'm runnig as root my script, after the start i'm checking log file, all script start's has this two line.
But i'm running script as root, what i'm doing wrong?
#35. anon on 07 April 2009
a php daemon, with plugin type arch.
#34. Kevin on 03 April 2009
#33. ger on 02 April 2009
The only thing I can say from my experience - php seems have memory leaks when works in infinitive loop. Even if he php code itself is well designed to pervent this. If you'll monitor the memory consumed by your php daemon - you will see it continuously grows in time.
The solution of this prob I use - juts kill / restart the daemon with cronjob from time to time.
Hope this will be useful for someone.
#32. Dani on 25 March 2009
Sometimes PHP can be the ideal choice to run such things. If you have some LAMP environment with PHP handling your data in the first place and you need some background process it is the best choice to use the same environment for that process instead of risking to corrupt your data because of compatibility issues like character-encoding.
#31. Kevin on 16 March 2009
@ rhuel: This is not going to work on shared-host-environments, because you need to be root to fire up the daemon. Only after you start it, it can become another user.
This is because root will have to setup some dirs like logdir & rundir, and chown it all.
#30. rhuel on 16 March 2009
#29. jatrn on 11 March 2009
First of all thank you very much for this lib, it is very usefull.
I got a small problem. I'm able to start my daemon by "/etc/init.d/IMM15 start" but can not stop it, "/etc/init.d/IMM15 stop" doesn't work. There is nothing in the log and on the screen. See my code below.
Thanks for you help.
... [more]
#!/usr/bin/php -q
<?php
require_once "System/Daemon.php";
System_Daemon::setOption("appName","IMM15");
System_Daemon::setOption("appDescription","simple deamon by jatrn");
System_Daemon::setOption("authorName","xxx");
System_Daemon::setOption("authorEmail","xxx@yahoo.com");
System_Daemon::start();
System_Daemon::writeAutoRun();
while (true) {
$t=1;
sleep(10); }
System_Daemon::stop();
?>
#28. Kevin on 04 March 2009
#27. Eduardo Jordan on 03 March 2009
I wonder why facebook, a multibillon dolar company, uses it!
Kevin, I gonna use this class and will give you feedback.
About the perl guy. FYI, PHP has syntax similar to Perl, just simpler to understand.
... [more] I guess that for Perl programmers:
my @lines = <FILE>;
while (<FILE>) { print $_; }
that is nice, and this horrible
$handle = fopen('datafile.csv', "r");
while (!feof($handle)) {
$buffer = fgets($handle, 4096);
echo $buffer;
}
fclose($handle);
I don't think so, second one is easier to read and understand.
#26. Kevin on 02 March 2009
Let me just say: Nobody is forcing your hand here.
But I think your vision on this matter does not include factors like: time, resources, and company context.
... [more] For instance at my company, there is no (need for a) C programmer at all. There never was and there probably never will be. But we still have the need to automate a lot of thinks that are based on our PHP software.
Perl just doesn't play well with our LAMP environment. For instance we have many libraries & classes that the automating daemons need to interface with. And I was not planning to recreate & maintain all of our business-logic (no, this is not in CPAN unfortunately ;) in two different languages. I value DRY principles too much for that.
So I've been running PHP daemons for years now (it took a while before I submitted to PEAR) and without any problems. And so for me it's safe to say: it solves more problems than it creates.
#25. Anon on 01 March 2009
Hey, Anon here (the one you responded to). I seemed to stumble upon this post again~
Let me reemphasize that it is interesting that PHP can do this, but for obvious reasons it should not. PHP is an awesome language in which quick websites can be easily created due to it's ease of use and availability.
... [more]
Other than than, to put it bluntly, it sucks. It is truly a horrible language. There is little point in debating that point here so please don't. (If you really want to debate, use a search engine to find essays about PHP and it's..erm..attributes.) (I am kind of cheating here; I go on to insult PHP and tell you not to argue :O)
I suppose when you have a hammer everything looks like a nail, but your three reasons to use PHP for creating daemons are not convincing at all.
"Reuse & connect existing code"
You should not be reinventing the wheel to begin with. If you must, there is Perl and CPAN.
"Deliver new applications very fast"
Yes, PHP has a lot of functions (too many), but Perl is better at creating applications quickly.
"Everyone knows PHP (right?)"
I already mentioned this point in my previous post, but I will do so here again (with a different approach). If your C programmer leaves, find a new C programmer. It is really that simple. If your Photoshopping person left would you resort to using Microsoft's paint? No, you would get a new Photoshopper. (Hypothetical situation is hypothetical, by the way.)
#24. Centerax on 13 February 2009
This is great stuff, in conjunction with Monit this is very powerful and easy to implement.
Great job!
#23. Kevin on 11 February 2009
I've left a comment at that URL.. Let's see how long it stays there ;)
Thanks a lot for letting me know Chris!
#22. Chris on 10 February 2009
#21. Ali on 10 February 2009
#20. Kevin on 01 February 2009
#19. Kevin on 01 February 2009
#18. Tom on 27 January 2009
#17. Strawp on 26 January 2009
Quick stupid question though: In your example above, is everything from ::start(); to the end of the script the child process? Is the parent dead at this point?
If for example I wanted to fork a slow script as a child from the action page of a web app but keep the parent running so that it could finish up and redirect the user, how would that look?
#16. Kevin on 25 January 2009
@ marek: That's not an issue.. Thats the solution TO the issue that you will lose the mysql connection if you don't.
#15. Douwe Kasemier on 23 January 2009
#14. Zach Blank on 21 January 2009
#13. Jason Moss on 20 January 2009
#12. Dustin on 20 January 2009
#11. marek on 20 January 2009
#10. Timothy on 19 January 2009
#9. wiwo on 14 January 2009
#8. Kevin on 13 January 2009
I suppose I forgot to say the obligatory:
Sorry for my bad English, it's not my native language.
... [more] But really, thanks. I want to improve my English and I will definitely take a look at it.
#7. Kevin on 13 January 2009
@ simeon: I agree PHP is not the best language for it, the article says something similar. But it's very well possible and even suitable in some cases.
From a design point-of-view you may be right about PHP. It probably wasn't meant to run that long, but:
... [more] - I haven't run into problems yet
- I believe PHP resource IDs are different from file descriptors
You do make in interesting point though: thank you.
#6. Kevin on 13 January 2009
But to do any real damage you would need root access to a Linux box in a production environment.
If you do: I hope you're at least responsible enough to know your own coding limits and not run your hobby projects on your company's main server. If you're not: your company's box is probably already destroyed, anyway. along with your job :)
#5. Matt Baker on 13 January 2009
http://owl.english.purdue.edu/handouts/grammar/g_comma.html
#4. simeon on 12 January 2009
PHP's process model was is inherited from the cgi days and is built around loading, executing, and terminating (and don't get me wrong. There are definitely advantages to this process model for web development). Running a PHP script indefinitely is likely to push up against the edge cases in the runtime engine...
The alternative approach I've taken when I need something more sophisticated than cron jobs is to make sure I have command line interfaces to my PHP business logic and write the daemon in python or even bash. The daemon can be extremely simple (listen on a port, tail a file, etc) and merely invokes the appropriate PHP script to handle all the business logic... Just my 3 cents.
#3. Anon on 12 January 2009
#2. Anon on 12 January 2009
"Everyone knows PHP (right?)"
Everyone knows how to grunt and point too. Sure, I find it interesting that PHP can do this, but please, there is horrible PHP code littered throughout the web. Please do not bring that to a lower level :(
#1. crackgerbal on 12 January 2009