我似乎被困在这里。我想通过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 folderpathfoo\ bar or ls ' folderpathfoo bar'
,但不是ls 'folderpathfoo bar'
我对Perl不太好,可能有人有经验的人可以推荐解决方法吗?
string :: ShellQuote的shell_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);
当然,您可以如下避免在本地的外壳:
use String::ShellQuote qw( shell_quote );
my $remote_cmd = shell_quote("ls", "--", $remote_dir);
system("ssh", "-i", "id_pub", $ssh_addr, $remote_cmd);
运行本地壳并使用它来逃脱命令以使远程外壳安全看起来像这样:
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的回答,证明了使用选项结束的使用SIGIL --
,以确保即使以DASHES开头的remote_dir
值也被用ls
好吧,您有几种可能性扩展的可能性。
首先将System()与字符串一起使用。这将破坏您在太空字符上的所有路径。您可以将系统用作列表
解决此问题system('ssh', '-i', 'id_pub', $ssh_addr, 'ls', $remote_dir)
现在我们仍然有一个问题,因为SSH将在外壳扩展的外壳上运行远程代码,这将破坏空格的路径再次
因此,您需要将$ remote_dir放入'
字符中,以阻止远程外壳分解路径:给予
system('ssh', '-i', 'id_pub', $ssh_addr, 'ls', "'$remote_dir'")
希望这有帮助/有效
请注意,正如下面的评论者所说的那样,这是一个假设$ remote_dir中没有'
字符。您需要逃脱或解析$ remote_dir,以确保您无法获得看起来像/file.txt'; rm -rf / #
的路径,该路径将尝试删除远程系统上的每个文件
让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 ::任何那里的任何地方。