Issue
Previously I have asked a question here on how to determine whether a path is a directory or not in remote site using SSH. I wish to create the directory if the path is not a directory. I have tried following code with two ways but it seem not to be working. Thanks for everyone that helps here.
use File::Path;
my $destination_path = "<path>";
my $ssh = "usr/bin/ssh";
my $user_id = getpwuid( $< );
my $site = "<site_name>";
my $host = "rsync.$site.com";
if (system("$ssh $user_id\@$host [ -d $destination_path ]") == 0) {
print "It is a directory.\n";
} else {
print "It is not a directory.\n";
#First Way
if(system("$ssh $user_id\@$host [ make_path ($d_path_full) ]") == 0{
#Second Way
if(system("$ssh $user_id\@$host [ mkdir -p $d_path_full ]") == 0{
print "Create directory successfully.\n";
} else {
print "Create directory fail.\n";
}
}
Solution
The bracket(s), single [
or the pair [ ]
, is a builtin in bash
which is a test operator (see man test
), and the last use of it is incorrect. But you don't need it to make a directory
use warnings;
use strict;
use feature 'say';
my $ssh = '/usr/bin/ssh';
my $user_id = ...
my $host = ...
my $to = quotemeta $user_id.'@'.$host;
my $cmd = 'mkdir -p TEST_MKDIR_OVER_SSH';
system("$ssh $to $cmd") == 0 or die "Can't mkdir: $!";
The mkdir
is quiet with -p
if a directory already exists, and it returns succes what also defeats the purpose of [ ]
(if that was the intent). But an actual error -- a file with that name exists, no permissions on the path, etc -- does make its way back to the script, as you'd want, and a string with the error message is in $!
so please test for this.
If you simply wish to know whether the directory existed please put back your test branch, or just omit -p
and analyze the $!
for what that message is on your system.
As for the second attempt: the command to be executed runs on the remote system and has nothing to do with this script anymore (apart from interpolated variables). So Perl functions or libraries from this script make no sense in that command.
For the next step I suggest to look into modules for (preparing and) running external commands, that are much more helpful than the bare system
.
Some, from simple to more capable: IPC::System::Simple, Capture::Tiny, IPC::Run3, IPC::Run. Also see String::ShellQuote, to prepare commands and avoid quoting issues, shell injection bugs, and other problems. This recent post is a good example, and there's a lot more out there.
Answered By - zdim Answer Checked By - Mary Flores (WPSolving Volunteer)