2012-04-30 2 views
3

지난 한 달 동안 HP procurve 스위치에서 마스터 클리어를 수행하기 위해 스크립트 작업을 해왔습니다. 나는 HP 내부 직원들과 이야기를 나누었고 그들은 내가 가진 것보다 완전히 다른 시스템을 사용하고있어 도움이되지 못했습니다. 나는 그것을 모두 알아 냈다고 믿습니다.내가 생각하는 텔넷 입력 버퍼 문제

  1. 그것을 확장에 액세스 할 준비가 식별하는 스위치에서 입력을 부착 APC에 SNMP 트랩을 통해
  2. 재부팅 스위치
  3. 대기를 전환하는 텔넷 연결을 설정합니다 : 이것은 내 스크립트 내가 어떻게해야 무엇인가 부트 롬
  4. 확장 부트롬에 액세스합니다.
  5. 스위치에 컴팩트 플래시 카드에
  6. 실행 목록 명령을 디렉토리를 변경하고 배열
  7. 에 덤프 펌웨어 파일 및 폴더 무엇을 식별 할 배열의 각 항목에 foreach 문을 실행)는 펌웨어를 무시합니다 B) 각 파일을 마스터 삭제 배열에 추가합니다. C) 폴더의 파일에 대해 foreach를 실행하고 마스터 삭제 배열에 폴더를 추가 한 다음 삭제 목적으로 폴더를 추가합니다 (삭제 목적으로)
  8. foreach를 실행하여 삭제합니다. 마스터 삭제 배열의 모든 항목이 스위치를 지우려면
  9. d는 스위치에 대한 기본 정보를 설정합니다.

UPDATE

좋아 나는 $telnet->buffer_empty; 내가 두 번째 list 명령을 호출하고 쓰레기 파일로 덤프됩니다하기로 결정 그래서 시간의 100 %를, 동작하지 않습니다 수 있도록. 아래는 제 스크립트입니다. 지금까지 테스트 한 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; 
+0

이 스크립트의 문제점은 명령과 관련이 없습니다. 필자가 사용중인 텔넷 버전이 펄에 버퍼링 된 내용과 스크립트가 응답하는 방식에 중대한 문제를 야기하는 데이터를 어떻게 되돌려 놓는 지입니다. 어쩌면 텔넷 시스템의 다른 버전이이 문제를 해결할 수도 있지만, 우리 환경에서는이를 구현할 수 없습니다. 현재 파일을 파싱하고 배열에 저장하는 기능을 보류로 설정했지만 대신 일반 파일 세트를 사용하여 파일을 지우는 기능을 사용했습니다. –

답변

2

당신을 위해 무엇을 물어 않는 이는 $telnet->buffer_empty있다, 그러나 나는 (그것을 시도하지만) 그게 문제라고 생각하지 않습니다.

프롬프트가 너무 빨리 일치하지 않습니까? 즉, '=>'도 포함 된 명령 출력이 있습니까? 가장 좋은 디버깅 방법은 $telnet->dump_log('/tmp/some_file')을 통해 이루어 지므로 연결에 들어갔다 나오는 모든 것을 16 진수로 덤프 할 수 있습니다. (더 중요한 것은 Net :: Telnet을 읽고 쓰는 정확한 순서가 무엇인지 알 수 있습니다. 너무 일찍 매칭).

'=>'프롬프트와 너무 일찍 일치하는 경우 정규식을 조금 더 엄격하게 설정하십시오. 문자열의 끝을 확인하기 위해 '\ z'를 추가하는 것이 좋은 시작이지만 '=>'다음에 공백이 있으면주의해야합니다 ('==>? \ z /'와 비슷합니다). (하지만 '\ z'는 실제로 "끝"이 아니라 Net :: Telnet이 지금까지 수집 한 것이기 때문에 결과 중간에있는 불운 한 패킷이 '=>'로 끝나면

또한 인쇄하기 전에 프롬프트가 기다리지 않으므로 "인쇄물"이 길어질 수 있습니다. Net :: Telnet 개체의 "Prompt"필드를 항상 설정 한 다음 -> cmd를 사용하면 프롬프트가 반환되기 전에 대기합니다.

+0

입력 해 주셔서 감사합니다. 필자가 게시 한 후에 Net :: Telnet 설명서를 철저하게 검색하고 $ telnet-> buffer_empty를 추가하고 스크립트의 성공률을 0 %에서 약 60 %로 높였습니다. 다음에 덤프 로그를 만들고 장치에 대해 두 번 스크립트를 실행합니다. 인쇄본 세트에 관해서는, 나는 스크립트의 삭제 부분을 작업하면서 아직 수정하지 않았다. –