【问题标题】:SSH Create Directory In Remote Site Using Perl ScriptSSH 使用 Perl 脚本在远程站点中创建目录
【发布时间】:2019-05-21 11:52:51
【问题描述】:

之前我曾向question 询问过如何使用 SSH 确定远程站点中的路径是否为目录。如果路径不是目录,我希望创建目录。我尝试了两种方法来跟踪代码,但它似乎不起作用。感谢所有在这里提供帮助的人。

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";
    }
}

【问题讨论】:

    标签: linux perl ssh


    【解决方案1】:

    括号,单个[ 或一对[ ],是bash 中的内置函数,它是一个测试运算符(参见man test),最后一次使用它是不正确的。但是你不需要它来制作目录

    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: $!";
    

    如果目录已经存在,mkdir-p 保持安静,它返回成功,这也违背了[ ] 的目的(如果这是意图)。但是一个实际的错误——一个具有该名称的 file 存在,路径上没有权限等——确实如你所愿返回到脚本,以及一个带有错误的字符串消息在$!,所以请对此进行测试。

    如果您只是想知道该目录是否存在,请放回您的测试分支,或者只是省略 -p 并分析 $! 以了解该消息在您的系统上的内容。

    至于第二次尝试:要执行的命令在远程系统上运行,与此脚本无关(除了插值变量)。因此,该脚本中的 Perl 函数或库在该命令中毫无意义。

    对于下一步,我建议研究用于(准备和)运行外部命令的模块,这比裸露的system 更有帮助。

    一些,从简单到更强大:IPC::System::SimpleCapture::TinyIPC::Run3IPC::Run。另请参阅String::ShellQuote,以准备命令并避免引用问题、shell 注入错误和其他问题。最近的post 有一些例子;搜索更多。

    【讨论】:

    • @TanYihWei 欢迎您。如果出现问题,请告诉我。
    【解决方案2】:

    我建议使用适当的模块来执行 SSH,即Net::OpenSSH,这是一个基于 OpenSSH 构建的 SSH 客户端。

    虽然在纯 Perl 中实现,但它快速且稳定,并且没有强制依赖(当然,OpenSSH 二进制文件除外)。 As explained in the docs,它会在特定条件下自动引用命令列表中的任何 shell 元字符。

    以下代码演示了它如何响应您的用例。它依赖于@zdim 解释的相同快捷方式,使用mkdir -p

    • 如果目录不存在,则创建它(如果失败,则会发生错误)
    • 如果它已经存在,则什么都不会发生
    • 如果存在具有目标名称的文件,则会发生错误

    代码:

    use warnings;
    use strict;
    use Net::OpenSSH;
    
    my $host = ...;
    my $user_id = ...;
    my $destination_path = ...;
    
    # connect
    my $ssh = Net::OpenSSH->new($host, user => $user_id);
    $ssh->error and die "Can't ssh to $host: " . $ssh->error;
    
    # try to create the directory
    if ( $ssh->system('mkdir', '-p', $destination_path) ) {
        print "dir created !\n";
    } else {
       print "can't mkdir $dir on $host : " . $ssh->error . "\n";
    }
    
    # disconnect
    undef $ssh;
    

    【讨论】:

    • 嗨@GMB 感谢您的回答。它不起作用,因为我的工作机器没有安装 Net::OpenSSH 模块,并且我不允许在机器中安装任何模块。对不起。
    猜你喜欢
    • 2020-01-06
    • 1970-01-01
    • 2012-09-18
    • 2011-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-09
    相关资源
    最近更新 更多