NAME

Server::Control -- Flexible apachectl style control for servers

VERSION

version 0.15

SYNOPSIS

use Server::Control::Apache;

my $apache = Server::Control::Apache->new(
    conf_file => '/my/apache/dir/conf/httpd.conf'
);
if ( !$apache->is_running() ) {
    $apache->start();
}

DESCRIPTION

Server::Control allows you to control servers in the spirit of apachectl, where a server is any background process which listens to a port and has a pid file. It is designed to be subclassed for different types of servers.

The original motivation was to eliminate all those little annoyances that can occur when starting and stopping a server doesn't quite go right.

FEATURES

  • Checks server status in multiple ways (looking for an active process, contacting the server's port)

  • Detects and handles corrupt or out-of-date pid files

  • Tails the error log when server fails to start

  • Uses sudo by default when using restricted (< 1024) port

  • Reports what is listening to a port when it is busy (with Unix::Lsof)

AVAILABLE SUBCLASSES

The following subclasses are currently available as part of this distribution:

These will probably be moved into their own distributions once the implementation stabilizes.

CONSTRUCTOR PARAMETERS

You can pass the following common parameters to the constructor, or include them in an rc file.

Some subclasses can deduce some of these parameters without needing an explicit value passed in. For example, Server::Control::Apache can deduce many of these from the Apache conf file.

bind_addr

At least one address that the server binds to, so that Server::Control can check it on start/stop. Defaults to localhost. See also "port".

error_log

Location of error log. Defaults to log_dir/error_log if log_dir is defined, otherwise undef. When a server fails to start, Server::Control attempts to show recent messages in the error log.

log_dir

Location of logs. Defaults to server_root/logs if server_root is defined, otherwise undef.

name

Name of the server to be used in output and logs. A generic default will be chosen if none is provided, based on either "server_root" or the classname.

pid_file

Path to pid file. Will throw an error if this cannot be determined.

poll_for_status_secs

Number of seconds (can be fractional) between status checks when waiting for server start or stop. Defaults to 0.2.

port

At least one port that server will listen to, so that Server::Control can check it on start/stop. Will throw an error if this cannot be determined. See also "bind_addr".

restart_method

Method to use for the "restart" action - one of "hup" or "stopstart", defaults to "stopstart".

server_root

Root directory of server, for conf files, log files, etc. This will affect defaults of other parameters like log_dir.

serverctlrc

Path to an rc file containing, in YAML form, one or parameters to pass to the constructor. If not specified, will look for "server_root"/serverctl.yml. e.g.

# This is my serverctl.yml
use_sudo: 1
wait_for_status-secs: 5

Parameters passed explicitly to the constructor take precedence over parameters in an rc file.

use_sudo

Whether to use 'sudo' when attempting to start and stop server. Defaults to true if port < 1024, false otherwise.

wait_for_status_secs

Number of seconds to wait for server start or stop before reporting error. Defaults to 10.

METHODS

Action methods

start

Start the server. Calls "do_start" internally. Returns 1 if the server started successfully, 0 if not (e.g. it was already running, or there was an error starting it).

stop

Stop the server. Calls "do_stop" internally. Returns 1 if the server stopped successfully, 0 if not (e.g. it was already stopped, or there was an error stopping it).

restart

If the server is not running, start it. Otherwise, restart the server using the "restart_method" - one of "hup" or "stopstart", defaults to "stopstart".

hup

Sends the server parent process a HUP signal, which is a standard way of restarting it. Returns 1 if the server was successfully signalled and is still running afterwards, 0 if not.

Note: HUP is not yet fully supported for NetServer and HTTPServerSimple, because it depends on a valid command-line that can be re-exec'd.

stopstart

Stops the server (if it is running), then starting it. Returns 1 if the server restarted succesfully, 0 if not.

refork

Send a TERM signal to the child processes of the server's main process. This will force forking servers, such as Apache and Net::Server::Prefork, to fork new children. This can serve as a cheap restart in a development environment, if the resources you want to refresh are being loaded in the child rather than the parent.

Returns the list of child pids that were sent a TERM.

ping

Log the server's status.

Command-line processing

handle_cli (constructor_params)

Helper method to implement a CLI (command-line interface) like apachectl. This is used by two scripts that come with this distribution, apachectlp and serverctlp. In general the usage looks like this:

#!/usr/bin/perl -w
use strict;
use Server::Control::Foo;

Server::Control::Foo->handle_cli();

handle_cli will process the following options from @ARGV:

  • -v|--verbose - set log level to debug

  • -q|--quiet - set log level to warning respectively

  • -c|--class - forwards the call to the specified classname. The classname is prefixed with "Server::Control::" unless it begins with a "+".

  • -h|--help - prints a help message using Pod::Usage

  • -k|--action - calls this on the Server::Control::MyServer object (required)

  • Any constructor parameter accepted by Server::Control or the specific subclass, with underscores replaced by dashes - e.g. --bind-addr, --wait-for-status-secs

Any parameters passed to handle_cli will be passed to the Server::Control constructor, but may be overriden by @ARGV options.

In general, any customization to the default command-line handling is best done in your Server::Control subclass rather than the script itself. For example, see Server::Control::Apache and its overriding of _cli_option_pairs.

Log output is automatically diverted to STDOUT, as would be expected for a CLI.

Status methods

is_running

If the server appears running (the pid file exists and contains a valid process), returns a Proc::ProcessTable::Process object representing the process. Otherwise returns undef.

is_listening

Returns a boolean indicating whether the server is listening to the address and port specified in bind_addr and port. This is checked to determine whether a server start or stop has been successful.

status

Returns status of server as an integer. Use the following constants to interpret status:

  • Server::Control::RUNNING - Pid file exists and contains a valid process

  • Server::Control::LISTENING - Something is listening to the specified bind address and port

  • Server::Control::ACTIVE - Equal to RUNNING & LISTENING

  • Server::Control::INACTIVE - Equal to 0 (neither RUNNING nor LISTENING)

status_as_string

Returns status as a human-readable string, e.g. "server 'foo' is not running"

LOGGING

Server::Control uses Log::Any for logging events. See Log::Any documentation for how to control where logs get sent, if anywhere.

The exception is "handle_cli", which will tell Log::Any to send logs to STDOUT.

IMPLEMENTING SUBCLASSES

Server::Control uses Moose, so ideally subclasses will as well. See Server::Control::Apache for an example.

Subclass methods

do_start ()

This actually starts the server - it is called by "start" and must be defined by the subclass. Any parameters to "start" are passed here. If your server is started via the command-line, you may want to use "run_system_command".

do_stop ($proc)

This actually stops the server - it is called by "stop" and may be defined by the subclass. By default, it will send a SIGTERM to the process. $proc is a Proc::ProcessTable::Process object representing the current process, as returned by "is_running".

run_system_command ($cmd)

Runs the specified $cmd on the command line. Adds sudo if necessary (see "use_sudo"), logs the command, and throws runtime errors appropriately.

validate_server ()

This method is called after the server starts or is HUP'd. It gives the subclass a chance to validate the server in a particular way. For example, Server::Control::Apache can visit a particular URL and make sure the result is as expected.

validate_server should return a boolean indicating whether the server is in a valid state. The default validate_server always returns true.

PLUGINS

Because Server::Control uses Moose, it is easy to define plugins that modify its methods. If a plugin is meant for public consumption, we recommend that it be implemented as a role and named Server::Control::Plugin::*.

In addition to the methods documented above, the following empty hook methods are called for plugin convenience:

  • successful_start - called when a start() succeeds

  • failed_start - called when a start() fails

  • successful_stop - called when a stop() succeeds

  • failed_stop - called when a stop() fails

Server::Control uses the MooseX::Traits role if it is installed, so you can call it with new_with_traits(). The default trait_namespace is Server::Control::Plugin.

For example, here is a role that sends an email whenever a server is successfully started or stopped:

package Server::Control::Plugin::EmailOnStatusChange;
use Moose::Role;

has 'email_status_to' => ( is => 'ro', isa => 'Str', required => 1 );

after 'successful_start' => sub {
    shift->send_email("server started");
};
after 'successful_stop' => sub {
    shift->send_email("server stopped");
};

__PACKAGE__->meta->make_immutable();

sub send_email {
    my ( $self, $subject ) = @_;

    ...;
}

1;

and here's how you'd use it:

my $apache = Server::Control::Apache->new_with_traits(
    traits          => ['EmailOnStatusChange'],
    email_status_to => 'joe@domain.org',
    conf_file       => '/my/apache/dir/conf/httpd.conf'
);

RELATED MODULES

  • App::Control - Same basic idea for any application with a pid file. No features specific to a server listening on a port, and not easily subclassable, as all commands are handled in a single case statement.

  • MooseX::Control - A Moose role for controlling applications with a pid file. Nice extendability. No features specific to a server listening on a port, and assumes server starts via a command-line (unlike pure-Perl servers, say). May end up using this role.

  • Nginx::Control, Sphinx::Control, Lighttpd::Control - Modules which use MooseX::Control

TO DO

  • Plugin to check a URL after start and make sure it comes back ok

  • Plugin to dynamically generate conf files

  • Consult global serverctlrc file as well, for common host settings

  • Add persistent shell mode, to eliminate startup cost for repeated restarts

ACKNOWLEDGMENTS

This module was developed for the Digital Media group of the Hearst Corporation, a diversified media company based in New York City. Many thanks to Hearst management for agreeing to this open source release.

SEE ALSO

serverctlp, Server::Control::Apache

COPYRIGHT AND LICENSE

This software is copyright (c) 2011 by Jonathan Swartz.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.