» 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_STRICT); 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.
You probably shouldn't follow me
Like this Article?
| I'd appreciate it if you leave a comment, spread the word, or consider a small donation |
tags: programming, php, daemon, PEAR
category: Programming - PHP - PEAR
read: 254,471 times
tagcloud
#261. ouiea on 17 January 2012
I'm using Amazon's Linux (don't ask why) and I've been having the "No autoRunTemplateReplace found" when trying to create the init.d script.
In the end, I've ended editing the Daemon.php file
(located here in my install: /usr/share/pear/System ) and forcing RedHat as my OS:
search:
repace with:
I could write the init.d file after that.
BTW, it would be great to have a bigger window for the comments, I feel like peeping through a keyhole ;)
Thanks!
H
#260. Pawel on 12 January 2012
Generally works fine, however I have some problem with my daemon.
Daemon was supposed to run some instructions every 3 seconds, but thanks to logs, I noticed that sometimes it freezes for around 1 hour.
So logs:
... [more] ...
[Jan 12 08:52:59] info: running
[Jan 12 08:53:02] info: running
[Jan 12 08:53:05] info: running
[Jan 12 10:06:26] info: running //waits over 1 hours instead of 3 seconds
The pause is done with: System_Daemon::iterate(3)
Wondering if anyone had similar problem, or has an idea what might be causing it ?
Thanks
#259. Tom on 10 January 2012
It's a LOT better than cron. I'm calling a command line script which calls a php file. Writing a script to call that and trigger on cron just was a nightmare because the script had to execute from a specific directory. So this was much better because you don't have to worry about the directory change being lost due to sub shells, etc.
Two other things worth mentioning are Gearman and Clockwork. Gearman is not going to be something you really want to loop and use like a daemon, but it's related and is nice. Clockwork is a replacement for cron basically. It's Ruby, but you should still be able to use PHP to control it. I haven't looked into it yet because it just took a few more minutes to setup than this and this worked perfect...But may be worth a look.
#258. Benji on 07 January 2012
Thanks for sharing, you are a maven.
#257. Achim on 27 December 2011
The APC op-code cache is basically useless in PHP-CLI environment. If a PHP will be called regularly via cron, the op-code will be compiled every time again, even APC don't persist the cache over several processes.
But in case of a daemon, the op-code will be compiled only once and used for each "loop" again and again - even if APC is not used :-)
#256. Ivang on 23 December 2011
I was looking a way to avoid the (ethernal) use of cron and your post is the most useful article I found for months.
It probably gives some minor problem (like the previous comments) but it does not care, your little script for demonizing a php script is the best contribution to php since the MVC frameworks!!
... [more] Thank you very much
#255. Big Jim on 16 December 2011
It bizarrely loops through the script that makes the above call and gives this output 136 times:
Followed by this 136 times:
It doesn't actually start the daemon though. I'm running this on CentOS w/ the following small modification for writing the start script:
I've also noticed that /etc/init.d/logparser status (and restart) don't work. I'm guessing something is wrong w/ the init.d start script, but I can't figure it out. Any ideas?
Thanks
#254. Carl on 09 December 2011
If you get the "bash: chkconfig: command not found" and you already have it installed, just get it's location and run it from there:
[CODE=text"]
# whereis chkconfig
[/CODE]
I had to use:
[CODE=text"]
# /sbin/chkconfig --add myScript
[/CODE]
#253. Carl on 06 December 2011
Do the following if you want your daemon to run at system boot.
FYI: The following assumes that your script is called "logparser"
1.) Use your PHP script to write the autostartup files using the writeAutoRun() method.
!! Make sure "appRunAsGID" and "appRunAsUID" is set to 0 !!
2.) Add your script to the list of system services with:
3.) Don't forget to enable your service:
That should be all there is to it :)
#252. Barney on 02 December 2011
This has saved me a pile of work!
One problem though, on ubuntu (and i assume all debian systems) when i use the --write-initd parameter, i get a message in the log file that it wasn't possible to write to the /etc/init.d directory, and that i should try running as root.
... [more]
unfortunately i am already running as root!!!
any ideas?
#251. Roberto on 13 November 2011
Saludos !!!
Hello Great job related to the PHP Deamons, I want to donate via paypal but where ?
... [more]
Best Regards !
#250. Iser Epstein on 04 November 2011
Should I have to install other PHP Cli ?
If so,how to do that ? where can I get it from ?
#249. Jochem Stoel on 21 October 2011
I came across a 'problem' with arguments given from the commandline. I will post the problem and my solution here in case it helps somebody.
Let's call your script daemon.php for the sake of it, you run the script by doing this:
You can give arguments to your daemon by doing his:
The array $argv then contains:
This daemon thing 'explodes' these arguments on a whitespace before they are passed to the script.
This means when you do this:
It will give you the following array values:
This was not very convenient for me, because I wanted to pass a string that contains whitespaces to my daemon.
The following PHP function turns the above array into this:
In this function, I purposefully do not use the first string that contains the scriptname.
If you want to set the runmode in your daemon, you can use this function like this:
I hope this can be useful for somebody.
#248. Evgeniy on 19 October 2011
I have a problem with running the daemon.
I do so:
I close the terminal, and after re-connection can not detect the process.
I do not see the process in the list of server processes.
What am I doing wrong?
Im using Ubuntu
Thank you!
#247. Adam on 18 October 2011
The issue I'm currently running into, is that even though I specify an integer value to System_Daemon::iterate, the process continues to run, and loop (incrementing the count variable each time).
What's occurring is that even though there is a non-negative, greater than zero integer passed to System_Daemon::iterate, the process keeps going and going, incrementing the count of the variable $cnt and seemingly ignoring the iterate call.
Is there anything else I need to be aware of or perhaps a method in addition to iterate here -
again, my goal is to replace an hourly cron with a daemon process.
Thanks in advance,
Adam
#246. Peter on 14 October 2011
I'm using it for a project at the moment.
But i wonder, does "sysMaxExecutionTime" actually do anything?
If i set it to 10 as test it doesn't kill the daemon after 10 seconds/minutes.
... [more] Which brings me to the next question, is there an option or command that allows me to kill the daemon if it runs too long? Let say after 10 minutes if it's still running : kill it.
I can do a date() with execution and compare, when it's higher and execute System_Daemon::stop() for example. But i just wondered if there's something better than that.
#245. Claudius Coenen on 06 October 2011
I ran into a minor problem with stopping my daemon, and added System_Daemon::isRunning() to my while-loop.
I thought i mentioned it here, in case anyone else has the same problem. When i stopped my daemon with /etc/init.d/awesomedaemon stop, the log-messages switched from "daemon" to "non-daemon", but the service continued to run. Adding the check for "isRunning" solved that problem.
... [more]
Now it exits just fine!
#244. Adam on 29 August 2011
#243. Andrew on 26 August 2011
We use it for our daemon with CentOS. It never dies even for a minutes in months.
One thing that bugging me is memory usage for the daemon itself. I tested the daemon to run a simple task and it consume > 200MB. Have any idea about this?
Our daemon only process two lines:
... [more] while (!System_Daemon::isDying())
{
Proc_Close (Proc_Open ("/usr/bin/php /opt/web/anl/isat/engine/MTBillSendChildProc.php& > /dev/null", Array (), $fsx));
System_Daemon::iterate(2);
}
#242. JW on 12 August 2011
I'm trying to build out a simplified rsyslog parser. I have a number of hosts on my network that write to my centralized syslog server. In addition to raw file logging, I have a named pipe that the syslog will output to as well. What I'm trying to accomplish is writing a script that will read the named pipe and check each line for predefined patterns for problems. If a line matches, it will log the problem line and notify somebody about the issue.
I'm trying to the script read in a configuration file/settings from either a flat file or mySQL DB table. These configurations will contain the REGEXP and notification settings, so they need to be updated on the fly and reread in if possible without having to fully restart the parsing script.
I'm in the initial stages of getting all this put together and here is some basic code that I put after "// Here comes your own actual code" in your example:
I can start the daemon just fine using the init script, but I can't stop it. It just times out. Trying to do a kill -0 on the PID does not do anything and I have to do a kill -9 to stop it.
#241. Gene on 04 August 2011
#!/usr/local/bin/php
<?php
....
?>
#240. Gene on 04 August 2011
I have to run it by typing "php ./file.php"
This wouldn't be a problem except for the startup script is trying to run it as "./file.php"
... [more]
Anyone have an idea how I can edit the command the startup script uses, or update my server to not need the "php" in front of the command? Thank you for your help!
#239. Andrew Blake on 01 August 2011
Cheers
Andrew
#238. Andrew Blake on 01 August 2011
My linux Knowledge is very poor so will note the only minor thing I noticed here rather than trying to figure out how in PEAR. For some reason the kill command didn't work for me (though I never investigated why), and then once running trying to just run it again this time with the --write-initd argument wouldn't generate the init.d file. I had thought it might kill the daemon and restart. I just rebooted, and ran again with --write-inid and worked perfectly.
Thankyou
#237. Andrew Blake on 01 August 2011
Cheers for the post.
#236. yuki on 17 July 2011
incoming mail-->postfix-->php phrasing-->postfix-->destination.
Postfix will receive incoming mail, then inject it to port, for example port 10033, then script php will receive and phrase it, after that, script php will inject it back to other port (e.g port 10034).
... [more]
So how do i configure php so the script will be able to receive then do phrasing and inject to port?
many thanks for your answer.
#235. Nemanja on 07 July 2011
Thank you very much for this exquisite article!
#234. Jean on 06 July 2011
From what I've learned during my time as Perl developer, you might want to consider closing STD* handles before forking though (e.g. fclose(STDIN)). That should prevent errors when echo is called within the daemonized part of the script and it helps realiably detaching from the console.
#233. Jocko on 28 June 2011
sh: /export: not found
What is the problem here?
#232. Pinoy on 08 June 2011
#231. astaza on 06 June 2011
you say echo will error if it's work in this mothed, but if it's run in cronjob will output errors?
thanks
#230. Ismail on 01 June 2011
#229. James Gillmore on 30 May 2011
#228. kirill on 18 May 2011
Regarding the script in the "Complex Example" section - here you start the daemon with System_Daemon::start() before you process --write-initd parameter. As process changes its identity upon the start - this causes problem "Unable to create startup file". To overcome that you could either move write-initd part up in the code or call script with
params.Also, at ubuntu I have problems stopping / restarting the daemon with the generated init.d script. I got error:
But even if I replace --name with --exec in the control script - I get another error - daemon does not stop but rather changes its mode to 'non-daemon' and keeps running. In this case it outputs log records to stdout, but can not be stopped with CTRL+C 0_o
#227. Alex on 12 May 2011
I am facing a problem when writing to the init.d folder. I'm getting the following error:
I have the next permissions:
And finally my php code (session_cleaner.php)
Do you have any idea why I can't write to init.d folder?
Thanx a lot
Alex
#226. fforex on 11 May 2011
#225. Adam on 05 May 2011
#224. Simon on 05 May 2011
#223. Ed on 02 May 2011
My script is chmod a+x, owned and grouped to root, but it's still not writing. Here's /var/log
[May 02 16:15:30] notice: Starting acibind daemon, output in: '/var/log/acibind.log'
... [more] [May 02 16:15:30] info: Changed identify to '':''
[May 02 16:15:30] notice: No data dir found in either: or
[May 02 16:15:30] warning: Unable to create startup file [l:1134]
[May 02 16:15:30] notice: unable to write init.d script
[May 02 16:15:30] err: Not receing data from ZM. [l:183]
Any help is much appreciated!
Thanks,
Ed
#222. Jason on 20 April 2011
Could we technically send any signal as long as we set it using setSigHandler? Or would certain signals have an effect on the daemon (like SIGKILL)?
#221. Kevin on 19 April 2011
You can open a tcp port, or for very rudimentary communication, can use custom POSIX signals. Or work with a jobs table or filebased queue, etc.
#220. Kevin on 19 April 2011
You can open a tcp port, or for very rudimentary communication, can use custom POSIX signals. Or work with a jobs table or filebased queue, etc.
#219. Jason on 19 April 2011
We want the daemon to run a mysql query but only when we tell it to, we don't want the daemon doing anything else the rest of the time (but obviously still keep running in the background).
So the daemon can't check to do anything, it can only take in input.
... [more]
I know it can read in arguments through $argv but this would only work initially when you start up the daemon. It has to somehow dynamically retrieve this. Maybe using php://stdin or something but I don't know the best way.
Any help would be appreciated on this!
#218. Kevin on 19 April 2011
#217. Jason on 19 April 2011
How can you detect if an argument has been passed to the daemon whilst it is running?
start dameon...
./daemon.php
then a command is executed on the server...
./daemon.php --blah
#216. Kevin on 17 April 2011
#215. Kevin on 17 April 2011
@ Robert: Nope, pretty busy as it is, thanks : )
@ Tom Dexter: Thanks for chiming in.
... [more]
@ Jim McNeely: Maybe you can try installing pear with homebrew on OSX
#214. Tom on 16 April 2011
That enables the posix functions apparently.
Thanks anyway!
#213. Jim McNeely on 16 April 2011
err: [PHP User Error] PEAR_Exception not found?! [l:519]
Which upon examination shows it is looking for some PEAR exception classes; I see these buried in the PEAR sub file Exception.php, but it still isn't working. I would really love to use this, any help would be hugely appreciated.
#212. Tom on 16 April 2011
Still using and loving your pear package!
Trying to use it on Fedora 14 at the moment, after playing with it on Ubuntu.
... [more]
When I go to run the daemon I get the following error:
PHP Fatal error: Uncaught System_Daemon_Exception: PHP is compiled without --enable-posix directive in /var/www/testproject/system/system.php on line 85
#0 /var/www/testproject/system/system.php(85): System_Daemon::start()
#1 {main}
thrown in /usr/share/pear/System/Daemon.php on line 552
<font color=#ff0000>
Fatal error: Uncaught System_Daemon_Exception: PHP is compiled without --enable-posix directive in /var/www/testproject/system/system.php on line 85
#0 /var/www/testproject/system/system.php(85): System_Daemon::start()
#1 {main}
thrown in /usr/share/pear/System/Daemon.php on line 552
</font>
Will I just have to re-compile php without the -enable-posix argument?
Thanks in advance for your help!!
Tom
#211. Adolphe on 15 April 2011
i use systemdaemon to create a server that listens for incoming connections and hit a function to query a MS SQL database.
When not running in background, mssql_connect works perfectly, everything seems good. However in background mode mssql does not work.
How can you help me on this ?
#210. Tom Dexter on 26 March 2011
I found out the hard way that this can have the nasty side affect of having some other unwanted resource becoming the default file descriptor for STDOUT (2) or STDERR (3). In my case STDOUT became the file handle for my MySQL unix socket! As soon as I accidentally left a print statement in my script it started mysteriously closed the connection causing "MySQL has gone away" errors!
To prevent this, early in your script before opening any logs or database connections, close ALL three of STDIN, STDOUT, and STDERR and open global file handles to three things to take their place, in order (using a dummy for STDIN, and some log file for the others) such as:
... [more]
fclose(STDIN);
fclose(STDOUT);
fclose(STDERR);
$GLOBALS['STDIN'] = fopen('/dev/null', 'r');
$GLOBALS['STDOUT'] = fopen('/var/log/default.log', 'a+b');
$GLOBALS['STDERR'] = fopen('/var/log/default.log', 'a+b');
That will cause any erroneous output to write harmlessly to those logs. Note that the names of those globals are irrelevant, the important thing is the ORDER they're in, which causes them to get the file descriptors 1, 2, and 3 respectively.
Be glad you didn't have to figure this out :D
Tom
#209. Tom Dexter on 26 March 2011
System_Daemon::setSigHandler(SIGTERM, 'your_function');
In that function (which gets passed the signal number like any signal handler) perform your update and then call System_Daemon::stop();
#208. Dan on 24 March 2011
btw - this is an awesome class
Thanks
... [more]
Dan
#207. Robert on 21 March 2011
#206. Andy on 21 March 2011
It would be nice if System_Daemon::start() would return a success flag, so that one could continue/abort based upon whether or not the daemon actually started.
#205. Kevin on 10 March 2011
@ Andre Agassi: If your code has an existing __autoload function then this function must be explicitly registered on the __autoload stack. This is because spl_autoload_register() will effectively replace the engine cache for the __autoload function by either spl_autoload() or spl_autoload_call().
From: http://www.php.net/manual/en/function.spl-autoload-register.php
#204. Andre Agassi on 06 March 2011
#203. Andy on 04 March 2011
If the file is not less than 16 characters, the daemon will not stop. When you issue a restart command, a new, simultaneous process will be spun up.
Doesn't work: mydaemonfile.php
... [more] Works: mydaemonfil.php
Cheers,
Andy
#202. Kevin on 04 March 2011
#201. Kevin on 04 March 2011
'appRunAsGID' => $gid,
'appRunAsUID' => $uid,
#200. Kevin on 04 March 2011
#199. Shane Harter on 09 February 2011
https://github.com/shaneharter/PHP-Daemon
I'm posting this because the commenter before me was talking about switching a Cron to a daemon. My library is similar to yours in many ways but a feature this has that readers here might find useful is a built-in timer. Suppose you wanted to run some code every second. Or maybe 5 times a second.
... [more]
Also, I built a pretty nifty auto-restart feature to side-step the (very correct) memory issues you wrote about.
Shane
#198. Anish Sharma on 09 February 2011
#197. Kumar Chetan Sharma on 09 February 2011
#196. Wilson on 13 January 2011
#195. Stefan on 10 January 2011
I have one slight problem:
OS = gentoo
... [more] when i call System_Daemon::writeAutoRun() i get an error:
No autoRunTemplatePath found
when i add this variable to Linux.php in OS-folder i get:
No autoRunTemplateReplace found
when i add this variable to Linux.php i get:
notice: No PROPERTIES found in autoRun template
i'm stuck here, please help me out
thanks in advance!!
#194. Morten on 03 January 2011
We're running a daemon with it and using monit to make sure it's always running.
Part of the function is calling an external service - but since this has some downtime during the night, we have a cronjob killing the daemon at that time and then monit makes sure it gets started again. This seems to work just fine.
... [more]
But - now and then we've experienced that more than one thread of our daemon is runing!
How can this be? How can we prevent it from happening?
Thanks for any help.
Kind regards and a happy new year to all.
#193. Joerg on 06 December 2010
first of all: This class is awesome. Thanks a lot!
But now my question, which is not 100% related to your code:
I try to create a php-Daemon, which parses an logfile and saves each line to a database-table.
... [more] The logfile is actively written to and also will be rotated every night.
Do you got such a environment build up successfully with php and System_Daemon? I searched several days in the internet, but the only thing I found was a CPAN-module for perl called File::Tail, which does exactly what I need but in the wrong language. All php-code I found just implemented something like "return the last x lines of messages in a logfile" or weren't aware of logrotate :-(
Thanks in advance
#192. Kyle on 03 December 2010
To fix this I had to shorten the name of my appName
'appName' => 'jque1',
... [more] from
'appName' => 'jobqueue_processor1',
and then this worked. It seems that /proc/$ids/status truncates thus causing start-stop-daemon to fail to shutdown as the --name does not match
#191. Tom on 02 December 2010
Many thanks for the reply!
I was under the impression that the UID and GID of 1000 was for the root user, my mistake!
... [more]
Anyway, my passwd file says that root is 0:0 but after entering these into the daemon option I get the following errors:
[Dec 02 20:45:59] err: Unable to change group of file '/var/run/daemon' to 0 [l:1425]
[Dec 02 20:45:59] crit: Unable to change identity [l:1281]
[Dec 02 20:45:59] emerg: Cannot continue after this [l:1283]
Am I overlooking something else now?
Thanks for your patience!
Tom
#190. Brian on 02 December 2010
You probably have these two options set.
"appRunAsUID"=>array(
... [more] "type"=>"number/0-65000",
"default"=>0,
"punch"=>"The user id under which to run the process",
"example"=>"1000",
"detail"=>"Defaults to root which is insecure!",
"required"=>true),
"appRunAsGID"=>array(
"type"=>"number/0-65000",
"default"=>0,
"punch"=>"The group id under which to run the process",
"example"=>"1000",
"detail"=>"Defaults to root which is insecure!",
"required"=>true),
Look in your /etc/passwd file and compare the uid and gid for root
#189. Tom on 29 November 2010
Once again thanks for the awesome work. Just having some troubles getting the daemon to run as root. I am running a clean ubuntu install, with your example daemon above. I have chmod'd the file as you say above, but everytime I run it it says changing identity to tom:tom. I have tried chown'ing the file too, not sure if that would help the situation?
Thanks.
#188. Tom Dexter on 12 November 2010
#187. Tom Dexter on 12 November 2010
#186. Kevin on 09 November 2010
But I fixed it as well:
http://pear.php.net/bugs/bug.php?id=18031
So be sure to upgrade when I push the new release (or get it from github if you can't wait)
#185. Kevin on 08 November 2010
@ KevBurnsJr: I'm using it in production yes, other folks told me they have as well. However there seem to be quite some edge cases in which a deamon stops working (use echo 1 time, have a dependency that tracks some kind of log/history in an array, thus eventually becoming too large for memory). Because there are plenty other examples and it's hard to cover all of them at first try, you should use monit to restart your daemon & notify you whenever that happens.
There are currently no known bugs that will cause it in PHP or System_Daemon itself, but anything put in your execution loop can pretty easily kill your daemon.
#184. KevBurnsJr on 06 November 2010
Have you ever actually deployed a PHP daemon as part of a production system?
Do you know anyone who has?
#183. Tom on 06 November 2010
Thanks for the awesome tutorial, just what I need!
I am looking to create a daemon in php which will handle commands send to it. However when it is sent a command, i would like it to spawn a kind of child daemon to process that command, otherwise the main daemon would be bogged down doing one command and not be able to handle subsequent commands. Is this possible with this package?
... [more]
How would I go about doing it?!
Thanks again.
#182. Kevin on 31 October 2010
#181. robert on 28 October 2010
many thanks for your great work.
Unfortunately I have an issue regarding using of the init.d
... [more]
This code appears in the console if i try to use the written init.d file
Unable to start /var/daemon/bookingd_test/scriptd.php: Exec format error (Exec format error)
Do I miss something important??
System: Debian lenny
br
robert
#180. Kevin on 11 October 2010
@ Alessandro Desantis: Use ob_start() or maybe even use classkit to overrule echo (dirty)
@ frank: System_Daemon init.d files have protection against this. Should not be possible if you use them
... [more]
@ Thom: Thanks :)
@ Greg J: Wow. Thanks for reporting the fix!
#179. Greg J on 07 October 2010
for the record, the file runs fine with the following command
php myfile.php
... [more]
its only when I attempt to run it as an executable with the following command that I get the problem
./myfile.php
gives me this error
Extension '/var/www/hb_daemon.php' not present.
THE PROBLEM
The problem is that the script I had originated from a windows environment. I thought by deleting a line then recreating it would remove the characters at the end that was causing the problem but the end line characters appear to be built into the file somehow. I have been using gedit in ubuntu 10.04 (lucid) to edit in linux. I tried several other editors but couldnt seem to shake the problem. there seems to be a mysterious ^M at the end of every line. this appeared when I tried using vi but was invisible in all other editors.
THE FIX
you need to run dos2unix over the file.
this program was not installed in my distro so I ran the following command to install it.
sudo apt-get install tofrodos
after that, it still didnt run, said file not found, which is apparently due to a bug so the workaround is to run the following commands from the /usr/bin directory
sudo ln -s fromdos dos2unix
sudo ln -s todos unix2dos
once that was done, I simply ran
dos2unix myfile.php
once done i can run a executable php file from the command line by typing
./myfile.php
happy days!
good luck
Greg J
#178. Greg J on 03 October 2010
Extension '/var/www/hb_daemon.php' not present.
Forum posts I have found say that php cannot be found in the path however I can confirm this.
... [more] php indeed resides in /usr/bin and that path is specified in the init.d file that is created from the $path = System_Daemon::writeAutoRun(); command.
The daemon starts fine when I use the command php hb_daemon.php from the folder where the daemon is located. I found the earlier post from december and tried all the things you suggested but the problem remains.
What happens if you try
php ./daemon.php?
- it runs as expected
If it works, you need to chmod u+x daemon.php
- did this
and maybe put /usr/bin/php in your /etc/shells
- did this
and maybe put #!/usr/bin/php -q in the head of your script.
- already there
The script is simple, it just counts to 5 at 1 second intervals then the daemon stops.
I am running the apt-get installation of php on ubuntu 10.04. PHP 5.3.2-1ubuntu4.5 with Suhosin-Patch (cli) (built: Sep 17 2010 13:41:55)
Any help would be appreciated
Thanks in advance
Greg J
#177. Thom on 01 October 2010
Great work!
#176. frank on 19 September 2010
help appreciated
fra*
#175. gazbond on 17 September 2010
#174. Alessandro Desantis on 10 September 2010
#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. crackgerbal on 12 January 2009
#1. 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 :(