Permalink
Browse files

synchronous output

  • Loading branch information...
1 parent 786ae14 commit 2830330382de3e3adf1c2bb5b25ae21cf8862440 @shibayu36 shibayu36 committed Jun 12, 2012
Showing with 130 additions and 52 deletions.
  1. +2 −0 Build.PL
  2. +6 −2 lib/Cinnamon.pm
  3. +5 −14 lib/Cinnamon/DSL.pm
  4. +11 −0 lib/Cinnamon/Local.pm
  5. +9 −22 lib/Cinnamon/Logger.pm
  6. +97 −14 lib/Cinnamon/Remote.pm
View
@@ -22,6 +22,8 @@ my $build = Module::Build->new(
'Class::Load' => 0,
'Term::ReadKey' => 0,
'Getopt::Long::Parser' => 0,
+ 'AnyEvent' => 0,
+ 'POSIX' => 0,
},
build_requires => {
'Directory::Scratch' => 0,
View
@@ -46,9 +46,13 @@ sub run {
}
}
- log info => sprintf(
- "\n========================\n[success]: %s\n[error]: %s",
+ log success => sprintf(
+ "\n========================\n[success]: %s",
(join(', ', @success) || ''),
+ );
+
+ log error => sprintf(
+ "[error]: %s",
(join(', ', @error) || ''),
);
}
View
@@ -59,29 +59,20 @@ sub run (@) {
$opt = shift @cmd if ref $cmd[0] eq 'HASH';
my ($stdout, $stderr);
- my $host;
my $result;
+ my $is_remote = ref $_ eq 'Cinnamon::Remote';
+ my $host = $is_remote ? $_->host : 'localhost';
+
+ log info => sprintf "[%s :: executing] %s", $host, join(' ', @cmd);
+
if (ref $_ eq 'Cinnamon::Remote') {
- $host = $_->host;
$result = $_->execute($opt, @cmd);
}
else {
- $host = 'localhost';
$result = Cinnamon::Local->execute(@cmd);
}
- if ($result->{has_error}) {
- my $message = sprintf "%s: %s", $host, $result->{stderr}, join(' ', @cmd);
- die $message;
- }
- else {
- my $message = sprintf "[%s] %s: %s",
- $host, join(' ', @cmd), ($result->{stdout} || $result->{stderr});
-
- log info => $message;
- }
-
return ($result->{stdout}, $result->{stderr});
}
View
@@ -4,11 +4,22 @@ use warnings;
use Carp ();
use IPC::Run ();
+use Cinnamon::Logger;
+
sub execute {
my ($class, @cmd) = @_;
my $result = IPC::Run::run \@cmd, \my $stdin, \my $stdout, \my $stderr;
chomp for ($stdout, $stderr);
+ for my $line (split "\n", $stdout) {
+ log info => sprintf "[localhost :: stdout] %s",
+ $line;
+ }
+ for my $line (split "\n", $stderr) {
+ log info => sprintf "[localhost :: stdout] %s",
+ $line;
+ }
+
+{
stdout => $stdout,
stderr => $stderr,
View
@@ -4,42 +4,29 @@ use warnings;
use parent qw(Exporter);
use Term::ANSIColor ();
-use Log::Dispatch;
-use Log::Dispatch::Screen;
use Cinnamon::Config;
our @EXPORT = qw(
log
);
-my $logger;
-sub logger () {
- $logger ||= do {
- my $level = Cinnamon::Config::get('log_level') || 'info';
- my $logger = Log::Dispatch->new;
- $logger->add(
- Log::Dispatch::Screen->new(
- name => 'screen',
- min_level => $level,
- )
- );
- $logger;
- };
-}
-
my %COLOR = (
- error => 'red',
+ success => 'green',
+ error => 'red',
+ info => 'white',
);
sub log ($$) {
- my ($level, $message) = @_;
- my $color = $COLOR{$level} || 'green';
+ my ($type, $message, $color) = @_;
+ $color ||= $COLOR{$type};
- $message = Term::ANSIColor::colored $message, $color;
+ $message = Term::ANSIColor::colored $message, $color if $color;
$message .= "\n";
- logger->log(level => $level, message => $message);
+ my $fh = $type eq 'error' ? *STDERR : *STDOUT;
+
+ print $fh $message;
}
!!1;
View
@@ -3,6 +3,12 @@ use strict;
use warnings;
use Net::OpenSSH;
+use AnyEvent;
+use AnyEvent::Handle;
+use POSIX;
+
+use Cinnamon::Logger;
+
sub new {
my ($class, %args) = @_;
bless \%args, $class;
@@ -20,30 +26,107 @@ sub host { $_[0]->{host} }
sub execute {
my ($self, @cmd) = @_;
my $opt = shift @cmd;
- my ($stdout, $stderr);
+ my $host = $self->host || '';
+ my $conn = $self->connection;
+ my $exec_opt = {};
+
if (defined $opt && $opt->{sudo}) {
- ($stdout, $stderr) = $self->execute_by_sudo($opt->{password}, @cmd);
+ @cmd = ('sudo', '-Sk', @cmd);
}
- else {
- ($stdout, $stderr) = $self->connection->capture2(join(' ', @cmd));
+
+ my ($stdin, $stdout, $stderr, $pid) = $conn->open_ex({
+ stdin_pipe => 1,
+ stdout_pipe => 1,
+ stderr_pipe => 1,
+ tty => $opt->{tty},
+ }, join ' ', @cmd);
+
+ if ($opt->{password}) {
+ print $stdin "$opt->{password}\n";
+ }
+
+ my $cv = AnyEvent->condvar;
+ my $exitcode;
+ my ($fhout, $fherr);
+
+ my $stdout_str = '';
+ my $stderr_str = '';
+
+ my $end = sub {
+ undef $fhout;
+ undef $fherr;
+ waitpid $pid, 0;
+ $exitcode = $?;
+ $cv->send;
+ };
+
+ my $print = sub {
+ my ($s, $handle) = @_;
+ my $type = $handle eq 'stdout' ? 'info' : 'error';
+ while ($s =~ s{([^\x0D\x0A]*)\x0D?\x0A}{}) {
+ log $type => sprintf "[%s :: %s] %s",
+ $host, $handle, $1;
+ }
+ if (length $s) {
+ log $type => sprintf "[%s :: %s] %s",
+ $host, $handle, $s;
+ }
+ };
+
+ $fhout = AnyEvent::Handle->new(
+ fh => $stdout,
+ on_read => sub {
+ $stdout_str .= $_[0]->rbuf;
+ $print->($_[0]->rbuf => 'stdout');
+ substr($_[0]->{rbuf}, 0) = '';
+ },
+ on_eof => sub {
+ undef $stdout;
+ $end->() if not $stdout and not $stderr;
+ },
+ on_error => sub {
+ my ($handle, $fatal, $message) = @_;
+ log error => sprintf "[%s] STDOUT: %s (%d)", $host, $message, $!
+ unless $! == POSIX::EPIPE;
+ undef $stdout;
+ $end->() if not $stdout and not $stderr;
+ },
+ );
+
+ $fherr = AnyEvent::Handle->new(
+ fh => $stderr,
+ on_read => sub {
+ $stderr_str .= $_[0]->rbuf;
+ $print->($_[0]->rbuf => 'stderr');
+ substr($_[0]->{rbuf}, 0) = '';
+ },
+ on_eof => sub {
+ undef $stderr;
+ $end->() if not $stdout and not $stderr;
+ },
+ on_error => sub {
+ my ($handle, $fatal, $message) = @_;
+ log error => sprintf "[%s] STDERR: %s (%d)", $host, $message, $!
+ unless $! == POSIX::EPIPE;
+ undef $stderr;
+ $end->() if not $stdout and not $stderr;
+ },
+ );
+
+ $cv->recv;
+
+ if ($exitcode != 0) {
+ log error => sprintf "[%s] Status: %d", $host, $exitcode;
}
+{
- stdout => $stdout,
- stderr => $stderr,
+ stdout => $stdout_str,
+ stderr => $stderr_str,
has_error => !!$self->connection->error,
error => $self->connection->error,
};
}
-sub execute_by_sudo {
- my ($self, $password, @cmd) = @_;
- return $self->connection->capture2(
- { stdin_data => "$password\n" },
- join(' ', 'sudo', '-Sk', @cmd),
- );
-}
-
sub DESTROY {
my $self = shift;
$self->{connection} = undef;

0 comments on commit 2830330

Please sign in to comment.