1. 程式人生 > >Shell應用(9):自動化批量編譯

Shell應用(9):自動化批量編譯

指令碼概述
   當需要在很多(比如幾十至幾百)臺機器上編譯同一程式時,如果一個個地手工拷貝原始碼、再編譯,那麼效率就很低,為了能大量節省手工、並行地編譯,因此寫了一個指令碼,該指令碼基於自動化指令碼語言expect(expect基於tcl)實現,基本原理是針對每個遠端主機,建立一個子程序,在該子程序內先呼叫scp拷貝原始碼到遠端主機,再用ssh登入到遠端主機、傳送cd、configure和make命令,互動期間的命令輸出多用正則分析,最終的編譯輸出儲存到當前目錄output子目錄下。其命令列引數說明如下:
    第1引數為遠端主機配置檔案:一個多行文字檔案,每行格式為IP 使用者名稱 密碼,空格符分隔,支援#註釋。
   
 第2引數為本地主機原始碼目錄:要求該目錄存在Makefile和configure檔案。
    第3引數為遠端主機目標目錄:用於存放原始碼的位置。

指令碼實現
   拷貝原始碼  1proc copy_file {host user srcdir dstdir passwd {to10} } {
 2    if [catch "spawn scp -rq $srcdir [email protected]$host:$dstdir" msg] {
 3        send_error "failed to spawn scp: $msg\n" 4        exit1 5
    }
 6    
 7    set timeout $to 8    expect_after eof { 
 9        send_error "$host scp died unexpectedly\n"10        exit111    }
12    expect {
13        "(yes/no)?" { send "yes\r"; exp_continue }
14        -re "(?:P|p)assword:" { send "$passwd\r" }
15        timeout { do_timeout "$host scp" }
16    }
17

18    expect {
19        full_buffer { exp_continue }
20        timeout { exp_continue }
21        eof 
22    }
23}    第2行呼叫spawn命令執行scp命令,並用catch捕捉錯誤;當執行成功後,第12行用expect等待遠端輸出(超時預設為10秒),第13、14行自動輸入使用者名稱和密碼,當過程中網路連線斷開時,會匹配到第8行的eof;當輸出完成連線關閉時,會匹配到第21行的eof;如果輸出太多超過expect內部的buffer時,會匹配到第19行的full_buffer,這裡由於為了提高效率,使用了靜默方式的scp,因些實際會匹配到第20行的timeout,不管匹配到哪種情況,都要繼續直到eof。
 
   執行編譯  1proc do_make {host user passwd subdir {to10} } {
 2    if [catch {spawn ssh [email protected]$host} msg ] {
 3        send_error "failed to spawn ssh: $msg\n" 4        exit1 5    }
 6    
 7    set timeout $to 8    expect_after eof { 
 9        send_error "$host ssh died unexpectedly\n"10        exit111    }
12    
13    expect {  
14        "*yes/no" { send "yes\r"; exp_continue }
15        -re "(?:P|p)assword:" { send "$passwd\r" }  
16        timeout { do_timeout "$host ssh" }
17    }  
18    wait_cmd $spawn_id passwd19
20    send "cd $subdir\r"21    wait_cmd $spawn_id cd
22    
23    send "source configure\r"24    wait_cmd $spawn_id configure
25
26    send "make\r"27    wait_cmd $spawn_id make
28
29    send "exit\r"30    expect eof  
31}    關於spawn和expect的解釋與上節拷貝原始碼相同,不同的是依次傳送命令cd、source configure、make,每個命令須等到命令提示符後(呼叫自定義函式wait_cmd)再發下一個,最後傳送exit退出ssh、導致連線關閉,匹配到最後一行的eof。對於有的專案原始碼,可能沒有或不用配置,那麼configure檔案可以不存在或內容為空,如果不存在導致報錯也沒關係,不影響make;如果configure出錯,那麼make也會出錯。這裡使用source是為了使配置在當前shell中生效。
   
   主迴圈  1set f [open $file r]
 2set curtime [clock seconds]
 3
 4log_user 0 5set s {[:blank:]}
 6set pattern "^(\[^#$s]+)\[$s]+(\[^$s]+)\[$s]+(\[^$s]+)" 7
 8while { [gets $f line] !=-1 } {
 9    if { ![regexp $pattern [string trimleft $line] ? host user passwd] } {
10        continue
11    }
12    send_user "$host $user $passwd\n"13    if { ![fork] } {
14        
15        set filename output/${host}_[clock format $curtime -format %y.%m.%d_%H.%M.%S].log
16        log_file -noappend -a $filename
17
18        copy_file $host $user $srcdir $dstdir $passwd 3019        do_make $host $user $passwd $subdir 3020
21        send_user "$host finish\n"22        exit23    }
24}    開啟遠端主機配置檔案,讀取每一行直到檔案尾,忽略註釋行,用正則提取IP、使用者名稱和密碼,建立子程序,按IP和當前時間命名log檔案(由於前面呼叫log_user 0關閉了控制檯輸出,因此為了能記錄輸出到日誌檔案,一定要加-a選項),最後呼叫函式copy_file和do_make。
   
   完整指令碼下載:autobuild.zip posted on 2016-09-28 11:04 春秋十二月 閱讀(2964) 評論(0)  編輯 收藏 引用 所屬分類: System