NAME
Process::Govern - Run child process and govern its various aspects
VERSION
version 0.03
SYNOPSIS
To use via command-line (in most cases):
% govproc \
--timeout 3600 \
--log-stderr-dir /var/log/myapp/ \
--log-stderr-size 16M \
--log-stderr-histories 12 \
/path/to/myapp
To use directly as Perl module:
use Process::Govern qw(govern_process);
govern_process(
name => 'myapp',
command => '/path/to/myapp',
timeout => 3600,
stderr_log => {
dir => '/var/log/myapp',
size => '16M',
histories => 12,
},
);
DESCRIPTION
Process::Govern is a child process manager. It is meant to be a convenient bundle (a single parent/monitoring process) for functionalities commonly needed when managing a child process. It comes with a command-line interface, govproc.
Background story: I first created this module to record STDERR output of scripts that I run from cron. The scripts already log debugging information using Log::Any to an autorotated log file (using Log::Dispatch::FileRotate, via Log::Any::Adapter::Log4perl, via Log::Any::App). However, when the scripts warn/die, or when the programs that the scripts execute emit messages to STDERR, they do not get recorded. Thus, every script is then run through govproc. From there, govproc naturally gets additional features like timeout, preventing running multiple instances, and so on.
Currently the following governing functionalities are available:
logging of STDERR output to an autorotated file
execution time limit
preventing multiple instances from running simultaneously
In the future the following features are also planned or contemplated:
CPU time limit
memory limit
With an option to autorestart if process' memory size grow out of limit.
other resource usage limit
loadwatch-like functionality (pause when system load is too high)
fork/start multiple processes
autorestart on die/failure
set (CPU) nice level
set I/O nice level (scheduling priority/class)
limit STDIN input, STDOUT output?
trap/handle some signals for the child process?
set UID/GID?
provide daemon functionality?
provide network server functionality?
Inspiration: djb's tcpserver.
set/clean environment variables
FUNCTIONS
govern_process(%args)
Run child process and govern its various aspects. It basically uses IPC::Run and a loop to check various conditions during the lifetime of the child process. Known arguments (required argument is marked with *
):
command* => STR | ARRAYREF | CODE
Program to run. Passed to IPC::Run's
start()
.name => STRING
Should match regex
/\A\w+\z/
. Used in several ways, e.g. passed asprefix
in File::Write::Rotate's constructor as well as used as name of PID file.If not given, will be taken from command.
timeout => INT
Apply execution time limit, in seconds. After this time is reached, process (and all its descendants) are first sent the TERM signal. If after 30 seconds pass some processes still survive, they are sent the KILL signal.
The killing is implemented using IPC::Run's
kill_kill()
.Upon timeout, exit code is set to 201.
log_stderr => HASH
Specify logging for STDERR. Logging will be done using File::Write::Rotate. Known hash keys:
dir
(STR, defaults to /var/log, directory, preferably absolute, where the log file(s) will reside, should already exist and be writable, will be passed to File::Write::Rotate's constructor),size
(INT, also passed to File::Write::Rotate's constructor),histories
(INT, also passed to File::Write::Rotate's constructor),period
(STR, also passed to File::Write::Rotate's constructor).single_instance => BOOL
If set to true, will prevent running multiple instances simultaneously. Implemented using Proc::PID::File. You will also normally have to set
pid_dir
, unless your script runs as root, in which case you can use the default/var/log
.pid_dir => STR (default: /var/log)
Directory to put PID file in. Relevant if
single
is set to true.on_multiple_instance => STR
Can be set to 'exit' to silently exit when there is already a running instance. Otherwise, will print an error message 'Program <NAME> already running'.
FAQ
Why use Process::Govern?
The main feature this module offers is convenience: it creates a single parent process to monitor child process. This fact is more pronounced when you need to monitor lots of child processes. If you use, on the other hand, use separate parent/monitoring process for timeout and then a separate one for CPU watching, and so on, there will potentially be a lot more processes running on the system.
CAVEATS
Not yet tested on Win32.
SEE ALSO
Process::Govern attempts (or will attempt, some day) to provide the functionality (or some of the functionality) of the builtins/modules/programs listed below:
Starting/autorestarting
djb's supervise, http://cr.yp.to/daemontools/supervise.html
Pausing under high system load
loadwatch
cPanel also includes a program called cpuwatch.
Preventing multiple instances of program running simultaneously
Execution time limit
alarm() (but alarm() cannot be used to timeout external programs started by system()/backtick).
Logging
djb's multilog, http://cr.yp.to/daemontools/multilog.html
Although not really related, Perinci::Sub::Wrapper. This module also bundles functionalities like timeout, retries, argument validation, etc into a single function wrapper.
AUTHOR
Steven Haryanto <stevenharyanto@gmail.com>
COPYRIGHT AND LICENSE
This software is copyright (c) 2013 by Steven Haryanto.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.