在尝试使用ssh设置时间时寻找匹配的“”'时出现意外的EOF

时间:2012-09-27 17:45:57

标签: linux perl ssh

我有一个perl脚本,通过SSH远程在某些PC上运行命令。所以我想把所有电脑上的时间设置为相同。 PC是基于Linux的系统,perl脚本使用另一个具有执行命令的.txt文件。但是当我运行perl脚本时,我收到以下错误:

Command = date --set "27 SEP 2012 19

sh: -c: line 0: unexpected EOF while looking for matching `"'
sh: -c: line 1: syntax error: unexpected end of file

perl脚本工作正常,因为我尝试了另一个命令,它给出了结果。 那么什么可能导致这个错误。

perl代码是:

#!/usr/bin/perl

open (MYFILE,'HostIPWithCmd.txt');
$i=0;
 @IPs=<MYFILE>;
 foreach (@IPs) {
chomp;
($EthIP,$Cmd)= split(":");
 if($EthIP!=~ ("#"))
 {
    push(@hostIP,$EthIP);
    push(@destCmd,$Cmd);

 }

 else
 {
   push(@hostIP,"$EthIP");
   push(@destCmd,$Cmd);
 }
}

$i=0;

foreach my $host (@hostIP)
{
   if($host !=~ ("#"))
   {

      my @cmds= split(/,/,$destCmd[$i]);
      print "\n\nCommands For $host = $destCmd[$i]\n";


   foreach my $command (@cmds)
             {
 print "\n*************************************";
 print "\nCommand = $command \n\n";
 system("ssh -o ConnectTimeout=10 $host $command");

         }

  print "\n***** End Of Host : $host  *****\n";
  print "************************************************************\n\n";
      }

 $i++;
}

和HostIPWithCmd.txt

   10.20.146.97:date --set "27 SEP 2012 19:00:00"

提前致谢。

1 个答案:

答案 0 :(得分:4)

这很简单。这是因为你的字符串中有其他地方的冒号,这会导致字符串的结尾消失。声明:

($EthIP,$Cmd)= split(":");

输入:

10.20.146.97:date --set "27 SEP 2012 19:00:00"

将屈服:

$EthIP = '10.20.146.97';
$Cmd   = 'date --set "27 SEP 2012 19';

分割列表的其余部分(被丢弃)将是:

@rest = ("00", "00");

因为您在冒号:上拆分了。一个简单的解决方法是设置限制:

($EthIP,$Cmd)= split(/:/, $_, 2);  # max 2 fields

---

但是,即使使用此修复程序,您的代码也能正常运行,这是值得怀疑的。您的代码中存在相当多的严重错误。从上到下:

  • 您不使用use strict; use warnings;这是主要错误,因为它会允许您在代码中发出静默警告和拼写错误(请参阅下面的示例)。如果没有这两个pragma,就不要编写perl代码。
  • 您使用open语句而不检查返回值,例如open MYFILE, 'HostwithIP.txt' or die $!。不检查返回值将允许open无声地失败,从而导致各种麻烦。不使用warnings不会警告您,您正在从一个封闭的文件句柄中读取,并且在您弄明白之前,您将整天坐在那里挠头。
  • 您使用带有全局文件句柄的两个参数open。您应该使用显式打开模式和词法文件句柄。例如。 open my $fh, "<", 'HostIPWithCmd.txt" or die $!
  • 您正在使用foreach (@IP)而不是简单地遍历文件句柄,例如while (<MYFILE>)
  • split使用正则表达式,而不是字符串。它会将字符串转换为正则表达式,但最好从一开始就做到这一点。 split /#/
  • 没有!=~运营商。它将被解释为$foo != ~ $bar,或换句话说,$foo$bar的逐位否定之间的数字不等式检查。您想要的运算符是!~。这个特殊的东西会将你的代码分解成许多小部分,特别是当你不使用warnings时,错误是沉默的。所以不,正如你在评论中所说的那样,你的剧本工作得非常好,它被打得非常糟糕。您没有看到它,因为您没有使用warnings
  • 你的if-else语句完全是多余的,因为if和else子句都会发生同样的事情。 $EthIP"$EthIP"之间没有区别。两者完全相同。这可能是您认为代码正常工作的原因。

此外,在使用system,反引号或qx()时,最好还是考虑其他方法来解决问题。有些模块可以比system更好地处理这个问题。