Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/perl
- # License: feel free to distribute and modify this software under
- # a BSD-style or GPL license
- # Version 1.0 Mar 6, 2011
- use warnings;
- use strict;
- use POE qw(Wheel::Run Filter::Stream);
- use File::Basename qw(dirname);
- use Cwd qw(getcwd);
- use Getopt::Long qw(GetOptions);
- use Pod::Usage;
- pod2usage(1) if (!@ARGV);
- my ($arg_command, $arg_fallback, $arg_seconds, $arg_disconnect_regex, $arg_stream, $arg_verbose, $arg_wait_on_sigint, $arg_conduit, $arg_help)
- = ('', '', 30, '(?i:rpc|error|unavailable|http(?!:\/\/))', '', 0, 3, undef, '');
- GetOptions(
- 'c|command=s' => \$arg_command,
- 'f|fallback=s' => \$arg_fallback,
- 's|seconds=i' => \$arg_seconds,
- 'd|disconnect-regex=s' => \$arg_disconnect_regex,
- 'stream' => \$arg_stream,
- 'v|verbose+' => \$arg_verbose,
- 'w|wait-on-sigint=i' => \$arg_wait_on_sigint,
- 'conduit=s' => \$arg_conduit,
- 'h|help' => \$arg_help
- ) or pod2usage(1);
- pod2usage(1) if ($arg_help);
- sub argify {
- my $args = shift;
- if (index($args, '"') == 0) {
- $args = [split(/"/, $args, 3)];
- shift(@$args);
- $args->[0] =~ s/(?<!\\) /\\ /g;
- my @args_args = split(/ +/, $args->[1]);
- shift(@args_args);
- @$args[1..@args_args] = @args_args;
- } else {
- $args = [split(/(?<!\\) +/, $args)];
- }
- $args->[0] =~ s/\\(?! )/\//g;
- return $args;
- }
- $arg_command = argify($arg_command);
- $arg_fallback = argify($arg_fallback);
- $arg_disconnect_regex = qr/$arg_disconnect_regex/;
- my $init_close_all = 0;
- $SIG{$_} = \&catch_sigs for(qw(INT TERM KILL));
- POE::Session->create(
- inline_states => {
- _start => \&on_start,
- got_child_stdout => \&on_child_stdout,
- got_child_stderr => \&on_child_stderr,
- got_child_close => \&on_child_close,
- got_child_signal => \&on_child_signal,
- close_all => \&close_all,
- restore_remote => \&restore_remote,
- run_new => \&run_new,
- error_state => \&error_state,
- delay_int => \&delay_int
- }
- );
- $poe_kernel->run();
- exit 0;
- sub catch_sigs {
- my $signame = shift;
- print "\n\nCaught SIG$signame\n" if ($arg_verbose > 0);
- $poe_kernel->call('s_alias', 'close_all', $signame);
- }
- sub close_all {
- $poe_kernel->alarm_remove_all();
- if ($init_close_all || $_[ARG0] ne 'INT') {
- for my $key (keys %{$_[HEAP]{children_by_wid}}) {
- $_[HEAP]{children_by_wid}{$key}->kill('INT');
- }
- exit;
- }
- for my $key (keys %{$_[HEAP]{children_by_wid}}) {
- $_[HEAP]{children_by_wid}{$key}->put("\cC");
- $poe_kernel->delay_add('delay_int', $arg_wait_on_sigint, $_[HEAP]{children_by_wid}{$key});
- }
- if ($_[ARG0] eq 'INT') {
- 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";
- $init_close_all++;
- }
- }
- sub delay_int {
- if ($_[ARG0]) {
- $_[ARG0]->kill('INT');
- }
- }
- sub run_new {
- my ($wheelname, $command_arr_ref) = ($_[ARG0], $_[ARG1]);
- my $old_dir = getcwd;
- chdir dirname($command_arr_ref->[0]);
- $_[HEAP]{miner}{$wheelname} = POE::Wheel::Run->new(
- Program => $command_arr_ref,
- Conduit => $arg_conduit,
- StdoutFilter => $arg_stream ? POE::Filter::Stream->new() : POE::Filter::Line->new(InputRegexp => qr/\s*[\r\n]{1,2}\s*/, OutputLiteral => "\r\n"),
- StderrFilter => $arg_stream ? POE::Filter::Stream->new() : POE::Filter::Line->new(InputRegexp => qr/\s*[\r\n]{1,2}\s*/, OutputLiteral => "\r\n"),
- StdoutEvent => "got_child_stdout",
- StderrEvent => "got_child_stderr",
- CloseEvent => "got_child_close",
- ErrorEvent => "error_state"
- ) or die "$0: can't POE::Wheel::Run->new";
- chdir $old_dir;
- $_[KERNEL]->sig_child($_[HEAP]{miner}{$wheelname}->PID, "got_child_signal");
- $_[HEAP]{children_by_wid}{$_[HEAP]{miner}{$wheelname}->ID} = $_[HEAP]{miner}{$wheelname};
- $_[HEAP]{children_by_pid}{$_[HEAP]{miner}{$wheelname}->PID} = $_[HEAP]{miner}{$wheelname};
- $_[HEAP]{miner_status}{$wheelname}{live} = 1;
- # $_[HEAP]{miner_status}{$wheelname}{pid} = $_[HEAP]{miner}{$wheelname}->PID;
- print(
- "\nChild pid ", $_[HEAP]{miner}{$wheelname}->PID,
- " started as wheel ", $_[HEAP]{miner}{$wheelname}->ID, ".\n"
- ) if ($arg_verbose > 0);
- return $_[HEAP]{miner}{$wheelname};
- }
- sub restore_remote {
- $_[KERNEL]->post('s_alias', 'run_new', 'remote', $arg_command);
- warn "\n! Running remote.\n";
- }
- sub error_state {
- my ($operation, $errnum, $errstr, $wheel_id) = @_[ARG0..ARG3];
- $errstr = "\nremote end closed" if $operation eq "read" and !$errnum;
- warn "\n\nWheel $wheel_id generated $operation error $errnum: $errstr\n" if ($arg_verbose > 0);
- }
- sub on_start {
- $_[KERNEL]->alias_set('s_alias');
- $_[KERNEL]->post('s_alias', 'run_new', 'remote', $arg_command);
- }
- sub on_child_stdout {
- on_child_stdout_or_err('stdout', @_);
- }
- sub on_child_stderr {
- on_child_stdout_or_err('stderr', @_);
- }
- sub on_child_stdout_or_err {
- my $from = shift;
- my ($line, $wheel_id) = @_[ARG0, ARG1];
- if ($wheel_id == $_[HEAP]{miner}{remote}->ID) {
- if ($line =~ $arg_disconnect_regex) {
- $line .= ' (remote)';
- $_[HEAP]{miner}{remote}->kill('INT');
- if (!$_[HEAP]{miner_status}{local}{live}) {
- $_[KERNEL]->post('s_alias', 'run_new', 'local', $arg_fallback);
- warn "\n! Running local.\n";
- }
- $_[KERNEL]->delay_add('restore_remote', $arg_seconds);
- }
- elsif ($_[HEAP]{miner_status}{local}{live} && $line !~ /^\s*$/) {
- $_[HEAP]{miner}{local}->put("\cC");
- $poe_kernel->delay_add('delay_int', $arg_wait_on_sigint, $_[HEAP]{miner}{local});
- }
- }
- $line =~ s/(\s)+/$1/g;
- $line = $arg_verbose > 0 && $from eq 'stderr' ? $line . ' from stderr' : $line;
- if ($arg_stream) {
- local $| = 1; # enable autoflush
- print $line;
- } else {
- $line =~ s/[\r\n]//g;
- print $line . "\n";
- }
- }
- sub on_child_close {
- my $wheel_id = $_[ARG0];
- my $child = delete $_[HEAP]{children_by_wid}{$wheel_id};
- unless (defined $child) {
- print "\nwid $wheel_id closed all pipes.\n" if ($arg_verbose > 0);
- return;
- }
- print "\npid ", $child->PID, " closed all pipes.\n" if ($arg_verbose > 0);
- delete $_[HEAP]{children_by_pid}{$child->PID};
- }
- sub on_child_signal {
- print "\npid $_[ARG1] exited with status $_[ARG2].\n" if ($arg_verbose > 0);
- my $child = delete $_[HEAP]{children_by_pid}{$_[ARG1]};
- for my $miner (keys %{$_[HEAP]{miner}}) {
- if ($_[HEAP]{miner}{$miner}->PID == $_[ARG1]) {
- $_[HEAP]{miner_status}{$miner}{live} = 0;
- }
- }
- return unless defined $child;
- delete $_[HEAP]{children_by_wid}{$child->ID};
- }
- __END__
- =head1 NAME
- miner_connect.pl - Using miner_connect.pl
- =head1 SYNOPSIS
- miner_connect.pl -c cmd -f cmd [-s sec] [-d regex] [-w sec] [--stream] [--conduit str] [-v]
- Options:
- --help -h this help message
- --command -c miner command to run that connects to pool
- --fallback -f miner command to run that connects to local
- bitcoind
- --seconds -s seconds to wait before retrying pool connect,
- default 30
- --disconnect-regex -d regex to use to detect disconnects from pool,
- default '(?i:rpc|error|unavailable|http(?!:\/\/))'
- --wait-on-sigint -w seconds to wait after relaying a ctrl-c to the
- miners
- --stream -s stream output for miners that update khash/s
- on the same line
- --conduit select a POE::Wheel::Run conduit other than
- its run time selection, this is helpful if no
- output is occuring, selection options
- available: pipe, socketpair, inet, pty, pty-pipe
- --verbose -v increase verbosity of output
- =cut
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement