{{{
<?php
// Allowed arguments & their defaults
$runmode = array(
'no-daemon' => false,
'help' => false,
'write-initd' => false,
// production environment by default
'env' => 'production'
);
// 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();
}
// Include the class
error_reporting(E_ALL);
require_once "System/Daemon.php";
// 1000 exists locally, but likely won't on a server. What's a good save id to use?
// Hopefully the functions will return the proper ids (owner of this file).
$uid = getmyuid();
$uid = ($uid === false) ? $uid = 1000:$uid;
$gid = getmygid();
$gid = ($gid === false) ? $gid = 1000:$gid;
// Setup
$options = array(
'appName' => 'li3botd',
'appDir' => dirname(__FILE__),
'appDescription' => 'li3 IRC Bot.',
'authorName' => 'Tom Maiaroto',
'authorEmail' => 'tom@union-of-rad.com',
'sysMaxExecutionTime' => '0',
'sysMaxInputTime' => '0',
// I think this is JUST the daemon. The command we're calling is via shell_exec() should be it's own thing. So this can be low.
// If this daemon gets greedy, it'll turn off at 8M of RAM usage. It can be restarted, but let's see how 8M goes.
'sysMemoryLimit' => '8M',
'appRunAsGID' => $gid,
'appRunAsUID' => $uid
);
// Rename the process based on evnironment. Except for production.
if($runmode['env'] != 'production') {
$options['appName'] = $options['appName'] . '-' . $runmode['env'];
}
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;
// 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) {
while (!System_Daemon::isDying() && $runningOkay) {
// 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',
$mode
);
// In the actual 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.
$li3_app_path = dirname(dirname(__DIR__));
// shell_exec() returns null if an error occurred. So if !is_null() should return true.
$runningOkay = (!is_null(shell_exec("(cd {$li3_app_path} && exec libraries/lithium/console/li3 --env={$runmode['env']} Bot)")));
// Should that 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('There was an error with the bot, so this will be my last run');
}
// Relax the system by sleeping for a little bit iterate also clears statcache
// System_Daemon::info('{appName} sleeping for %s seconds.', 3);
// This doesn't seem to work properly with exact timing. it may be because it's calling usleep() somehow? I don't know.
// It'll work for us here because the time we don't care about, but if we wanted to say 3hrs it wouldn't be 3 hrs.
// See more here: http://pear.php.net/package/System_Daemon/docs/latest/__filesource/fsource_System_Daemon__System_Daemon-1.0.0RC1SystemDaemon.php.html#a595
System_Daemon::iterate(3);
// Here's all it's suppose to do.
//sleep(3); // <--- this would be more accurate with time in seconds
//clearstatcache();
// ...and for us, using PHP 5.3+
//gc_collect_cycles();
}
// Shut down the daemon nicely
// This is ignored if the class is actually running in the foreground
System_Daemon::stop();
}}}