简体   繁体   中英

Pass a indicator from Bash back to Perl over SSH via STDIN

We have a Linux server which can run a diagnostic script, diag.pl , which coordinates reporting over other servers.

diag.pl iterates over the child servers, and for each of them, SSHs in and runs a bash script, which passes information back:

my $cmd=sprintf("ssh %s sudo /usr/lib/support/report.sh -e %s | uudecode -o \"%s-outfile.tgz\") 2>%1 |", $server, $specialparam, $servername)

The line of code in report.sh that sends the data back is:

 uuencode --base64 ${REPORT}.tar.gz /dev/stdout

I would like to update report.sh to send back an additional line of information, something like:

 echo "special-file-found=${SFF}" > /tmp/sff.cfg
 uuencode --base64 /tmp/sff.cfg > /dev/stdout

Once the special file has been found, the Perl script will update so that it no longer sends the specialparam back to subsequent report.sh calls.

Is there a good way to send that input so that it will be easy for Perl to catch it?

What have I tried

  1. Setting a user.comment attr on the tar.gz using setattr , but the comment does not survive the uuencoding
  2. Currently thinking that my best bet is to use the pseudocode above, creating a new file to encode and send along, and update the Perl script to check it with each new transmission until it finds the special file.

I take it that the objective is to modify a shell script which returns to the caller an encoded file, so that it sends yet more information, specifically a string to be used as a flag in the caller.

It is not clear how the shell script is run from the Perl script, but there are ways to do this so that the caller gets back separate "lines" that are printed, either as they are emitted or altogether after the run completes.

Then you can just add to the shell script the needed extra print to STDOUT , and in the caller check each line of shell output to see whether it conforms to some "protocol;" for example, whether it is, or starts with, special-file-found string. Then you can set flags for further calls or write control file for following runs, etc. Otherwise, the line is the encoded file.

A made-up basic example using pipe-open (see by the end of the page)

use warnings;
use strict;
use feature 'say';

my @cmd = qw(ls -l ./);

my $file_found = quotemeta 'special-file-found';

my ($flag, $binfile);

my $pid = open(my $out, '-|', @cmd)   // die "Can't open @cmd: $!";

while (<$out>) {
    chomp;
    if (/^$file_found/) { 
        $flag = 1;
    }
    else {
        $binfile = $_;
        # whatever else need be done, or perhaps  last;
    }
}
close $out;

This example runs the command ls -l ./ but instead of it you can run any executable, like @cmd = ('report.sh', 'arg1', 'arg2',...) .

Another way is to use backticks ( qx ) and assign its return to an array, in which case each element receives a line of output.

Yet another, better, way is to use a module which manages external commands. For example, from simple to more capable: IPC::System::Simple , Capture::Tiny , IPC::Run3 , IPC::Run .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM