268008 items (1143 unread) in 24 feeds
CNN
(18 unread)
MSNBC
(35 unread)
PHP
(48 unread)
Deals
(1034 unread)
Web Development
(6 unread)
CNN Money
(2 unread)
The scope of this blog entry is to give you a quick and dirty demo for start-stop-daemon together with a short use case on Gearman (all on Ubuntu). In this example, I'm using the start-stop-daemon to handle my Gearman workers through an init.d script.
Gearman is a queue! But unlike for example most of the backends to Zend_Queue, Gearman provides a little more than just a message queue to send — well — messages from sender to receiver. With Gearman it's trivial to register functions (tasks) on the server to make in order to start a job and to get stuff done.
For me the biggest advantages of Gearman are that it's easy to scale (add a server, start more workers) and that you can get work done in another language without building an API of some sort in between. Gearman is that API.
Back to start-stop-daemonstart-stop-daemon is a facility to start and stop programs on system start and shutdown. On recent Ubuntus most of the scripts located in /etc/init.d/ make use of it already. It provides a simple high-level API to system calls — such as stopping a process, starting it in a background, running it under a user and the glue, such as writing a pid file.
Once adjusted, register it with the rc-system: update-rc.d script defaults. This will take care of the script being run during the boot process and before shutdown is completed.
The script may be called with /etc/init.d/script start|stop|restart (the pipes designated "or").
Upon start, we write a pidfile to /var/run and start the process. The same pidfile is used on stop — simple as that. The rest of it is hidden behind start-stop-daemon which takes care of the ugly rest for us.
The best practices for finding files with PHP has evolved a lot in a the last
few years. Back in 2004, one of the very first thing I did with PHP was
porting the File::Find::Rule Perl module to PHP. File::Find::Rule is a
great way to describe the files and directories you want to work with. I used
the opendir, readdir, and closedir native PHP functions, and it did the
job quite well. The PHP class was named sfFinder, and it can still be found
in all symfony versions. Even if the class is bundled with symfony, I know
that a few people use it for all kind of stuff, not necessarily related to
symfony.
But the code starts to show its age; first because I learned a lot since then
about PHP, and also because there is a better way now. Enter
iterators! PHP 5 comes
bundled with a bunch of iterator classes that ease all kind of, well,
iterations. You can iterate over an iterator with the standard foreach
operator, a very powerful PHP construct.
So, how do you get all the files and directories recursively with PHP iterators? Frankly, I don't know. Well, I know more or less which classes to use and how to assemble them, but instead of thinking too hard, I always copy and paste an existing snippet of code to get it right. Here is such a snippet:
// some flags to filter . and .. and follow symlinks
$flags = \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS;
// create a simple recursive directory iterator
$iterator = new \RecursiveDirectoryIterator($dir, $flags);
// make it a truly recursive iterator
$iterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::SELF_FIRST);
// iterate over it
foreach ($iterator as $file)
{
// do something with $file (a \SplFileInfo instance)
}
Noticed the fancy
\character before each built-in class? That's the way you reference built-in PHP class when using them in a PHP 5.3 namespace context.
As you can see for yourself, nothing complex. You just need to know the which Iterator to use, their possible flags, and how to compose them together. So, the first barrier of entry is the learning curve. There are a lot of great tutorials and presentations on the Internet about iterators, but the official documentation on php.net probably lacks some good examples.
The other "problem" is that everything is very object-oriented. And as soon as you want to filter the iterator, you will need to create your own classes, which seems impractical most of the time. That's because PHP iterators are very powerful and have been written to be general-purpose iterators.
What is filtering? Let's say I want to exclude all files ending with .rb
from the iterator. I can create a simple \FilterIterator for that:
class ExcludeRubyFilesFilterIterator extends \FilterIterator
{
public function accept()
{
$fileinfo = $this->getInnerIterator()->current();
if (preg_match('/\.rb$/', $fileinfo))
{
return false;
}
return true;
}
Truncated by Planet PHP, read more at the original (another 10753 bytes)