ImJustAFriend has asked for the wisdom of the Perl Monks concerning the following question:

I am 100% sure I'm missing something real basic here, but after a week of trial and error, I think it's time to ask you fine folks for help.

I am creating an automation script for work that will run from Windows laptops. It will use the Control::CLI module to ssh to the target remote servers and do the work. The script I created works wonderfully, with one minor annoyance. At a certain point in my script, I have to launch an external script that resides on one of the target servers and monitor it's progress so I know when to move on. The external script does provide feedback as it runs, which I do monitor... but my users want to see that feedback when the script is running. An example of what they currently see from my script is:

Are you ready to let it run (y/n)? y Pre-loading started at: Tue Jul 28 16:10:13 UTC 2015 Please wait for pre-loading to finish... X records loaded into system in N seconds... X records loaded into system in N seconds... ...

What they are asking for is to show the output of the pre-loader script, like:

Are you ready to let it run (y/n)? y Pre-loading started at: Tue Jul 28 16:10:13 UTC 2015 Please wait for pre-loading to finish... File1 loaded... File2 loaded... ... X records loaded into system in N seconds... X records loaded into system in N seconds... ...

The "FileN loaded" lines are printed out by the pre-loader script. The command I send to the server to launch the pre-loader looks like this:

$s1_output = $s1_cli->cmd("/path/to/pre-loader.pl arg1 arg2 2>&1");

How can I get the output of pre-loader.pl to display in my calling script window?

Thanks in advance!!

Replies are listed 'Best First'.
Re: Call external script via ssh with Control::CLI, get output to calling script window
by Monk::Thomas (Friar) on Jul 29, 2015 at 08:27 UTC

    Disclaimer: I haven't used Control::CLI before.

    With '->cmd()' it seems like you can't. But the documentation says '->cmd()' is equivalent to

    $obj->read(Blocking => 0); $obj->print($cliCommand); $output = $obj->waitfor($obj->prompt);

    so you may be able to replace the call to cmd() with something like this:

    $obj->read(Blocking => 0); $obj->print($cliCommand); while (not $obj->prompt) { my $inc_output = $obj->read(Blocking => 0); if (defined $inc_output) { print $inc_output; $s1_output .= $inc_output; } sleep 1; } (process output in $s1_output)
    This code fragment is totally untested. I just wanted to give you an idea.

      Thanks for the idea, I'll try it out!!

        You can use polling mode on cmd() if you set Blocking to 0

        So you could do this:

        $s1_cli->cmd( Command => "/path/to/pre-loader.pl arg1 arg2 2>&1", Blocking => 0 ); do { Time::HiRes::sleep 0.2; ($ok, $output) = $s1_cli->cmd_poll; print $output if length $output; } until $ok;

        Or else this:

        $s1_cli->cmd( Command => "/path/to/pre-loader.pl arg1 arg2 2>&1", Blocking => 0 ); $s1_cli->poll( Poll_code => sub { $output = ($s1_cli->cmd_poll)[1]; print $output if length $output } );