• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            隨筆-162  評論-223  文章-30  trackbacks-0
            腳本概述
               當需要在很多(比如幾十至幾百)臺機器上編譯同一程序時,如果一個個地手工拷貝源碼、再編譯,那么效率就很低,為了能大量節省手工、并行地編譯,因此寫了一個腳本,該腳本基于自動化腳本語言expect(expect基于tcl)實現,基本原理是針對每個遠程主機,創建一個子進程,在該子進程內先調用scp拷貝源碼到遠程主機,再用ssh登錄到遠程主機、發送cd、configure和make命令,交互期間的命令輸出多用正則分析,最終的編譯輸出保存到當前目錄output子目錄下。其命令行參數說明如下:
                第1參數為遠程主機配置文件:一個多行文本文件,每行格式為IP 用戶名 密碼,空格符分隔,支持#注釋。
                第2參數為本地主機源碼目錄:要求該目錄存在Makefile和configure文件。
                第3參數為遠程主機目標目錄:用于存放源碼的位置。

            腳本實現
               拷貝源碼
             1proc copy_file {host user srcdir dstdir passwd {to 10} } {
             2    if [catch "spawn scp -rq $srcdir $user@$host:$dstdir" msg] {
             3        send_error "failed to spawn scp: $msg\n"
             4        exit 1
             5    }
             6    
             7    set timeout $to
             8    expect_after eof { 
             9        send_error "$host scp died unexpectedly\n"
            10        exit 1
            11    }
            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 {to 10} } {
             2    if [catch {spawn ssh $user@$host} msg ] {
             3        send_error "failed to spawn ssh: $msg\n"
             4        exit 1
             5    }
             6    
             7    set timeout $to
             8    expect_after eof { 
             9        send_error "$host ssh died unexpectedly\n"
            10        exit 1
            11    }
            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 passwd
            19
            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 30
            19        do_make $host $user $passwd $subdir 30
            20
            21        send_user "$host finish\n"
            22        exit
            23    }
            24}
               打開遠程主機配置文件,讀取每一行直到文件尾,忽略注釋行,用正則提取IP、用戶名和密碼,創建子進程,按IP和當前時間命名log文件(由于前面調用log_user 0關閉了控制臺輸出,因此為了能記錄輸出到日志文件,一定要加-a選項),最后調用函數copy_file和do_make。
               
               完整腳本下載:autobuild.zip
            posted on 2016-09-28 11:04 春秋十二月 閱讀(3857) 評論(0)  編輯 收藏 引用 所屬分類: System
            久久久久国产一区二区三区| 一本久道久久综合狠狠躁AV| 久久精品9988| 国产午夜福利精品久久| 狠狠色丁香久久婷婷综合| 99国产欧美久久久精品蜜芽| 国产巨作麻豆欧美亚洲综合久久| 久久久精品久久久久影院| 国产91色综合久久免费| 久久笫一福利免费导航 | 亚洲国产精品无码久久久久久曰| 精品国产乱码久久久久久人妻| 97久久精品无码一区二区| 国产一区二区久久久| 国产精品午夜久久| 婷婷久久综合九色综合98| 亚洲va中文字幕无码久久 | 久久精品亚洲乱码伦伦中文| 狠狠色婷婷久久一区二区三区| 精品无码久久久久久久动漫| 乱亲女H秽乱长久久久| 久久精品极品盛宴观看| 久久久久亚洲AV无码专区桃色| 久久青草国产手机看片福利盒子| 亚洲日本va中文字幕久久| 香蕉久久夜色精品国产2020| 久久久精品国产亚洲成人满18免费网站| 久久精品无码一区二区无码| 亚洲国产精品18久久久久久| 波多野结衣AV无码久久一区| 久久夜色撩人精品国产小说| 久久综合精品国产一区二区三区 | 久久久久久久波多野结衣高潮| 久久久艹| 久久久久久国产a免费观看黄色大片 | 久久棈精品久久久久久噜噜| 亚洲va久久久噜噜噜久久天堂| 欧美va久久久噜噜噜久久| 久久婷婷成人综合色综合| 久久精品人人做人人爽电影蜜月 | 久久激情五月丁香伊人|