精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

使用Perl腳本徹底實現系統管理自動化

運維 系統運維 自動化
交互式程序通常需要用戶手動完成一些操作,因此常常會成為系統管理自動化和測試自動化中的障礙。最早出現在 Unix 上的 Expect 語言可以用來和 passwd/ssh/telnet/ftp 等命令行程序進行交互,將用戶從這些手工操作中解放出來。本文將介紹 Perl 中的 Expect 和 Expect::Simple 兩個模塊。

交互式程序通常需要用戶手動完成一些操作,因此常常會成為系統管理自動化和測試自動化中的障礙。最早出現在 Unix 上的 Expect 語言可以用來和 passwd/ssh/telnet/ftp 等命令行程序進行交互,將用戶從這些手工操作中解放出來。作為 Tcl 語言的擴展,Expect 最初由 Tcl 編寫,但是現在已經有了 Perl 和 Python 的實現。Perl 作為最為流行的腳本語言之一,整合了 C/sh/sed/awk 的優點且和系統結合緊密,已成為系統管理員有力的工具。本文將介紹 Perl 中的 Expect 和 Expect::Simple 兩個模塊,結合系統管理和軟件測試實例,說明如何實現與命令行程序的自動化交互。

局限性

Perl 的 Expect 模塊依賴于 IO::Tty,而 IO::Tty 只適用于 POSIX 兼容系統,所以該模塊目前還無法直接在 Windows 環境下使用。有兩個變通的方法:一是使用 Cygwin 虛擬機;二是基于 ActiveState 提供的 Expect for Windows 工具,使用 Tcl 語言編寫自動化腳本。本文所使用的環境為 RHEL5.3 32 位版本,Perl 5.8.8。

下載和安裝

Expect 和 Expect::Simple 都可以從 CPAN 網站上直接下載,最新版本為 Expect-1.21 和 Expect::Simple-0.04。比較方便的安裝方法是使用 Perl 自帶的包管理工具 cpan:

清單 1. 模塊安裝

				
 perl -MCPAN -e 'install Expect::Simple'

請確保有足夠的執行權限,cpan 將自動解決模塊間依賴關系。由于 Expect::Simple 依賴于 Expect,安裝 Expect::Simple 的過程中,Expect 模塊以及另外的依賴模塊都會自動安裝完畢。

Expect 模塊詳解

與最初的 Expect 語言類似,Expect 模塊的主要功能也通過 spawn,expect,send 三個方法實現。

spawn:啟動目標程序

清單 2. spawn 方法原型

				
 $obj = Expect->spawn( $command, @parameters ); 

spawn 是 Expect 類的主要方法之一,通過 fork 和 exec 啟動目標程序,若成功則返回 Expect 對象,否則返回 undef。參數 $command 指定目標程序,@parameters 為可選參數。下面是一個簡單的例子:

清單 3. spawn 用法示例

				
 $obj1 = Expect->spawn( "ftp 9.9.9.9" );           # 啟動 ftp 進程
 $obj2 = Expect->spawn( "ftp", "9.9.9.9" );        # 與上一行等效  

上述兩行執行結果相同,但其實際處理過程存在細微差別。一般情況下我們可以把完整的命令行 ( 甚至可以是復合命令,包括命令、參數、管道符、重定向符等 ) 都寫入 $command 而不指定 @parameters。

注:在 spawn 的實現中,$command 和 @parameters 都原封不動地傳遞給了 Perl 的 exec 函數。根據 exec 函數的說明文檔,如果傳遞進來的是多元列表參數,exec 直接將其傳遞給 execvp 系統調用;如果傳遞進來的是標量參數或者單元列表參數,exec 函數將檢查是否存在 shell 元字符 ( 如 | & ; ( ) < > 等 ),若存在,則將此參數交給系統 shell 進行解析,否則將其分詞后傳遞給 execvp 系統調用。因此如果 spawn 的是一個含有 shell 元字符的復合命令,我們一般只能將其完整寫入 $command。

#p#

expect:等待特定輸出

清單 4. expect 方法原型

				
 $obj->expect( $timeout, @match_patterns ); 

使用 Expect 對象的 expect 方法等待目標程序的特定輸出。參數列表中 $timeout 設定超時 ( 以秒為單位 ),@match_patterns 提供一個或多個匹配模式,如果在設定時間內目標程序輸出結果和 @match_patterns 中某元素匹配則成功返回。缺省情況下 expect 使用精確匹配,若想使用正則表達式,可以在該模式元素前加 '-re' 前綴 :

清單 5. 啟用正則表達式匹配

				
 $obj->expect( 10, 'match me exactly', '-re'=>'match\s+me\s+exactly' ); 

標量上下文中 expect 返回匹配模式在 @match_patterns 中的位置 ( 注意下標從 1 開始 ),若不成功則返回 undef。而列表上下文中 expect 返回一個包含詳細匹配信息的列表:

清單 6. expect 方法的列表返回值

				
 ( $pos, $err, $match, $before, $after ) = $obj->expect( $timeout, @patterns ); 

其中 $pos 就是在標量環境中的返回值,$err 是出錯信息,$match 為成功匹配的字串,$before 為匹配字串之前的輸出部分,$after 為匹配字串之后的輸出部分。下面這個例子 (matchinfo.pl 及其輸出結果 ) 具體說明了這些值的含義:

清單 7. matchinfo.pl

				
 #! /usr/bin/perl 
 # 9.125.13.44 是一臺 ftp 服務器,使用 ftp 命令登錄時的輸出為:
 # Connected to 9.125.13.44. 
 # 220 AIX6144 FTP server (Version 4.2 Tue Dec 22 14:13:26 CST 2009) ready. 
 # 502 authentication type cannot be set to GSSAPI 
 # 502 authentication type cannot be set to KERBEROS_V4 
 # KERBEROS_V4 rejected as an authentication type 
 # Name (9.125.13.44:root): 

 use Expect; 
 $obj = Expect->spawn( "ftp 9.125.13.44" ) or die "Couldn't spawn ftp, $!"; 
 # 關閉目標程序的輸出顯示
 $obj->log_stdout( 0 ); 
 # 使用 slice 獲取列表環境下的返回值
 @result{ "position", "error", "match", "before", "after" } = $obj->expect( 10, 'Name' ); 
 # 查看匹配結果
 print "$_ = $result{$_}\n" foreach ( keys %result ); 
 # 關閉目標程序
 $obj->soft_close( ); 

為了使運行結果更加清楚,示例中使用 $obj->log_stdout(0)關閉目標程序的輸出顯示。該程序的運行結果為:

清單 8. matchinfo.pl 輸出結果

				
 after =  (9.125.13.44:root): 
 match = Name 
 error = 
 position = 1 
 before = Connected to 9.125.13.44. 
 220 AIX6144 FTP server (Version 4.2 Tue Dec 22 14:13:26 CST 2009) ready. 
 502 authentication type cannot be set to GSSAPI 
 502 authentication type cannot be set to KERBEROS_V4 
 KERBEROS_V4 rejected as an authentication type 

Expect 對象也提供了單獨的方法來獲得這些匹配信息,如 $obj->before( ),$obj->after( ),$obj->match( ),$obj->error( ) 等。

使用 -i 選項可以對多個或多組 Expect 對象同時執行 expect 操作:

清單 9. -i 選項

				
 $obj1 = Expect->spawn( "ftp 9.125.13.44" ) or die $!; 
 $obj2 = Expect->spawn( "telnet 9.9.9.9" ) or die $!; 
 $obj3 = Expect->spawn( "ssh 9.181.59.64" ) or die $!; 
 expect ( $timeout, 
         '-i', $obj1, '-re', qr/name/i, 
         '-i', [$obj2, $obj3], '-re', qr/login/i, '-re', qr/password/i, 
 ) 

本例使用函數風格的 expect 方法 ( 區別于通過對象調用 ),構造匿名數組的引用 [...] 來傳遞多個 Expect 對象。

此外在 $obj->expect($timeout, @match_patterns)中,@match_patterns 還可采用 [ $regexp, sub{}, @opt_params ]的形式,根據不同模式來執行不同后續操作。邏輯流程較為簡單時,利用此特點可以使代碼組織更加緊湊。下面的 telnet 登錄腳本 (exptelnet.pl) 采用了這種形式:

清單 10. exptelnet.pl

				
 #! /usr/bin/perl 
 use Expect; 

 my $PROMPT = '[\]\$\>\#]\s*$'; # 遠程系統的命令提示符模式
 $obj = Expect->spawn( "telnet 9.125.13.44" ) or die "Couldn't spawn telnet, $!"; 
 $obj->expect( 10, 
        [ qr/login:\s*$/i, 
          sub{ my $self = shift; $self->send( "root\r" ); exp_continue;} 
        ], 
        [ qr/password:\s*$/i, 
          sub{ my $self = shift; $self->send( "zu88jie\r" ); exp_continue;} 
        ], 
        [ qr/$PROMPT/, 
          sub{my $self=shift; $self->send( "logout\r" ); exp_continue_timeout;} 
        ], 
 ); 

示例中匿名函數返回 exp_continue 符號將重置等待時間并繼續執行 expect,使得一次 expect 調用可以完成多次匹配動作。與之相對的是返回 exp_continue_timeout 符號,在繼續執行 expect 時不重置等待時間。

#p#

send:發送數據

清單 11. send 方法原型

				
 $obj->send( @strings ); 

當交互式程序等待用戶輸入時,可以使用 send 方法向其提供輸入數據。需要注意,send 送出的數據可能會回顯在終端上 ( 具體與終端設置有關 ),此數據會進入 Expect 對象的匹配緩沖區,被下一個 expect 動作接收。為了避免 send 數據對 expect 匹配造成混亂,一般可以使用 $obj->stty( "-echo" )方法關閉終端回顯,或者在 spawn 前使用 $obj->raw_pty(1)將終端設定成 raw 模式 (raw 模式將關閉回顯,禁止回車 - 換行符翻譯 ),或者為 expect 提供更加精確的匹配模式。

log_file:設置日志記錄

清單 12. log_file 方法原型

				
 $obj->log_file( $filename | $filehandle | undef ); 

將交互過程的內容輸出到日志文件能便于自動化腳本的追蹤和調試。通常使用文件名或者文件句柄作為參數來指定具體日志文件,例如:

清單 13. 設置日志記錄

				
 $obj = Expect->spawn( "ftp 9.9.9.9" ); 	
 # 使用"w"選項截斷舊日志
 $obj->log_file( "./out.log", "w" );  

debug:設置調試信息

清單 14. debug 方法原型

				
 $obj->debug( 0 | 1 | 2 | 3 ); 

參數 0 為禁止調試信息 ( 缺省值 ),1 ~ 3 級詳細程度遞增。另一個相關的方法是 $object->exp_internal( 1 | 0 ),用以打開或關閉 expect 對象的內部調試信息。將此標志設置為 1 可以看到 expect 對象對輸出內容嘗試匹配的完整過程 (expdebug.pl):

清單 15. expdebug.pl

				
 #! /usr/bin/Perl 
 use Expect; 
 $obj = Expect->spawn( "ftp 9.125.13.44" ) or die $!; 
 $obj->exp_internal( 1 ); # 打開對象內部調試信息
 $obj->expect( 10, "Name" ); 
 $obj->soft_close( ); 

運行結果為:

清單 16. expdebug.pl 輸出詳細匹配過程

				
 Starting EXPECT pattern matching... 
 ... 省略中間輸出 ... 
 spawn id(3): Does `'
 match: 
  pattern #1: -ex `Name'? No. 
 ... 省略中間輸出 ... 
 match: 
  pattern #1: -ex `Name'? YES!! 
    Before match string: `Connected to 9.125.13.44.\r\n220 AIX6144 FTP server ...'
    Match string: `Name'
    After match string: ` (9.125.13.44:root): '
    Matchlist: () 

從結果中可以監視目標程序每一條輸出與 expect 模式的匹配情況,若匹配成功還能查看 before\match\after 字串,這對于調試程序大有幫助。

interact:返回交互模式

清單 17. interact 方法原型

				
 $obj->interact( ); 

為了適應某些特殊場合,我們可能需要將控制權交還給目標程序,此時只需使用 $obj->interact( )方法。

clear_accum 與 set_accum:操縱匹配緩沖區

清單 18. clear_accum 與 set_accum 方法原型

				
 $obj->clear_accum( ); 
 $obj->set_accum( $value ); 

expect 方法針對 Expect 對象的匹配緩沖區 (accumulator) 進行匹配嘗試,默認情況下每次匹配成功后,accumulator 中 before 和 match 部分將被清除,下次匹配從 after 開始。但是 Expect 對象提供了 clear_accum 與 set_accum 方法改變這種行為:使用 $obj>set_accum( $value )將緩沖區內容設置成 $value,使用 $obj>clear_accum( )清空緩沖區內容。具體用法參見如下代碼片段:

清單 19. 操縱匹配緩沖區內容

				
 $obj->notransfer( 1 ); 
 $obj->expect( $timeout, 
            # 1 保留 accumulator 內容 , pattern1 將被再次匹配
	    [ "pattern1", 
              sub { my $self = shift; ... } 
            ], 
            # 2 將 accumulator 內容設置為 after string,即截斷 before 和 match string 
            [ "pattern2", 
              sub { my $self = shift; ...; $self->set_accum( $self->after( ) );} 
            ], 
            # 3 將 accumulator 內容清空
	    [ "pattern3", 
              sub { my $self = shift; ...; $self->clear_accum( );} 
            ], 
 ); 

示例中 $obj->notransfer( 0 | 1 )方法用于設置是否保留匹配緩沖區內容。0 是默認行為 ( 清除 before 和 match);1 為保留所有內容。保留緩沖區內所有內容會導致原先匹配過的模式被再次匹配 (#1)。我們也可手動設置 accumulator 內容來影響下一次匹配 (#2 #3)。

#p#

Expect::Simple 模塊詳解

Expect::Simple 對 Expect 模塊進行了封裝,隱藏其內部復雜機制。此模塊處理一些簡單的應用已經足夠。

new;構造方法

清單 20. new 方法原型

				
 $obj = Expect::Simple->new( \%attr ); 

創建 Expect::Simple 對象的同時啟動目標程序,需傳遞關聯數組 %attr 的引用作為參數。通過該關聯數組設置目標程序的相關信息 ( 如命令、超時、提示符等 ),因此該數組必須包含 Prompt,DisconnectCmd,Cmd 等鍵值。

Cmd 鍵指定目標程序及其參數。它的值可以是標量或者是數組引用:Cmd => $commandCmd => [ $command, $arg1, $arg2, ...]。在 Expect::Simple 的實現中 $command 或 $command, $arg1, $arg2, ...都被直接傳給 Expect 的 spawn 方法,因此前面對 spawn 方法的分析在這里同樣適用:可以把完整的命令行寫入 $command;對不含 shell 元字符的簡單命令,也可以使用分拆形式,傳遞數組引用。

Prompt 鍵指定一個或一組預期的輸入提示 ( 支持正則表達式 ):Prompt => ['ftp>', 'telnet>', -re => 'prompt\d+>\s+']。Prompt 鍵值相當于 Expect 模塊中 expect 方法的匹配模式參數。

DisconnectCmd 鍵指定退出目標程序所用的指令:DisconnectCmd => 'exit'

Timeout 鍵設定超時 ( 缺省值為 1000 秒 ),如果目標程序在設定時間內未響應則返回。Expect::Simple 在目標程序啟動之前設置超時且使用全局設定,因此無法區分處理目標程序執行過程中立即響應部分和有明顯延時的部分。在設定超時值時需要考慮響應最慢的階段。

RawPty 鍵用于設置終端,對應于 Expect 模塊的 raw_pty 方法,默認值為 0。

Verbose 鍵用于設定輸出內容的詳細程度:Verbose => 3

send:順序發送數據

使用 $obj->send( $cmd | @cmds)向目標程序發送一條或依次發送多條數據。每條數據送達后等待下一個輸入提示以發送下一條數據。以 ssh 自動登錄為例,serialsend.pl 演示如何順序發送多條數據:

清單 21. serialsend.pl

				
 #! /usr/bin/perl 
 use Expect::Simple; 
 my %attr = ( 
        Prompt          => [ -re => qr/password:\s*$/i, 
                             -re => qr/[\]\$\>\#]\s*$/ ], 
        Cmd             => 'ssh root@9.125.13.44', 
        DisconnectCmd   => 'exit', 
        Verbose         => 3, 
        Timeout         => 10, 
 ); 
 my $obj = Expect::Simple->new( \%attr ); 
 # 自動輸入密碼,執行 ls 命令,退出。由于已設定退出命令,此處不必再發送 exit 
 $obj->send( "zhu88jie", "ls" ); 

輸出結果:

清單 21. serialsend.pl 執行結果

				
 Running command...done. 
 Sending `zhu88jie'
 Sending `ls'
 Disconnecting. 

若想看到 ls 命令的執行輸出,只需將 Verbose 值設為 4。

before,after,match_str,error:查看匹配信息

這些方法和 Expect 模塊中的 before,after,match,error 一一對應,不再詳細闡述。需要注意由于 Expect 對象的緩沖區在匹配過程中會不斷更新,在依次發送多條數據的情況下,使用這些方法只能查看最近一次匹配結果。

expect_handle:使用內部對象

Expect::Simple 封裝了 Expect 模塊的細節,提供簡單易用的接口,但是當 Expect::Simple 提供的功能無法以滿足需求時,還可以使用這個方法直接操作內部 Expect 對象。

#p#

應用示例

Expect 模塊使用示例

本例 (ftpdemo.pl) 演示如何使用 Expect 模塊從 ftp 上自動下載文件。

清單 22. ftpdemo.pl

				
 #!/usr/bin/perl 
 # Usage: ftpdemo.pl [-u username] [-p password] host file1 [file2 file3 ...] 
 use Expect; 
 use Getopt::Std; 

 # 設置缺省用戶名和密碼
 my %opts = ( u=>'anonymous', p=>'anonymous@mycompany.com' ); 
 # 解析 -u 和 -p 選項
 getopt( 'up', \%opts ); 
 $host = shift @ARGV;            # 下一個參數是 ftp 服務器地址
 @files = @ARGV;                 # 余下的參數為需要下載的文件

 # 啟動 ftp 進程
 print "Starting ftp session with server $host ...\n"; 
 $ftp = Expect->spawn( "ftp $host" ) or die "Couldn't spawn ftp, $!"; 

 # 屏蔽多余輸出
 $ftp->log_stdout( 0 ); 

 # 等待用戶名輸入提示
 unless ( $ftp->expect(30, -re=>qr/name \(.*?\):\s*$/i) ) { 
  die "Never got username prompt on $host, ".$ftp->error( )."\n"; 
 } 

 # 發送用戶名數據
 print "Sending username ($opts{u}) ... \n"; 
 $ftp->send( "$opts{u}\r" ); 

 # 等待密碼輸入提示
 unless ( $ftp->expect( 30, -re=>qr/password:\s*$/i ) ) { 
  die "Never got password prompt on $hostname, ".$ftp->error( )."\n"; 
 } 

 # 發送密碼
 print "Sending password ( $opts{p} ) ... \n"; 
 $ftp->send( "$opts{p}\r" ); 

 # 等待 ftp 命令行提示
 unless ( $ftp->expect(30,"ftp>") ) { 
  die "Never got ftp prompt after sending username, ".$ftp->error( )."\n"; 
 } 

 # 下載文件
 foreach my $file ( @files ) { 
  print "Getting the $file ... \n"; 
  $ftp->send( "get $file\r" ); 
  unless ( $ftp->expect( 30,"ftp> " ) ) { 
    die "Never got ftp prompt after attempting to get $file, ".$ftp->error( )."\n"; 
  } 
 } 

 # 斷開 ftp 連接
 print "Download finished. Disconnecting ... \n"; 
 $ftp->send( "bye\r" ); 
 $ftp->soft_close( ); 
 print "Done.\n"; 

使用此腳本從 9.125.13.44 的 ftp 根目錄下載 diskusage.log 文件,運行結果:

清單 23. ftpdemo.pl 執行結果

				
 # ./ftpdemo.pl -u root -p zhu88jie 9.125.13.44 diskusage.log 
 Starting ftp session with server 9.125.13.44 ... 
 Sending username (root) ... 
 Sending password (zhu88jie) ... 
 Getting the diskusage.log ... 
 Download finished. Disconnecting ... 
 Done. 
 # 

Expect::Simple 模塊使用示例

本例演示如何使用 Expect::Simple 對目標程序的輸入輸出進行測試。腳本 target.pl 作為此例中的目標程序。target.pl 循環讀取用戶輸入,直到用戶輸入 quit 時退出。

清單 24. target.pl

				
 #! /usr/bin/perl 
 my $p = 'tpt %d> ';             # 輸入提示符
 printf( $p, 0 ); 
 while( <> ){ 
    do { print "byebye\n"; last } if /quit/; 
                                # 如果用戶輸入 quit 則輸出"byebye",跳出循環
    print uc( $_ );             # 否則以大寫的形式輸出用戶本次輸入
    printf( $p, $. );           # 更新輸入提示符,$. 為讀入行數計數器 
 } 
 print "quit> \n";               # 打印結束輸入提示符

某次運行結果如下:

清單 25. target.pl 執行結果示例

				
 # ./target.pl 
 tpt 0> 1 
 1 
 tpt 1> 2 
 2 
 tpt 2> quit 
 byebye 
 quit> 
 # 

exptest.pl 腳本用來模擬用戶輸入不同數據以測試目標程序的功能:

清單 26. exptest.pl

				
 #! /usr/bin/perl 
 use Test::More tests => 4; # 計劃執行的測試用例總數
 use Expect::Simple; 

 my %attr = ( Cmd => "./target.pl"
             DisconnectCmd => 'quit', 
             Prompt => [ -re => 'tpt\s\d+> ',  'quit> '], 
             RawPty => 1, 
             Verbose =>3, 
 ); 
 my $res;                   # 實際輸出結果
 my $obj = Expect::Simple->new( \%attr ); 

 # 測試用例 1,用戶輸入 a,預期目標程序輸出 A 
 $obj->send( 'a' ); 
 chomp( $res = $obj->before ); 
 is( $res, 'A', 'Test case 1: Input "a" -> Output "A"' ); 

 # 測試用例 2,用戶輸入 b,預期目標程序輸出 B 
 $obj->send( 'b' ); 
 chomp( $res = $obj->before ); 
 is( $res, 'B', 'Test case 2: Input "b" -> Output "B"' ); 

 # 測試用例 3,用戶輸入 quit,預期目標程序輸出 byebye 
 $obj->send( 'quit' ); 
 chomp( $res = $obj->before ); 
 is( $res, 'byebye', 'Test case 3: Input "quit" -> Output "byebye"' ); 

 # 測試用例 4,目標程序輸出 byebye 后應直接輸出 quit> 
 is ( $obj->match_str, 'quit> ', 'Test case 4: Output "byebye" -> Output "quit>" ' ); 

程序引用了 Test::More 模塊,Test::More 是一個編寫測試腳本的框架,這里只介紹程序中涉及的部分,更多內容請查閱 CPAN 網站上相關信息。整個測試過程使用 is 函數來判斷用例的執行結果:is ( $got, $expected, $comments )。該函數判斷 $got 與 $expected 是否相等,相等則通過,輸出“ok”,否則輸出“not ok”。

在 target.pl 循環執行的過程中,如果用戶未輸入 quit,則每次 expect 都匹配到輸入提示符“tpt\s\d+>”上,而終端回顯又被關閉,因此匹配緩沖區的 before 部分即為目標程序上次輸出的結果。程序中使用 $res 變量獲得目標程序的實際輸出,與預期結果比較判斷測試用例是否通過。exptest.pl 實際執行的結果為:

清單 27.exptest.pl 執行結果

				
 # ./exptest.pl 
 1..4 
 Running command...done. 
 Sending `a'
 ok 1 - Test case 1: Input "a" -> Output "A"
 Sending `b'
 ok 2 - Test case 2: Input "b" -> Output "B"
 Sending `quit'
 ok 3 - Test case 3: Input "quit" -> Output "byebye"
 ok 4 - Test case 4: Output "byebye" -> Output "quit>"
 Disconnecting.  
 # 

原文:http://www.ibm.com/developerworks/cn/linux/l-cn-perl-expect/index.html?ca=drs-

【編輯推薦】

  1. 在Linux下靈活使用expect腳本的小竅門
  2. Linux腳本分享:自動關機與計算任務管理
  3. 不看后悔的Linux生產服務器Shell腳本分享
責任編輯:yangsai 來源: IBMDW中國
相關推薦

2011-09-29 10:58:51

rBuilderLinux

2018-02-10 18:35:09

LinuxAnsible系統管理

2022-07-11 10:08:19

系統管理任務自動化

2011-08-02 11:31:35

Cfengine系統管理

2011-10-19 10:49:07

系統管理備份自動化

2011-10-10 14:21:18

系統管理自動化

2011-10-10 13:45:32

系統管理自動化

2011-11-17 16:06:45

IT系統管理

2011-07-04 14:16:03

2013-03-22 15:15:28

自動化管理部署虛擬化

2012-03-30 15:52:51

ibmdw

2011-03-03 10:20:06

bash系統管理

2013-09-18 10:57:09

虛擬化應用

2021-04-01 06:13:50

Ansible系統運維

2010-10-21 16:18:18

2010-05-05 15:56:37

Unix系統

2010-07-15 13:21:46

Perl多進程

2015-10-21 15:08:25

電纜自動化

2009-10-23 16:03:40

Oracle 10g系內存管理

2025-02-06 14:59:08

點贊
收藏

51CTO技術棧公眾號

亚洲国产日韩在线观看| 青青草原在线免费观看| 另类中文字幕国产精品| 国产精品传媒入口麻豆| 亚洲综合中文字幕68页| 国产亚洲精久久久久久无码77777| 久久97精品| 欧美性xxxxx极品少妇| 真人做人试看60分钟免费| 天堂网www中文在线| 九九九久久久精品| 91精品国产精品| 成人午夜免费影院| 人人网欧美视频| 欧美日产在线观看| 99热在线这里只有精品| 麻豆传媒视频在线观看免费| 99热国产精品| 成人精品aaaa网站| 神马久久久久久久| 国产精品国码视频| 国产午夜精品免费一区二区三区| 亚洲热在线视频| 精品欧美一区二区三区在线观看 | 成人网在线免费视频| 国产成人jvid在线播放| 久久国产精品二区| 93在线视频精品免费观看| 亚洲精品国产电影| 成年人性生活视频| 久久久久黄色| 色88888久久久久久影院野外| 美女av免费观看| 一区二区三区视频在线观看视频| 久久综合一区二区| 国产精品手机视频| 国产熟女精品视频| 奇米亚洲午夜久久精品| 日本精品久久久久影院| 久久这里只有精品国产| 中文av一区| 日韩一区二区欧美| 五月天精品在线| 精品欧美久久| 国产亚洲人成网站在线观看 | 国产精品色哟哟网站| 免费毛片一区二区三区久久久| 精品国产99久久久久久宅男i| 蜜臀久久99精品久久久画质超高清| 91av视频在线免费观看| 国产91av视频| 亚洲高清电影| 国自产精品手机在线观看视频| 青青草免费av| 欧美成人一品| 欧美精品一区二区三区国产精品| 欧美另类videoxo高潮| 99热国内精品永久免费观看| 色噜噜狠狠狠综合曰曰曰| 国产破处视频在线观看| 欧美电影免费播放| 久色乳综合思思在线视频| 亚洲精品卡一卡二| 一区二区三区四区电影| 欧美寡妇偷汉性猛交| 波多野结衣不卡视频| 欧美人成在线| 国内揄拍国内精品| aaaaaa毛片| 日本v片在线高清不卡在线观看| 国产成人在线视频| 一区二区三区精彩视频| 韩国欧美一区二区| 国产精品免费视频一区二区| 无码国产精品一区二区免费16| 97aⅴ精品视频一二三区| 欧美日韩成人一区二区三区| av中文字幕在线| 国产精品成人一区二区艾草| 久久精品在线免费视频| freexxx性亚洲精品| 色综合天天性综合| 最新天堂在线视频| 99re91这里只有精品| 日韩国产中文字幕| 成年人看的免费视频| 在线一区电影| 欧美性视频网站| 亚洲一区精品在线观看| 国产精品 欧美精品| 精品久久蜜桃| 日本在线免费中文字幕| 亚洲伊人伊色伊影伊综合网| 777米奇影视第四色| 国精品产品一区| 亚洲第一页自拍| 久久婷婷五月综合| 激情av一区| 国产精品第一区| 亚洲成人中文字幕在线| 国产无人区一区二区三区| av 日韩 人妻 黑人 综合 无码| 涩涩在线视频| 日韩一级在线观看| 亚洲国产av一区| 欧美先锋影音| 国产精品久久久久高潮| 东京干手机福利视频| 欧美激情一区二区三区全黄| 久久人人爽人人爽人人av| 丁香久久综合| 日韩精品中文字幕在线| 欧美成人精品一区二区免费看片| 久久精品五月| 国产精品一级久久久| 日本暖暖在线视频| 色成年激情久久综合| www.17c.com喷水少妇| 手机在线一区二区三区| 日本免费久久高清视频| 蜜桃av中文字幕| 亚洲日本电影在线| 999精品视频在线| 欧美一级三级| 欧美精品激情在线| 国产农村妇女毛片精品| 欧美激情一区三区| 午夜免费一区二区| 亚洲欧洲美洲国产香蕉| 韩国三级电影久久久久久| 精品国产无码一区二区| 国产精品高清亚洲| 黄色片在线免费| 自拍偷拍精品| 欧美最近摘花xxxx摘花| 午夜黄色小视频| 亚洲成人综合网站| 野战少妇38p| 国模吧视频一区| www.久久草| 亚洲资源一区| 欧美一级艳片视频免费观看| 色哟哟一一国产精品| 美国一区二区三区在线播放| 日本一区美女| 精品国产欧美日韩一区二区三区| 亚洲欧美国产日韩中文字幕| 成人午夜视频在线播放| 99国产精品一区| 少妇无码av无码专区在线观看 | 欧美成人免费看| 国产精品1024| 精品丰满人妻无套内射| 精品福利一区| 欧美中文在线字幕| 精品亚洲综合| 欧美日韩午夜在线| 美女福利视频网| 精品在线播放午夜| 潘金莲一级淫片aaaaaa播放1| 电影一区二区三区久久免费观看| 久久久国产91| 99热这里只有精品99| 亚洲综合在线免费观看| 国产xxxx视频| 日韩成人av影视| 中文字幕av日韩精品| 韩国一区二区三区视频| 欧美大秀在线观看| 午夜小视频在线播放| 日本韩国一区二区三区视频| 日韩福利在线视频| 国产中文字幕一区| 又大又硬又爽免费视频| 亚洲电影男人天堂| 国产日本欧美一区二区三区| 少女频道在线观看高清 | 99久久综合狠狠综合久久止| 黄色的视频在线观看| 亚洲免费av片| 91成品人影院| 午夜在线成人av| 国产真人做爰视频免费| 国产精品影音先锋| 国产欧美在线一区| 国产精品黑丝在线播放| 国产一区在线免费| 日韩美女在线| 97在线免费观看视频| 成人在线观看一区| 精品国产污网站| 精人妻无码一区二区三区| 亚洲人妖av一区二区| 天天插天天射天天干| 麻豆91小视频| 男女私大尺度视频| 热久久天天拍国产| 好看的日韩精品视频在线| 成人mm视频在线观看| 欧美高清视频一区二区| av在线中文| 亚洲高清一区二| 91theporn国产在线观看| 欧美色欧美亚洲高清在线视频| 欧美一级特黄高清视频| 91啪九色porn原创视频在线观看| 无套内谢丰满少妇中文字幕| 丝袜美腿高跟呻吟高潮一区| 日韩精品视频在线观看视频| 99国产**精品****| 久久精品五月婷婷| 97精品久久| 国产色婷婷国产综合在线理论片a| av毛片午夜不卡高**水| 久久精品久久精品亚洲人| 免费在线看v| 亚洲国产欧美在线成人app | 日韩av在线不卡| 国产婷婷一区二区三区久久| 在线观看日韩国产| 久久久久久久久久久久久av| 一区二区三区免费网站| 日韩精品久久久久久久的张开腿让| 91片黄在线观看| 美女久久久久久久久| 国产美女一区二区三区| 在线观看免费视频高清游戏推荐| 亚洲在线观看| 免费一级特黄特色毛片久久看| 888久久久| 中文字幕人成一区| 日本成人小视频| 色女人综合av| 成人羞羞网站| 色视频一区二区三区| 亚洲第一论坛sis| 久久久精品国产一区二区三区| 国产成人精品福利| 国产精品国产精品| 51vv免费精品视频一区二区| 亚洲一区二区三区四区在线播放| 亚州欧美在线| 91最新在线免费观看| 97久久精品一区二区三区的观看方式 | 日韩视频不卡中文| 国产aⅴ爽av久久久久成人| 欧美群妇大交群中文字幕| 在线免费看毛片| 欧美性色黄大片| 亚洲天堂2021av| 欧美日韩一级二级| 91超薄丝袜肉丝一区二区| 在线不卡免费av| 国产丰满美女做爰| 精品伦理精品一区| 日本一区二区三区在线观看视频| 日韩精品亚洲视频| 久久久资源网| 中文字幕综合一区| 看女生喷水的网站在线观看| 久久成人精品视频| 久久免费电影| 琪琪第一精品导航| 国产成人午夜性a一级毛片| 91精品久久久久久久久久| 欧洲一区在线| 精品欧美一区二区久久久伦| 啄木系列成人av电影| 夜夜春亚洲嫩草影视日日摸夜夜添夜 | 国产资源在线一区| 好吊操视频这里只有精品| 99九九99九九九视频精品| 人妻aⅴ无码一区二区三区| 国产精品久久午夜| 国产在线观看99| 欧美视频一二三| 夜夜狠狠擅视频| 精品国产乱码久久久久久浪潮| 日韩欧美电影在线观看| 最近2019中文免费高清视频观看www99| 麻豆免费在线观看| 51视频国产精品一区二区| 国产成人精品一区二区三区视频| 91亚洲精品在线| 亚洲春色h网| ijzzijzzij亚洲大全| 国产精品嫩草99av在线| 日本美女视频一区| 99视频精品免费视频| 一本一本久久a久久| 五月激情综合色| 一级爱爱免费视频| 日韩精品亚洲元码| 99视频免费在线观看| 日韩美女视频中文字幕| 视频二区欧美毛片免费观看| 免费成人深夜夜行视频| 伊人久久大香线蕉综合四虎小说 | 国内精品不卡在线| 亚洲最大成人网站| 亚洲精品日日夜夜| 久久久久亚洲视频| 精品播放一区二区| 一区二区三区视频网站| 97超级碰碰碰久久久| 国产精品777777在线播放| 欧美日韩精品不卡| 国产中文一区| 亚洲欧美视频二区| 26uuu国产电影一区二区| 久久久久久久9999| 欧美日韩精品一区二区在线播放| 亚洲av成人无码网天堂| 欧美黑人xxxⅹ高潮交| 日韩av黄色| 日本一区视频在线观看| 国产精品一卡| 四虎成人免费视频| 亚洲老妇xxxxxx| 亚洲综合精品国产一区二区三区 | 久久国产精品高清| 欧美日韩1区| 两性午夜免费视频| 18欧美乱大交hd1984| 日韩欧美一级大片| 亚洲免费精彩视频| 亚洲天堂av在线| 激情小说综合网| 亚洲经典自拍| 黄色性视频网站| 午夜在线成人av| 国内爆初菊对白视频| www.久久久久| 国产一区二区三区免费观看在线| 亚洲亚洲精品三区日韩精品在线视频| 亚洲中字在线| 亚洲一区二区三区蜜桃| 欧美性xxxx极品hd满灌| 男女视频在线观看免费| 欧美在线视频一区| 亚洲成aⅴ人片久久青草影院| 国产69精品久久久久久久| 不卡在线视频中文字幕| 日韩 国产 在线| 精品无人区乱码1区2区3区在线| 国内精彩免费自拍视频在线观看网址| 国产精品久久九九| 日韩一区二区久久| 成年人网站免费看| 色激情天天射综合网| melody高清在线观看| 91精品久久久久久久久久久| 先锋资源久久| 深夜视频在线观看| 亚洲丶国产丶欧美一区二区三区| 性感美女福利视频| 日韩免费精品视频| 93在线视频精品免费观看| 99视频在线观看视频| 亚洲午夜久久久久久久久久久 | 中文字幕亚洲自拍| 高清精品久久| 欧美日韩不卡在线视频| 26uuu欧美| 中文字幕二区三区| 欧美日韩xxxxx| 秋霞蜜臀av久久电影网免费| 久久综合伊人77777麻豆最新章节| 国产精品白丝在线| 亚洲黄色小说网| 热久久免费视频精品| 日韩精品诱惑一区?区三区| 宇都宫紫苑在线播放| 午夜精品久久久久久久99樱桃 | 亚洲国产精品传媒在线观看| 国产日本精品视频| 91国产视频在线| 欧美韩日一区| 中文字幕乱码一区| 欧美日韩在线观看一区二区| 在线观看h网| 欧美不卡在线一区二区三区| 久久99久久99精品免视看婷婷| 久久视频免费看| 国产亚洲精品久久久久久| 一区二区三区四区精品视频| 欧美污视频网站| 亚洲激情五月婷婷| 国产精品久久久久一区二区国产| 91久久精品国产91久久性色| 国产偷自视频区视频一区二区| 貂蝉被到爽流白浆在线观看| 精品国产一区二区三区久久久蜜月 | 日韩电影免费| 亚洲一区二区三区乱码aⅴ| 国产精品嫩草99av在线| 日韩va亚洲va欧美va清高| 日韩精品视频在线观看免费| 久久精品一级| 午夜国产一区二区三区|