App-Foca
view release on metacpan or search on metacpan
lib/App/Foca/Server.pm view on Meta::CPAN
Depending on the settings given to the command it will return the STDOUT or
STDERR or even both. The rules are:
=over 4
=item 1. On success it will look for STDOUT, if nothing is there then it looks in
STDERR. If nothing is foudn in STDERR and STDOUT then an empty string is
returned.
=item 2. On error it will look for STDERR first, if nothing is there then it
looks in STDOUT. If nothing is there then it returns an empty string.
=back
Both STDOUT and STDERR can be returned if the command is defined as follows:
server_uptime:
cmd: '/usr/bin/uptime'
capture_all: 'y'
=cut
sub run_cmd {
my ($self, $connection, $name, $cmd, $params) = @_;
my $output = '';
if ($cmd->{'cmd'}) {
my $capture_all = 0;
if ($cmd->{'capture_all'}) {
$capture_all = ($cmd->{'capture_all'} eq 'y');
}
my @foca_cmd;
# For the args, the cmd has a {%args%} parameter?
if ($cmd->{'cmd'} =~ /\{\%foca_args\%\}/) {
my $cmd = $cmd->{'cmd'};
if ($params) {
$cmd =~ s/\{\%foca_args\%\}/$params/g;
} else {
$cmd =~ s/\{\%foca_args\%\}//g;
}
@foca_cmd = $cmd;
} else {
@foca_cmd = $cmd->{'cmd'};
push(@foca_cmd, $params) if $params;
}
my $timeout = $cmd->{'timeout'} ?
int($cmd->{'timeout'}) : $self->{'commands_timeout'};
my ($result, $out, $err, $error_msg, @foca_cmd_pids, $in);
eval {
my $ip = $connection->peerhost();
log_info("Command - $name [timeout: $timeout][ip $ip] - About to run @foca_cmd");
$result = run_forked("@foca_cmd", {
child_in => \$in,
timeout => $timeout});
};
if ($result->{'timeout'} == $timeout) {
return (FOCA_RUN_RC_TIMEOUT_CMD, 'Timed out');
}
# Ok, sometimes because of SIG{CHLD} we get exit codes of 255
# with no stderr which foca thinks the command failed but it really did not,
# so lets check if we got stderr too, if we did not then the command was
# OK (unless of course there is a real: 'y' command). Check anything >
# than 1 cause 1 is by default an error (like /bin/false which wont
# return nothing to STDERR...)
if ($result->{'exit_code'} > 1) {
unless ($result->{'stderr'}) {
if (defined $cmd->{'real'}) {
if ($cmd->{'real'} ne 'y') {
# Force OK
$result->{'exit_code'} = 0;
}
} else {
# Force OK
$result->{'exit_code'} = 0;
}
}
}
if ($result->{'exit_code'} > 0) {
my $output = '';
if ($capture_all) {
$output = $result->{'merged'};
} else {
if ($out) {
$output = $result->{'stdout'};
}
if ($err) {
$output = $result->{'stderr'};
}
}
$output = $result->{'merged'} unless $output;
$output = $@ unless $output;
$output = $result->{'err_msg'} unless $output;
$output =~ s#Can't ignore signal CHLD, forcing to default.(\n)?##g;
return (FOCA_RUN_RC_FAILED_CMD, $output);
} else {
my $output = '';
if ($capture_all) {
$output = $result->{'merged'};
} else {
if ($out) {
$output = $result->{'stdout'};
}
if ($err) {
$output = $result->{'stderr'};
}
}
$output = $result->{'merged'} unless $output;
$output =~ s#Can't ignore signal CHLD, forcing to default.(\n)?##g;
return (FOCA_RUN_RC_OK, $output);
}
} else {
return (FOCA_RUN_RC_MISSING_CMD, 'Missing command in commands file');
}
}
=head2 B<load_commands()>
Load the commands YAML file and stores it in memory with L<Cache::FastMnap>
=cut
sub load_commands {
my ($self) = @_;
log_info("Loading commands from $self->{'commands_file'}");
if (-f $self->{'commands_file'}) {
my $commands = LoadFile($self->{'commands_file'});
if ($commands->{'commands'}) {
$self->{'commands'} = $commands->{'commands'};
} else {
$self->{'commands'} = {};
}
# We have dirs?
if (defined $commands->{'commands_dirs'}) {
foreach my $dir (@{$commands->{'commands_dirs'}}) {
next unless (-d $dir);
foreach my $file (glob("$dir/*")) {
next unless (-x $file);
my $base = basename($file);
if (defined $self->{'commands'}->{$base}) {
log_warn("Command $base is already defined");
} else {
log_debug("Adding $base (fullpath $file)");
$self->{'commands'}->{$base} = {
'cmd' => $file};
}
}
}
}
} else {
log_error("Commands file does NOT exists");
$self->{'commands'} = {};
}
# Store
$self->{'cache'}->set('foca_commands', $self->{'commands'});
}
######################## PRIVATE / PROTECTED METHODS ##########################
sub BUILD {
my ($self) = @_;
$self->{'cache'} = Cache::FastMmap->new(
share_file => $self->{'tmp_dir'} . '/foca_server_mmap',
init_file => 1,
( run in 0.635 second using v1.01-cache-2.11-cpan-39bf76dae61 )