3

I have a Perl script that runs from Jenkins slave. The script executes a shell script kept on remote box A. This shell script actually deploys war on machine A itself. Both machines, Jenkins slave and remote box are CentOS instances.

use strict;
use warnings;
use Cwd;
use File::Copy;
use Getopt::Long;
use File::Basename;
use Net::OpenSSH;

my ($conf_file, $environment, $doexec, $exec, $job, $dest_file, $user, $host, $IP, $TARGET_SERVER, $JENKINS_JOB, $wrapper, $src_file, $src_path, $src_dist_path, $src_full_path, $id_file, $ssh, @array, $line);

init();

sub init {
    $JENKINS_JOB = $ENV{'JOB_NAME'};

    $conf_file = "/home/ec2-user/SCM/conf/deploy_build.conf";
    open (FH, "<", $conf_file) or die "Cannot open < $conf_file: $!";

    while (<FH>) {
        if ( $_ =~ /\b$JENKINS_JOB\b/ ) {
            push @array, $_;
        } else {
            next;
        }
    }

    foreach $line (@array) {
        ($job, $src_path, $dest_file, $user, $wrapper) = split(':', $line);

        $id_file = "/home/ec2-user/.ssh/priv_key";

        $ssh = Net::OpenSSH->new($IP, key_path => $id_file, user => $user);
        $ssh->error and die "Couldn't establish SSH connection: ". $ssh->error;

        printf "\n";
        if (length $wrapper) {      
            printf "Initiating subroutine for executing wrapper on remote machine...\n";
            &exec_wrapper;
        } else {
                printf "*** No wrapper specified ****\n";
        }
    }
}


sub exec_wrapper {
    my ($stdout, $errput) = $ssh->capture2("~/release/$wrapper");

    printf "Output: $stdout\n" if $stdout;
    die "Error: $errput\n" if $errput;
    printf "\n\n\n";
}

Now the issue is that though the program runs fine, it prints output after a while. Whole output is captured in $stdout and then dumped later. Since this job runs as a Jenkins job, the end user has no idea what's going on until the output is dumped. I wanted to print each line as event occurs (runtime) instead of waiting for the whole output to be stored in the variable and dumped later. I did read this article but i'm not sure whether it applies to my case and if it does, how can i implement it. I did try putting $| = 1; at the top of my script. It didn't work. Then i tried placing it just before initializing ssh object but it didn't work in any of the cases. Just to mention, efficiency is not a concern in my scenario.

Any help will really be appreciated.

Technext
  • 7,887
  • 9
  • 48
  • 76
  • I hope you meant without using the Perl script i.e., directly calling the remote shell script from Jenkins slave box using command line. I tried that and it instantly prints output. :( – Technext Jul 02 '15 at 11:37
  • Yes but fortunately i got the [answer](http://www.perlmonks.org/?node_id=1132949). :) – Technext Jul 02 '15 at 18:17

1 Answers1

2

I got a solution from this node. Instead of storing the output in string and dumping it later, i can use the following code to print log real-time.

sub exec_wrapper {
    $ssh->system("~/release/$wrapper");
    $ssh->die_on_error("execution of ~/release/$wrapper failed");
}

I'm open to other approaches too.

Technext
  • 7,887
  • 9
  • 48
  • 76