3

そのため、この 1 か月間、HP procurve スイッチでマスター クリアを実行するスクリプトに取り組んできました。HP の内部担当者と話しましたが、彼らは私とはまったく異なるシステムを使用しているため、何の助けにもなりませんでした。私はそれをすべて理解したと信じています。これは私がやるべきスクリプトです:

  1. スイッチへの telnet 接続を確立します
  2. 接続された APC への SNMP トラップを介してスイッチを再起動します
  3. スイッチからの入力を待って、拡張ブート ROM にアクセスする準備ができていることを確認します
  4. 拡張 bootrom にアクセスします。
  5. ディレクトリをコンパクトフラッシュカードに変更します
  6. スイッチで list コマンドを実行し、それをアレイにダンプします
  7. 配列内の各項目に対して foreach を実行して、ファームウェア、ファイル、およびフォルダーが何であるかを識別します A) ファームウェアを無視します B) 各ファイルをマスター削除配列に追加します C) フォルダー内のファイルに対して同様の foreach を実行し、それらをマスター削除配列、次にフォルダー (削除目的)
  8. foreach を実行してマスター削除配列内のすべてのアイテムを削除し、スイッチをクリアします。
  9. 再起動し、スイッチの基本情報を設定します。

アップデート

$telnet->buffer_empty;100% の確率で を動作させることができなかったので、2 番目の list コマンドを呼び出して、それをガベージ ファイルにダンプすることにしました。以下は私のスクリプトで、これまでにテストした 10 個のスイッチで動作しています。私の夜勤は、スイッチを壊して、このリセット スクリプトをテストする予定です。

興味のある方のために説明すると、このスクリプトは HP Procurve スイッチで使用されており、私の調査によると、ほとんどのスイッチで機能しますが、すべてではありません。

#!/usr/bin/perl
$| = 1;


use Net::Telnet;
use Net::SNMP;
use strict;
use CGI;

#variabls for power, connections and systemname
my $power_host     = ('Power-APC');
my $power_port     = ('Power-APC-Port');
my $system_name    = ('system-name');
my $console_server = ('Console-Server');
my $console_mgmtA  = ('Console-ManagementA');
my $match;
my ($garbage, $trash);
my $master_value;
my $telnet;
my @array;
my @master_array;


checkForNull("Console-Server",$console_server,1);
checkForNull("Console-ManagementA",$console_mgmtA,1);
checkForNull("Power_Host",$power_host,1);
checkForNull("Power_Port",$power_port,1);
checkForNull("System_Name", $system_name,1);


#Starting reset script
print("Please wait while $system_name resets.\n");
print("Please do not interact with any consoles open to this device\n");
print("The reset will take approximitly 5 minutes\n");

#establishing Telnet connection
$telnet = new Net::Telnet (Timeout=>120, Errmode=>'return', Port => $console_mgmtA);

$telnet->open($console_server);
sleep(1);

#executing reboot via SNMP
print("Deleting configuration files.\n");

   my ($snmp, $error) = Net::SNMP->session(
      -hostname  => shift || "$power_host",
      -community => shift || 'private',
      -port      => shift || 161
   );
   if (!defined($snmp)) {
      printf("ERROR: %s.\n", $error);
      exit 1;
   }
   my $sysx = ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.4.$power_port";
   my $result = $snmp->set_request(
      -varbindlist => [$sysx, INTEGER, '3']
   );
   $snmp->close;




$telnet->waitfor(match=> '/Profiles/');
$telnet->cmd(string => '0', prompt => '/=>/');
#shift to compact flash card
$telnet->cmd (string=> 'cd cfa0', prompt => '/=>/');
my $garbage_output = $telnet -> cmd (string => 'ls', prompt => '/=>/');
$telnet->buffer_empty;


#propigates primary array with file list
undef @array;
@array = $telnet->cmd(string => 'ls', prompt => '/=>/');


#determines what should be deleted
foreach my $item (@array) {
    #cleans up the files for use in the if statement
   chomp ($item);
   #determines if it's a folder, passes folder name to sub
   if ($item=~ /\//) {
       subfolders ($item);
       #adds folder AFTER files in dir to ensure deletion
       push(@master_array, "rmdir $item");
   }
   #finds and ignores the primary and secondary firmware

   elsif ($item =~ /btm.swi|secondary.swi/) {
   }
   else {
    #adds all files to the master deletion list
    push(@master_array,"rm $item");
   }



#deletes all files listed in the master array
foreach $master_value (@master_array){
$telnet -> print ("$master_value");
}


#reboot switch
$telnet->print('boot');
$telnet->put(chr(13));
sleep(120);


#looking for ready screen
$telnet->waitfor(match=> '/continue/');
sleep (1);
$telnet->put(chr(13));
sleep (1);
$telnet->put(chr(13));
$telnet->waitfor(match=> '/continue/');
$telnet->put(chr(13));
$telnet->print('config');
$telnet->put(chr(13));
$telnet->print("hostname $system_name\n");
$telnet->print('lldp run');
$telnet->put(chr(13));
$telnet->print('wr mem');
$telnet->put(chr(13));
$telnet->print('boot');
$telnet->put(chr(13));
$telnet->print('y');


print("$system_name has been reset to factory settings.\n");
}


#add all files in folders to master deletion list
sub subfolders {
 my @subfolder_contents;
 my $subfolder = $_[0];
 my $file;

 @subfolder_contents = $telnet ->cmd(string => "ls $subfolder", prompt => '/=>/');
 foreach $file (@subfolder_contents){
  chomp ($file);
    push(@master_array, "rm $subfolder$file");
 }
};


sub checkForNull {
    my $name = $_[0];
    my $param = $_[1];
    my $required = $_[2];

    if($param eq "") {
        if ($required == 1) {
            print("\nSorry, no '$name' specified for this device, cannot continue.\n");
            exit 1;
        }
    }
# else {
 #       print("\n$name: $param\n");
  #  }
}

exit;
4

1 に答える 1

2

あなたが求めることをするがありますが、$telnet->buffer_emptyそれはあなたの問題ではないと思います(試してみてください)。

プロンプトが一致するのが早すぎませんか? 言い換えれば、たまたま「=>」も含むコマンド出力はありますか? デバッグする最善の方法は$telnet->dump_log('/tmp/some_file')、 を使用することです。これにより、接続に出入りするすべての 16 進ダンプが得られます (さらに重要なことに、Net::Telnet の読み取りと書き込みの正確なシーケンスにより、一致しているかどうか、どこで一致しているかがわかります)早すぎる)。

「=>」プロンプトとのマッチングが早すぎる場合は、正規表現をもう少し厳密にしてみてください。文字列の末尾を確認するために '\z' を追加するのは良い開始点ですが、'=>' の後にスペースがある場合は注意してください (つまり '/=> ?\z/' のようになります)。(しかし、もちろん、'\z' は実際には「終わり」ではなく、Net::Telnet がこれまでに収集したものすべてです。したがって、出力の途中にある不運なパケットの 1 つがたまたま「=>」で終わった場合、より厳密な正規表現も壊れます)

また、print は戻る前にプロンプ​​トを待たないため、長い一連の「prints」が疑わしいように見えます。Net::Telnet オブジェクトの "Prompt" フィールドを常に設定し、戻る前にプロンプ​​トを待機する ->cmd を使用することをお勧めします。

于 2012-05-01T05:04:43.330 に答える