【发布时间】:2020-05-19 05:56:15
【问题描述】:
尝试在 perl 脚本中远程执行一堆命令
看起来像这样:
$CMD1 = "/usr/sbin/mminfo -av -q \"savetime>'-1 day 18:00:00',savetime<'17:59:59'\" -r \"ssid,totalsize,nfiles,pool\"|grep \"xxxxx\"|/usr/bin/awk '!seen[\$1]++'";
print Dumper $CMD1;
$CMD = "/usr/bin/ssh xxxx\@$SRV \'$CMD1\' 2>&1";
print Dumper $CMD;
但是awk命令中的$1还是有问题,运行的时候好像取消了。
我能看到什么:
$VAR1 = '/usr/sbin/mminfo -av -q "savetime>\'-1 day 18:00:00\',savetime<\'17:59:59\'" -r "ssid,totalsize,nfiles,pool"|grep "xxxxxx"|/usr/bin/awk \'!seen[$1]++\'';
$VAR1 = '/usr/bin/ssh xxxxx@\'xxxxxx\' \'/usr/sbin/mminfo -av -q "savetime>\'-1 day 18:00:00\',savetime<\'17:59:59\'" -r "ssid,totalsize,nfiles,pool"|grep "xxxxx"|/usr/bin/awk \'!seen[$1]++\'\' 2>&1';
所以 awk 命令的 '$1' 被正确传递到远程,但是在运行时:
@RESU = `$CMD`;
print Dumper @RESU;
我可以看到我的 $1 丢失(或被远程 shell 解释为空值):
$VAR1 = 'awk: ligne de commande:1: !seen[]++
';
$VAR2 = 'awk: ligne de commande:1: ^ syntax error
';
$VAR3 = 'awk: ligne de commande:1: error: expression indice non valide
';
我尝试了很多方法,例如引用或双引号字符串,使用 perl 'qq' 函数创建字符串,将 $CMD1 的值直接放入 $CMD 并转义引号但没有办法。
当然,我的 awk 通过管道传输到另一个 awk(此处未提供)。
我不想要在本地运行 awk 的解决方案,因为我从“mminfo”命令返回了数百万行。
任何线索(或更好的方法!)?
【问题讨论】:
-
我会推荐模块Net::OpenSSH 来执行远程命令。那么你也应该能够减少所需的引用量
-
当前的问题是 Awk 脚本中的美元符号将被远程 shell 插入。添加单个反斜杠是不够的,因为远程 shell 将执行自己的插值级别。但实际上,在管道中运行琐碎的 shell 命令是没有意义的。 Perl 本身可以很好地做到这一点。尽量减少在外部进程中运行的代码量,以降低复杂性并可能提高性能。
-
@Håkon Hægland:我无法安装 CPAN 模块...
-
@Denis.A 尝试使用perlbrew 它允许您安装没有root权限的模块。
-
@tripleee :我的大问题是 mminfo 命令返回的数据量,我不想通过网络将数百万行传输到 perl 进程。这就是我远程运行所有命令的原因,结果是一行只有 2 个字段...