1

一部の PC で SSH を介してリモートでコマンドを実行する perl スクリプトがあります。そのため、すべての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"

前もって感謝します。

4

1 に答える 1

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;これは大きな間違いです。コードにサイレント警告やタイプミスが含まれる可能性があるためです(例については以下を参照してください)。これらの2つのプラグマなしでperlコードを記述しないでください。
  • open戻り値をチェックせずにステートメントを使用します。例: open MYFILE, 'HostwithIP.txt' or die $!。戻り値をチェックしないと、openがサイレントに失敗し、さまざまな問題が発生します。使用しwarningsない場合は、閉じたファイルハンドルから読み取っていることを警告することはなく、理解する前に1日中頭をかいて座っていることになります。
  • グローバルファイルハンドルで開く2つの引数を使用します。明示的なオープンモードと字句ファイルハンドルを使用する必要があります。例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、、backticksを使用する場合、またはqx()問題を解決するための他の方法を検討することは常に良い考えです。よりもはるかにうまくこれを処理できるモジュールがありますsystem

于 2012-09-27T18:50:38.857 に答える