在路径变量中使用带空格的perl system()查询

时间:2019-02-22 14:50:49

标签: bash perl

我似乎被困在这里。我想通过SSH将脚本中的系统请求发送到另一台服务器,检查是否存在文件夹。文件夹路径是从另一个脚本传递的,存储在变量中,并且其中可能包含空格。由于无法用其他字符替换空格,因此要避免在“ foo bar”之类的文件夹中出现“找不到”的情况,我需要传递类似  ls '/folderpath/foo bar'到其他服务器的外壳。 示例代码如下:

$cmd = 'ssh -i id_pub $ssh_addr ls $remote_dir'; 
if (system($cmd) == 0) {
do something
}

我已经用尽了所有可能的选项-在将\传递给命令之前,累了用\逃避可能的空间,试图在内部将'',“”传递给它,并在将它们都传递给$ cmd之前添加了两者。 但是我总是以这样的结尾:

ls \folderpath\foo\\ bar or ls \' \folderpath\foo bar\'

但不是ls '\folderpath\foo bar'

我对Perl不太满意,有经验的人可以推荐解决方法吗?

4 个答案:

答案 0 :(得分:5)

运行本地shell并使用它来逃逸命令,以确保远程shell的安全,如下所示:

system('env', "ssh_addr=$ssh_addr", "remote_dir=$remote_dir", 'bash', '-c',
       'printf -v remote_cmd "%q " ls -- "$remote_dir"; ssh "$ssh_addr" "$remote_cmd"');

与仅使用"'$remote_cmd'"不同,上述方法适用于所有可能的值,包括有意的恶意值,只要您的远程外壳程序也是bash。

感谢@ikegami's answer演示了使用选项结束标记--来确保即使将以破折号开头的remote_dir值也解析为位置ls

的论点

答案 1 :(得分:5)

String::ShellQuoteshell_quote在构建Shell命令时很有用。

my $remote_cmd = shell_quote("ls", "--", $remote_dir);
my $local_cmd = shell_quote("ssh", "-i", "id_pub", $ssh_addr, $remote_cmd);
system($local_cmd);

当然,可以避免在本地使用shell,如下所示:

use String::ShellQuote qw( shell_quote );

my $remote_cmd = shell_quote("ls", "--", $remote_dir);
system("ssh", "-i", "id_pub", $ssh_addr, $remote_cmd);

答案 2 :(得分:2)

好的,您可以通过这种方式扩展外壳。

首先使用system()和一个字符串。这将破坏您在空格字符上的所有路径。您可以通过将系统用作列表来解决此问题

system('ssh', '-i', 'id_pub', $ssh_addr, 'ls', $remote_dir)

现在我们仍然有一个问题,因为ssh将在具有shell扩展的shell中在远程服务器上运行远程代码,这将再次破坏空格上的路径

因此,您需要将$ remote_dir放在'字符内,以阻止远程Shell破坏路径:给定

system('ssh', '-i', 'id_pub', $ssh_addr, 'ls', "'$remote_dir'")

希望这对您有所帮助/有效

请注意,正如下面的评论者所述,这是假设$ remote_dir中没有'个字符。您需要转义或解析$ remote_dir以确保您不会获得类似/file.txt'; rm -rf / #的路径,该路径将尝试删除远程系统上的每个文件

答案 3 :(得分:1)

Net::OpenSSH为您照顾一切:

my $ssh = Net::OpenSSH->new($ssh_addr);
$ssh->error and die "unable to connect to remote host: " . $ssh->error;
if ($ssh->test('test', '-d', $remote_dir)) {
   # do something here!
}

哦,看来您在Windows机器上!您可以在此处以类似的方式使用Net::SSH::Any