Advertisement
Guest User

miner_connect.pl edit

a guest
Mar 6th, 2011
367
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Perl 8.09 KB | None | 0 0
  1. #!/usr/bin/perl
  2.  
  3. # License: feel free to distribute and modify this software under
  4. # a BSD-style or GPL license
  5. # Version 1.0 Mar 6, 2011
  6.  
  7. use warnings;
  8. use strict;
  9.  
  10. use POE qw(Wheel::Run Filter::Stream);
  11. use File::Basename qw(dirname);
  12. use Cwd qw(getcwd);
  13. use Getopt::Long qw(GetOptions);
  14. use Pod::Usage;
  15.  
  16. pod2usage(1) if (!@ARGV);
  17.  
  18. my ($arg_command, $arg_fallback, $arg_seconds, $arg_disconnect_regex, $arg_stream, $arg_verbose, $arg_wait_on_sigint, $arg_conduit, $arg_help)
  19.   = ('', '', 30, '(?i:rpc|error|unavailable|http(?!:\/\/))', '', 0, 3, undef, '');
  20. GetOptions(
  21.   'c|command=s'           => \$arg_command,
  22.   'f|fallback=s'          => \$arg_fallback,
  23.   's|seconds=i'           => \$arg_seconds,
  24.   'd|disconnect-regex=s'  => \$arg_disconnect_regex,
  25.   'stream'                => \$arg_stream,
  26.   'v|verbose+'            => \$arg_verbose,
  27.   'w|wait-on-sigint=i'    => \$arg_wait_on_sigint,
  28.   'conduit=s'             => \$arg_conduit,
  29.   'h|help'                => \$arg_help
  30. ) or pod2usage(1);
  31. pod2usage(1) if ($arg_help);
  32. sub argify {
  33.   my $args = shift;
  34.   if (index($args, '"') == 0) {
  35.     $args = [split(/"/, $args, 3)];
  36.     shift(@$args);
  37.     $args->[0] =~ s/(?<!\\) /\\ /g;
  38.     my @args_args = split(/ +/, $args->[1]);
  39.     shift(@args_args);
  40.     @$args[1..@args_args] = @args_args;
  41.   } else {
  42.     $args = [split(/(?<!\\) +/, $args)];
  43.   }
  44.   $args->[0] =~ s/\\(?! )/\//g;
  45.   return $args;
  46. }
  47. $arg_command = argify($arg_command);
  48. $arg_fallback = argify($arg_fallback);
  49. $arg_disconnect_regex = qr/$arg_disconnect_regex/;
  50. my $init_close_all = 0;
  51. $SIG{$_} = \&catch_sigs for(qw(INT TERM KILL));
  52. POE::Session->create(
  53.   inline_states => {
  54.     _start            => \&on_start,
  55.     got_child_stdout  => \&on_child_stdout,
  56.     got_child_stderr  => \&on_child_stderr,
  57.     got_child_close   => \&on_child_close,
  58.     got_child_signal  => \&on_child_signal,
  59.     close_all         => \&close_all,
  60.     restore_remote    => \&restore_remote,
  61.     run_new           => \&run_new,
  62.     error_state       => \&error_state,
  63.     delay_int         => \&delay_int
  64.   }
  65. );
  66. $poe_kernel->run();
  67. exit 0;
  68.  
  69. sub catch_sigs {
  70.   my $signame = shift;
  71.   print "\n\nCaught SIG$signame\n" if ($arg_verbose > 0);
  72.   $poe_kernel->call('s_alias', 'close_all', $signame);
  73. }
  74.  
  75. sub close_all {
  76.   $poe_kernel->alarm_remove_all();
  77.   if ($init_close_all || $_[ARG0] ne 'INT') {
  78.     for my $key (keys %{$_[HEAP]{children_by_wid}}) {
  79.       $_[HEAP]{children_by_wid}{$key}->kill('INT');
  80.     }
  81.     exit;
  82.   }
  83.  
  84.   for my $key (keys %{$_[HEAP]{children_by_wid}}) {
  85.     $_[HEAP]{children_by_wid}{$key}->put("\cC");
  86.     $poe_kernel->delay_add('delay_int', $arg_wait_on_sigint, $_[HEAP]{children_by_wid}{$key});
  87.   }
  88.  
  89.   if ($_[ARG0] eq 'INT') {
  90.     print "\n-----\nCtrl-C(SIGINT) again to close, I suggest you wait $arg_wait_on_sigint sec beforehand. Might have to close console window on Strawberry Perl.\n-----\n";
  91.     $init_close_all++;
  92.   }
  93. }
  94.  
  95. sub delay_int {
  96.   if ($_[ARG0]) {
  97.     $_[ARG0]->kill('INT');
  98.   }
  99. }
  100.  
  101. sub run_new {
  102.   my ($wheelname, $command_arr_ref) = ($_[ARG0], $_[ARG1]);
  103.   my $old_dir = getcwd;
  104.   chdir dirname($command_arr_ref->[0]);
  105.   $_[HEAP]{miner}{$wheelname} = POE::Wheel::Run->new(
  106.     Program       => $command_arr_ref,
  107.     Conduit       => $arg_conduit,
  108.     StdoutFilter  => $arg_stream ? POE::Filter::Stream->new() : POE::Filter::Line->new(InputRegexp => qr/\s*[\r\n]{1,2}\s*/, OutputLiteral => "\r\n"),
  109.     StderrFilter  => $arg_stream ? POE::Filter::Stream->new() : POE::Filter::Line->new(InputRegexp => qr/\s*[\r\n]{1,2}\s*/, OutputLiteral => "\r\n"),
  110.     StdoutEvent   => "got_child_stdout",
  111.     StderrEvent   => "got_child_stderr",
  112.     CloseEvent    => "got_child_close",
  113.     ErrorEvent    => "error_state"
  114.   ) or die "$0: can't POE::Wheel::Run->new";
  115.   chdir $old_dir;
  116.   $_[KERNEL]->sig_child($_[HEAP]{miner}{$wheelname}->PID, "got_child_signal");
  117.   $_[HEAP]{children_by_wid}{$_[HEAP]{miner}{$wheelname}->ID} = $_[HEAP]{miner}{$wheelname};
  118.   $_[HEAP]{children_by_pid}{$_[HEAP]{miner}{$wheelname}->PID} = $_[HEAP]{miner}{$wheelname};
  119.   $_[HEAP]{miner_status}{$wheelname}{live} = 1;
  120.   # $_[HEAP]{miner_status}{$wheelname}{pid} = $_[HEAP]{miner}{$wheelname}->PID;
  121.   print(
  122.    "\nChild pid ", $_[HEAP]{miner}{$wheelname}->PID,
  123.    " started as wheel ", $_[HEAP]{miner}{$wheelname}->ID, ".\n"
  124.   ) if ($arg_verbose > 0);
  125.   return $_[HEAP]{miner}{$wheelname};
  126. }
  127.  
  128. sub restore_remote {
  129.   $_[KERNEL]->post('s_alias', 'run_new', 'remote', $arg_command);
  130.   warn "\n! Running remote.\n";
  131. }
  132.  
  133. sub error_state {
  134.   my ($operation, $errnum, $errstr, $wheel_id) = @_[ARG0..ARG3];
  135.   $errstr = "\nremote end closed" if $operation eq "read" and !$errnum;
  136.   warn "\n\nWheel $wheel_id generated $operation error $errnum: $errstr\n" if ($arg_verbose > 0);
  137. }
  138.  
  139. sub on_start {
  140.   $_[KERNEL]->alias_set('s_alias');
  141.   $_[KERNEL]->post('s_alias', 'run_new', 'remote', $arg_command);
  142. }
  143.  
  144. sub on_child_stdout {
  145.   on_child_stdout_or_err('stdout', @_);
  146. }
  147.  
  148. sub on_child_stderr {
  149.   on_child_stdout_or_err('stderr', @_);
  150. }
  151.  
  152. sub on_child_stdout_or_err {
  153.   my $from = shift;
  154.   my ($line, $wheel_id) = @_[ARG0, ARG1];
  155.   if ($wheel_id == $_[HEAP]{miner}{remote}->ID) {
  156.     if ($line =~ $arg_disconnect_regex) {
  157.       $line .= ' (remote)';
  158.       $_[HEAP]{miner}{remote}->kill('INT');
  159.       if (!$_[HEAP]{miner_status}{local}{live}) {
  160.         $_[KERNEL]->post('s_alias', 'run_new', 'local', $arg_fallback);
  161.         warn "\n! Running local.\n";
  162.       }
  163.       $_[KERNEL]->delay_add('restore_remote', $arg_seconds);
  164.     }
  165.     elsif ($_[HEAP]{miner_status}{local}{live} && $line !~ /^\s*$/) {
  166.       $_[HEAP]{miner}{local}->put("\cC");
  167.       $poe_kernel->delay_add('delay_int', $arg_wait_on_sigint, $_[HEAP]{miner}{local});
  168.     }
  169.   }
  170.   $line =~ s/(\s)+/$1/g;
  171.   $line = $arg_verbose > 0 && $from eq 'stderr' ? $line . ' from stderr' : $line;
  172.   if ($arg_stream) {
  173.     local $| = 1; # enable autoflush
  174.     print $line;
  175.   } else {
  176.     $line =~ s/[\r\n]//g;
  177.     print $line . "\n";
  178.   }
  179. }
  180.  
  181. sub on_child_close {
  182.   my $wheel_id = $_[ARG0];
  183.   my $child = delete $_[HEAP]{children_by_wid}{$wheel_id};
  184.   unless (defined $child) {
  185.     print "\nwid $wheel_id closed all pipes.\n" if ($arg_verbose > 0);
  186.     return;
  187.   }
  188.   print "\npid ", $child->PID, " closed all pipes.\n" if ($arg_verbose > 0);
  189.   delete $_[HEAP]{children_by_pid}{$child->PID};
  190. }
  191.  
  192. sub on_child_signal {
  193.   print "\npid $_[ARG1] exited with status $_[ARG2].\n" if ($arg_verbose > 0);
  194.   my $child = delete $_[HEAP]{children_by_pid}{$_[ARG1]};
  195.   for my $miner (keys %{$_[HEAP]{miner}}) {
  196.     if ($_[HEAP]{miner}{$miner}->PID == $_[ARG1]) {
  197.       $_[HEAP]{miner_status}{$miner}{live} = 0;
  198.     }
  199.   }
  200.   return unless defined $child;
  201.   delete $_[HEAP]{children_by_wid}{$child->ID};
  202. }
  203.  
  204.  
  205. __END__
  206.  
  207. =head1 NAME
  208.  
  209. miner_connect.pl - Using miner_connect.pl
  210.  
  211. =head1 SYNOPSIS
  212.  
  213. miner_connect.pl -c cmd -f cmd [-s sec] [-d regex] [-w sec] [--stream] [--conduit str] [-v]
  214.  
  215.  Options:
  216.    --help             -h  this help message
  217.    --command          -c  miner command to run that connects to pool
  218.    --fallback         -f  miner command to run that connects to local
  219.                           bitcoind
  220.                          
  221.    --seconds          -s  seconds to wait before retrying pool connect,
  222.                           default 30
  223.                          
  224.    --disconnect-regex -d  regex to use to detect disconnects from pool,
  225.                           default '(?i:rpc|error|unavailable|http(?!:\/\/))'
  226.                          
  227.    --wait-on-sigint   -w  seconds to wait after relaying a ctrl-c to the
  228.                           miners
  229.                          
  230.    --stream           -s  stream output for miners that update khash/s
  231.                           on the same line
  232.                          
  233.    --conduit              select a POE::Wheel::Run conduit other than
  234.                           its run time selection, this is helpful if no
  235.                           output is occuring, selection options
  236.                           available: pipe, socketpair, inet, pty, pty-pipe
  237.                          
  238.    --verbose          -v  increase verbosity of output
  239. =cut
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement