snaked

 view release on metacpan or  search on metacpan

snaked  view on Meta::CPAN

#!/usr/bin/perl
#
#   snaked: cool cron replacement.
#
#
#   petya@kohts.ru
#
#

BEGIN {
  # unbuffered output
  $| = 1;

  use Cwd;
  use FindBin;

  # without this chroot abs_path (below)
  # returns empty string if daemon is called
  # from some shell script and current directory
  # is a home directory of a user (permissions?)
  chroot('/');

  $ENV{'MY_BIN'} = "$FindBin::Bin";
  $ENV{'MY_LIB'} = Cwd::abs_path("$ENV{'MY_BIN'}/../lib");
  if (! -d $ENV{'MY_LIB'}) {
    $ENV{'MY_LIB'} = Cwd::abs_path("$ENV{'MY_BIN'}/lib");
  }

  $ENV{'MY_ETC'} = "/etc/snaked";
  $ENV{'MY_ROOT'} = Cwd::abs_path("$ENV{'MY_BIN'}/../../../..");

  if (!$ENV{'PS_SNAKED_LIB'}) {
    $ENV{'PS_SNAKED_LIB'} = $ENV{'MY_LIB'};
  }
};

use strict;
use warnings;

use lib "$ENV{'MY_LIB'}";
use lib "$ENV{'PS_SNAKED_LIB'}";
use snaked;
use Yandex::Tools;
use Yandex::Tools::ProcessList;

package snaked::Daemon;
use Schedule::Cron::Events;
use Time::Local;
use POSIX;
use IO::Handle; # autoflush
use Socket; # socketpair
use Fcntl;
use Time::HiRes;
use File::Path;

my $version = $snaked::VERSION;

my ($daemon_regexp_configured, $daemon_match_cfg, $daemon_match_cfg1, $daemon_match_nocfg, $watchdog_match, $watchdog_match1);

my $current_user = getpwuid($<);
my $current_host = `hostname -f` || "";
my $from_address;
if ($current_user && $current_host) {
  $current_host =~ s/[\r\n]//go;
  $from_address = $current_user . '@' . $current_host;
}

my $my_path;
my $my_command_line;
my $watchdogs2maintain = 1;

my $use_usleep;
my $have_sleep_external;

if ($^O eq 'linux') {
  $use_usleep = 1;
}
else {
  my $ret = system("sleep 0");
  if ($ret eq 0) {
    $have_sleep_external = 1;
  }
  else {
    write_spool("external_sleep_error", "no external sleep: code [$?]; err: [$!]\n", {'mode' => "append"});
  }
}

sub clock_adjusted {
  my ($clock, $opts) = @_;

  $opts->{'start'} = $snaked::Daemon::runtime->{'start_time'} unless $opts->{'start'};
  $opts->{'threshold_left'} = -2 unless $opts->{'threshold_left'};
  $opts->{'threshold_right'} = 2 unless $opts->{'threshold_right'};

  my $elapsed_time_real = $clock->{'real'} - $opts->{'start'}->{'real'};
  my $elapsed_time_mono = $clock->{'mono'} - $opts->{'start'}->{'mono'};
  my $real_mono_diff = $elapsed_time_mono - $elapsed_time_real;

  my $clock_out = localtime($clock->{'real'});

  # were there any adjustments (respecting threshold)
  if ($real_mono_diff < $opts->{'threshold_left'} ||
    $real_mono_diff > $opts->{'threshold_right'} ) {
    
    if ($opts->{'return_adjustment'}) {
      return $real_mono_diff;
    }
    $clock_out .= " (adj. $real_mono_diff: " . localtime($clock->{'real'} + $real_mono_diff) . ")";
  }

  if ($opts->{'return_adjustment'}) {
    return 0;
  }

  return $clock_out;
}

sub my_usleep {
  my ($usec) = @_;

snaked  view on Meta::CPAN

      $ENV{'PS_SNAKED_CFG'} = Yandex::Tools::get_cmdline_param('cfg');

      if (! -d "$ENV{'PS_SNAKED_CFG'}") {
        die "Configuration does not exist: $ENV{'PS_SNAKED_CFG'}\n";
      }
    }
    else {
      $ENV{'PS_SNAKED_CFG'} = $ENV{'MY_ETC'};

      if (! -d $ENV{'PS_SNAKED_CFG'}) {
        $ENV{'PS_SNAKED_CFG'} = ($ENV{'MY_ROOT'} eq "/" ? "" : $ENV{'MY_ROOT'}) .
          "/etc/ps-farm/options/ps-snaked";
      }
      if (! -d $ENV{'PS_SNAKED_CFG'} && -d "/etc/ps-farm/options/ps-snaked") {
        $ENV{'PS_SNAKED_CFG'} = "/etc/ps-farm/options/ps-snaked";
      }
    }
  }

  if (! -d "$ENV{'PS_SNAKED_CFG'}") {
    $ENV{'PS_SNAKED_CFG'} = undef;
  }
  else {
    if (!$daemon_regexp_configured) {
      $daemon_match_cfg = qr/^([^\s]+perl[^\s]*[\s]+|)[^\s]+(ps-)?snaked.+(daemon|debug).+cfg.+$ENV{'PS_SNAKED_CFG'}/;
      $daemon_match_cfg1 = qr/^([^\s]+perl[^\s]*[\s]+|)[^\s]+(ps-)?snaked.+cfg.+$ENV{'PS_SNAKED_CFG'}.+(daemon|debug)/;
      $daemon_match_nocfg = qr/^([^\s]+perl[^\s]*[\s]+|)[^\s]+(ps-)?snaked.+(daemon|debug)/;
      $watchdog_match = qr/^([^\s]+perl[^\s]*[\s]+|)[^\s]+(ps-)?snaked.+(watchdog).+cfg.+$ENV{'PS_SNAKED_CFG'}/;
      $watchdog_match1 = qr/^([^\s]+perl[^\s]*[\s]+|)[^\s]+(ps-)?snaked.+cfg.+$ENV{'PS_SNAKED_CFG'}.+(watchdog)/;
      $daemon_regexp_configured = 1;
    }
  }

  return $ENV{'PS_SNAKED_CFG'};
}

Yandex::Tools::read_cmdline();
get_cfg_path();
Yandex::Tools::ProcessList::set_options({
  'daemon_match' => [$daemon_match_cfg, $daemon_match_cfg1],
  'daemon_match_startup' => [$daemon_match_nocfg],
  });

# commands which might work without actually
# finding configuration on the disk -- what they need
# is the PID which they get from the process table
#
if (Yandex::Tools::defined_cmdline_param('sample-config')) {
    my $target_dir = Yandex::Tools::get_cmdline_param('sample-config') || "/etc/snaked";
    if (-e $target_dir) {
        Yandex::Tools::die("Directory [$target_dir] exists, not going to overwrite.", {'no_log' => 1});
    }
    File::Path::mkpath($target_dir);
    
    if ($> eq 0) {
        Yandex::Tools::write_file_scalar($target_dir . "/log", "/var/log/snaked.log\n");
        Yandex::Tools::write_file_scalar($target_dir . "/admin_email", "root\n");
    }
    else {
        Yandex::Tools::write_file_scalar($target_dir . "/log", "/tmp/snaked.log\n");
        Yandex::Tools::write_file_scalar($target_dir . "/admin_email", getpwuid($>) . "\n");
    }

    File::Path::mkpath($target_dir . "/jobs/every_hour");
    Yandex::Tools::write_file_scalar($target_dir . "/jobs/every_hour/execution_schedule", "0 * * * *\n");
    Yandex::Tools::write_file_scalar($target_dir . "/jobs/every_hour/cmd", "uptime >> /tmp/snaked_every_hour\n");
    chmod(0755, $target_dir . "/jobs/every_hour/cmd") || Yandex::Tools::die("Unable to set permissions on [" . $target_dir . "/jobs/every_hour/cmd" . "]", {'no_log' => 1});

    File::Path::mkpath($target_dir . "/jobs/every_ten_seconds");
    Yandex::Tools::write_file_scalar($target_dir . "/jobs/every_ten_seconds/execution_interval", "10\n");
    Yandex::Tools::write_file_scalar($target_dir . "/jobs/every_ten_seconds/cmd", "uptime >> /tmp/snaked_every_ten_seconds\nsleep 2\n");
    chmod(0755, $target_dir . "/jobs/every_ten_seconds/cmd") || Yandex::Tools::die("Unable to set permissions on [" . $target_dir . "/jobs/every_ten_seconds/cmd" . "]", {'no_log' => 1});

    File::Path::mkpath($target_dir . "/jobs/fast_job");
    Yandex::Tools::write_file_scalar($target_dir . "/jobs/fast_job/execution_interval", "1\n");
    Yandex::Tools::write_file_scalar($target_dir . "/jobs/fast_job/cmd", "uptime >> /tmp/snaked_fast_job\n");
    Yandex::Tools::write_file_scalar($target_dir . "/jobs/fast_job/conflicts", "every_ten_seconds\n");
    chmod(0755, $target_dir . "/jobs/fast_job/cmd") || Yandex::Tools::die("Unable to set permissions on [" . $target_dir . "/jobs/fast_job/cmd" . "]", {'no_log' => 1});

    print "written sample configuration to: $target_dir\n";
    exit(0);
}
elsif (Yandex::Tools::defined_cmdline_param('stop')) {
  my $d = Yandex::Tools::ProcessList::get_other_daemon_process();
  if ($d) {
    print "requesting " . $d->pid() . " [" . $d->cmndline . "] to stop\n";
    kill (15, $d->pid);

    if (Yandex::Tools::defined_cmdline_param('wait')) {
      while (Yandex::Tools::ProcessList::get_other_daemon_process({'refresh_startup_processes' => 1})) {
        print ".";
        my_usleep(1_000_000);
      }
      print "\n";
    }
  }
  else {
    print "no snaked daemon found for $ENV{'PS_SNAKED_CFG'}\n";
  }
  exit 0;
}
elsif (Yandex::Tools::defined_cmdline_param('configure')) {
  my $d = Yandex::Tools::ProcessList::get_other_daemon_process();
  if ($d) {
    print "requesting " . $d->pid() . " [" . $d->cmndline . "] to refresh configuration\n";
    kill ("HUP", $d->pid)
  }
  else {
    print "no snaked daemon found for $ENV{'PS_SNAKED_CFG'}\n";
  }
  exit 0;
}
elsif (Yandex::Tools::defined_cmdline_param('restart')) {
  my $d = Yandex::Tools::ProcessList::get_other_daemon_process();
  if ($d) {
    if (!Yandex::Tools::defined_cmdline_param('only-errors')) {
      print "requesting " . $d->pid() . " [" . $d->cmndline . "] to restart\n";
    }
    kill ("USR2", $d->pid);

    if (Yandex::Tools::defined_cmdline_param('wait')) {



( run in 2.280 seconds using v1.01-cache-2.11-cpan-524268b4103 )