In the code below I am trying to clone a git repository to another machine using a Perl script.
If I print $output, I am getting all the login messages i.e, the contents of /etc/motd/, but not the actual command output.
How to resolve this issue? Am I doing something wrong in the execution of the ssh command?
sub myexec_remote
{
my($cmd, $hostname, $filename) = @_;
my $stdout = $stderr = $exit= "";
my ($output) = `ssh $hostname $cmd 2>&1`;
## this is the command i.e, executed
##command is ssh 111.22.11.32 "git clone --bare gt@l.com:/nfs/git/ /nfs/new123/"
$exit = $?;
if (defined $output)
{
open(MYOUTFILE, ">$filename");
print MYOUTFILE "$output";
close(MYOUTFILE);
}
}
I am using the backticks because sometimes ssh is done without passwordless and I have seen that the NET:SSH module doesn’t support it…
It is because you use the backticks operator in a list context:
When called in list context, backticks will return a list of lines. You only capture the first line, and put it in
$output. The other lines are ignored. Fromperldoc perlop:Solution:
Calling backticks in scalar context will cause $output to be a multiline string.
You can call backticks fine in array context, but you’ll have to print the entire array to the
MYOUTPUTFILElater onOther comments:
These are not part of the solution. The solution itself should be enough to fix your bug. However, they can decrease the risk of bugs, and increase your Perl knowledge.
Try using the three-argument version of open, instead of your two-argument with a global, and catch the error when the file could not be opened:
open(my $handle, '>', $filename) or die "Unable to open file, $!";Many people decide to use IPC::System::Simple instead of backticks, because you have more information when something goes wrong and you can avoid the shell.
Another option is IPC::Open3, which even lets you capture STDOUT, STDERR and the exitcode easily. It is a bit harder to use though.