【问题标题】:Different results with shell command in and out of a perl script使用 shell 命令进出 perl 脚本的不同结果
【发布时间】:2012-11-30 16:15:46
【问题描述】:

我有一个 perl 脚本需要检查远程机器上的空目录。使用 ksh 我可以获得以下 shell 脚本:

ksh# ssh user@host '[ "$(ls -A /empty/dir/* 2>/dev/null)" ] && echo "1" || echo "0"'

如果目录为空或不存在,这将正确返回“0”。仅当目录包含某些内容时,它才会返回“1”。

当我将这一行放在 perl 脚本中时:

#!/usr/bin/perl
print `ssh user\@host '[ "$(ls -A /empty/dir/* 2>/dev/null)" ] && echo "1" || echo "0"'`

无论我放什么,它都会返回一个“1”,空目录与否。我检查了与普通 shell 和 perl 脚本相比的 env 值,它们是相同的。

有没有人知道为什么这个命令只会在 perl 脚本中返回不同的结果?

两台机器都是 AIX 6.1,使用 KSH 作为默认 shell。

【问题讨论】:

  • Perl 可能正在调用 /bin/sh。您是否尝试过直接调用 ksh,/bin/ksh ssh user…
  • 我试过了。我收到错误“ksh: test: 0403-021 A] 字符丢失。”无论我指定 bash 还是 ksh。
  • 该命令的$(...) 部分应该在远程主机上运行。本地主机使用sh还是ksh都没有关系。

标签: perl ssh


【解决方案1】:

反引号内的文本在传递给操作系统之前被插入,就好像它在双引号内一样。运行

print qq`ssh user\@host '[ "$(ls -A /empty/dir/* 2>/dev/null)" ] && echo "1" || echo "0"'`

查看到底是什么字符串被传递给操作系统。我敢打赌,你至少得逃离$

一种更安全、更明智的方法是先构建您的命令,然后在反引号中运行它:

# q{...} does no interpolation
my $cmd = q{ssh user\@host '[ "$(ls -A /empty/dir/* 2>/dev/null)" ] && echo "1" || echo "0"'};
print `$cmd`;

【讨论】:

  • 谢谢。你是对的,在使用 'qq' 之后,我可以看到这实际上是被发送到操作系统的:'[ "0 11 10 8 7 3 2 0ls -A /empty/dir* 2>/dev/null)" ]' .你能解释一下 q{} 做了什么让它更安全吗?
  • 与单引号字符串一样,q{...} 不会插入其内容。见Quote-Like Operators in perlop
【解决方案2】:
use Net::SFTP::Foreign;

my $s = Net::SFTP::Foreign->new('user@host');
my $empty = 1;
if (my $d = $s->opendir('/empty/dir')) {
  if (defined $s->readdir($d)) {
    $empty = 0
  }
}

【讨论】:

    猜你喜欢
    • 2012-03-16
    • 2018-07-15
    • 1970-01-01
    • 2014-11-21
    • 1970-01-01
    • 2016-08-10
    • 2021-05-25
    • 1970-01-01
    • 2017-10-24
    相关资源
    最近更新 更多