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