Managing processes with Ubic

[ Perl tips index ]
[ Subscribe to Perl tips ]

Perl makes it easy to write code that fulfils a variety of roles, but if you want to write a persistently running process (a daemon) then things become more complex. How do you make sure you don't run multiple daemons at once? How do you manage the output of STDOUT and STDERR? How can you make sure that a set of related daemons are all started or stopped at the same time? And how do you arrange for your process to be restarted if it falls over, or your machine reboots?

The Ubic framework allows one to turn any process or segment of Perl code into a fully-managed daemon, without having to modify your code or executable at all! No special privileges are required, and your executable doesn't even need to be written in Perl!

Installing Ubic

Installing Ubic is done the same way you'd install any other Perl module. We recommend using <cpanm>:

    $ cpanm Ubic

Once the Ubic is installed, you'll need to set it up. The easiest way to do this is with the ubic-admin command:

    $ ubic-admin setup

We recommend keeping the defaults. Note that Ubic will install an entry in your personal crontab file which ensures the ubic-watchdog process is running.

Once you've finished configuration, you can check to see if ubic (and any other daemons) are running with ubic status:

    $ ubic status
    ubic
        ubic.ping   off
        ubic.update off
        ubic.watchdog   running (pid 10036)

You'll also discover that if you've used the defaults, there'll be a ubic directory in your home directory. This contains Ubic's configuration, log-files, and control-files, and we'll examine it next.

Daemonising code with Ubic

Turning an existing program into a Ubic service is easy! All we need to do is write a small piece of configuration in the ubic/service/ directory. For example, if we wished to run tagtime from ubic:

    # In ~/ubic/service/tagtime
    use Ubic::Service::SimpleDaemon;
    Ubic::Service::SimpleDaemon->new(
        bin => 'tagtimed.pl',
    );

That's it! We can now start tagtime easily:

    $ ubic start tagtime
    Starting tagtime... started (pid 12558)

Ubic will make sure you can't run a daemon if it's already running:

    $ ubic start tagtime
    Starting tagtime... already running

You can also use ubic stop ... and ubic status to stop a process, or to find the status of all running processes respectively.

Expanding on simple services

By default, Ubic discards any output from any daemon we start, but we can chose to log it instead.

    # Let's save our logfiles in our ubic/log directory
    my $LOG_HOME = "$ENV{HOME}/ubic/log";
    Ubic::Service::SimpleDaemon->new(
        bin       => 'tagtime',
        stdout    => "$LOG_HOME/tagtime.stdout.log",
        stderr    => "$LOG_HOME/tagtime.stderr.log",
        ubic_log  => "$LOG_HOME/tagtime.ubic.log",
    );

The ubic_log option is where ubic itself will log data about the process.

There are lots of options the Ubic::Service::SimpleDaemon module can take. You can read about them in its documentation.

Multiservices

Sometimes we'll want a collection of services can be all started or stopped in one go, or we'll just want to collect services together to make them easier to manage.

The simplest way to create a collection of services is simply by putting them inside a directory. For example, we create the directory ubic/service/example, any daemons defined inside it will be considered part of the example group. If we had defined services named foo and bar, our status screen might look like this:

    $ ubic status
    example
        example.bar off
        example.foo off
    tagtime     running (pid 12558)
    ubic
        ubic.ping   off
        ubic.update off
        ubic.watchdog   running (pid 10036)

It's possible to start or stop all services in a group, just by referring to the group name. For example ubic start example. We can also start individual processes: ubic start example.foo.

Groups can be nested as many times as you like. This can make management of large, multi-part systems much easier. For example, a running installation of Paul Fenwick's exobrain software might look like this:

    $ ubic status
    exobrain
        exobrain.source
            exobrain.source.foursquare      off
            exobrain.source.beeminder       running (pid 17608)
            exobrain.source.twitter         running (pid 17597)
            exobrain.source.facebook        off
        exobrain.core
            exobrain.core.router            running (pid 16614)
        exobrain.classify
            exobrain.classify.sentbox-reward        running (pid 16843)
            exobrain.classify.rtm-adder             running (pid 16847)
            exobrain.classify.bee-inbox             running (pid 16851)
            exobrain.classify.tweet-ping            running (pid 17407)
            exobrain.classify.bee-habit             running (pid 21871)
        exobrain.sink
            exobrain.sink.beeminder                 running (pid 16628)
            exobrain.sink.twitter                   running (pid 17469)
            exobrain.sink.habitrpg                  running (pid 21859)

There are other ways to create multiservices which are described in the documentation.

Learning more

Ubic provides many advanced features, including the ability to load configuration from files and external sources, a network ping service, have custom permissions for proceses, and of course the ability to query, start, and stop services directly from perl.

If you're interested in learning more, the Ubic documentation is a great place to start!

[ Perl tips index ]
[ Subscribe to Perl tips ]


This Perl tip and associated text is copyright Perl Training Australia. You may freely distribute this text so long as it is distributed in full with this Copyright noticed attached.

If you have any questions please don't hesitate to contact us:

Email: contact@perltraining.com.au
Phone: 03 9354 6001 (Australia)
International: +61 3 9354 6001

Valid XHTML 1.0 Valid CSS