因為公司的產品有linux 和windows兩套部署環境,領導安排我先來做windows的自動化部署。由於本人對windows 的dos命令基本沒啥概念,所以在最終完成之前,走了很多彎路,在這里記載下來,希望能夠對看到這篇文章的人,有所幫助。
好了,廢話少說,直接上步驟。
Background :
開發給過來的就是一個server.jar,雙擊server.jar,可以選擇安裝路徑,選擇licence,並最終安裝完成。安裝完成之后還需要做三個配置:
配置1):配置數據庫信息 [在Dos窗口打開安裝目錄下的DBconnection.bat,輸入相應數據庫信息,輸入完畢以后會自動測試是否鏈接成功]
配置2):升級數據庫 [如果數據庫和產品的version不一致,則需要執行dbupgrade.bat]
配置3):修改Run.bat中的某些參數
部署架構圖:[從Host 部署到 各個 slave中去]
我的想法是這樣的:
首先在Host 機器上手工執行server.jar並安裝到某個目錄,比如 C:\programs\baseDir\,然后把baseDir 復制到 各個slave機器【怎么復制過去讓我吃了不少苦頭】上去,當然復制之前會做好各種配置,最后通過host調用slave上的某個東東去執行已經復制過去的run.bat.【這里的 “某個東東”讓我破費周折,呵呵,這是后話,暫且按下不表】
本地配置這里就不詳細描述了,主要是用VBS調用Bat,如果bat需要交互的話,就用Wscript.SendKeys。
這里主要說一下我碰到的兩個難題。
難題一:把文件夾復制到Slave機器上去:
經過摸索,我發現dos有一個命令,Xcopy,是一個非常強大的拷貝命令,支持本地和遠程拷貝,當然拷貝的時候還包含子目錄和子文件夾,比如我現在想把 C:\programs\baseDir 這個文件夾拷貝到遠程機器上去,可以用如下命令:
1 xcopy c:\programs\baseDir \\RemoteIp\remotefolder\
但是這樣做,有一個前提,是 RemoteIp所對應的機器需要把 remotefolder設置為共享,並且允許可寫,如果每次都復制到這個目錄還好,如果我臨時想換一個目錄,那么又要新建一個目錄,並設置共享,這 “顯然不美” (最近在看《測試之美》,呵呵,只有美的東西才容易被別人喜歡,比如美女),所以我換了一種方式,直接xcopy 到Remote機器上的根目錄,比如如下所示:
1 xcopy c:\programs\baseDir \\RemoteIp\c$\dirA\dirB\
這樣只需要知道對方的IP,至少一個盤符(比如C盤,就用C$),那么就可以復制到任意文件夾下面,xcopy如果檢測到在相應盤符下面沒有文件夾,會自動創建,但是如果直接執行這個命令的話,很有可能會碰到如下提示:
1 Access Is Dennied
除了這個提示以外,沒有任何其它提示,在此表示微軟的bug report封裝的太厲害了,經過苦苦搜索,終於解決了這個問題,Xcopy如果直接拷貝到對方絕對路徑,需要先授權,在這里授權 用 net use 命令:(如果 不熟悉此命令,可以在Dos窗口 輸入 net use /? 來看說明)
1 Net use \\RemoteIp\Admin$ password /user:username
注意這里的Admin$,這個應該是windows的默認共享,選中computer--右鍵 manage--System Tools --Share Folders--Shares 可以看得到,
如果這里不加Admin$的話,可能會提示:
1 Invalid drive specification 2 0 File(s) copied
執行net use之后,dos窗口應該有提示:
1 The command completed successfully.
此時再執行xcopy應該就沒有問題了,如果不是successfully,而仍然是 Access Is Dennied,那么可能和 “簡單文件共享” 有關,試試下面這個神器吧:
MicrosoftFixit50053.msi
下載鏈接 : http://support.microsoft.com/kb/307874/zh-cn
把這個文件在相關機器上都執行一遍,此時在 net use,再 xcopy ,OK了
!!!!!收工!!!!!!!
難題二 :現在把所有的文件都拷貝到遠程機器上去了,那么怎么啟動呢?
策略1)因為啟動文件是一個Bat文件,我最先想到的是利用telnet命令,並暗自竊喜,原來一切都這么簡單。。,但是很快發現 telnet消耗的是本地資源,我啟動一個應用都至少消耗1.5G的內存,我要同時啟動那么多機器,用telnet的方式全部消耗本地資源,顯然不現實。
策略2)放棄telent,轉而把目光投向遠程服務,我在host機器上向slave機器發起一個命令,在slave機器上創建一個服務,用這個服務去調用對應的 bat文件,想法很好,但是很快被一個錯誤打擊了,沒找到解決方案,具體是什么錯誤忘記了。。。
策略3)再研究,發現 schtasks 這玩意是個好東西,可以利用host發送schtasks命令在slave機器上創建服務,然后還可以隨時啟動服務和停止服務,為了盡可能的不要讓任務自己運行,而是在收到我指令的時候才運行,我把這個任務設置成每12個月運行一次。。。
1 schtasks /create /S RemoteIp /u admin /p password /sc monthly /mo 12 /tn TaskName /tr C:\dirA\dirB\Slave1Run.bat /F
此時會顯示創建成功,然后去觸發這個任務
1 schtasks /Run /S RemoteIp /u username /p password /tn taskname
然后在遠程win7機器上也運行了,可以看到界面,然而,當Win7 向 Win Xp 發起請求的時候,Access is dennied 又出來了。。。搜遍中外網站 (國外網站請用goagent,你懂的),最后在微硬的社區發現這樣一段話:
I suspect you are running from/To Win7/Vista to XP
SchTasks.exe are not the same between these systems and it won't work. It took me a while to figure it out.
好吧,Schtasks 你好,Schtasks 再見。
策略4)繼續搜。。,最后搜到一個神器 psexec
下載地址:http://technet.microsoft.com/en-us/sysinternals/bb897553.aspx
Utilities like Telnet and remote control programs like Symantec's PC Anywhere let you execute programs on remote systems, but they can be a pain to set up and require that you install client software on the remote systems that you wish to access. PsExec is a light-weight telnet-replacement that lets you execute processes on other systems, complete with full interactivity for console applications, without having to manually install client software. PsExec's most powerful uses include launching interactive command-prompts on remote systems and remote-enabling tools like IpConfig that otherwise do not have the ability to show information about remote systems.
好吧,死馬當活馬醫,立即嘗試!,把psexec配置好以后,執行以下命令:
1 psexec \\RemoteIp -u username -p password -i -d c:\dirA\Run.bat
發現在有的機器上成功,有的機器上顯示Access is dennied。。。看來微硬對這個log很喜歡啊。。,此時再次搬出之前的神器MicrosoftFixit50053.msi
參看URL :
http://forum.sysinternals.com/topic15919.html
http://davidchuprogramming.blogspot.com/2009/12/psexecexe-access-denied.html
執行完以后,啟動成功!
!!!!!收工!!!!!!!
最后,附加幾個VBS方法,May be helpful or not。
獲取系統中正在運行的cmd.exe的個數:
1 '================================================================================ 2 'Function Name : CountNumberOfCMD 3 'Summary : 4 ' Count All cmd processes in system 5 '=================================================================================== 6 Function CountNumberOfCMD() 7 Dim objWMIService, processItems, processName 8 processName = "cmd.exe" 9 Set objWMIService = GetObject("winmgmts:\\.\root\cimv2") 10 Set processItems = objWMIService.ExecQuery("Select * from Win32_Process where Name='" & processName & "'") 11 CountNumberOfCMD = processItems.Count 12 End Function
獲取當前位置:
1 '========================================================================== 2 'Function Name: GetTestDataFileAbsolutePath 3 'Summary: Get The Config Excel's Absolute Path 4 '========================================================================== 5 Function GetTestDataFileAbsolutePath() 6 Dim ws 7 set ws=CreateObject("Scripting.FileSystemObject") 8 GetTestDataFileAbsolutePath = ws.GetFile(Wscript.ScriptFullName).ParentFolder.Path & "\Config\Config.xls" 9 'GetTestDataFileAbsolutePath = "C:\AD\Config\Config.xls" 10 Set ws = Nothing 11 End Function
打開一個excel
1 '=========================================================================== 2 'Function Name: openExcel 3 'Summary: Open Excel File 4 '=========================================================================== 5 Function openExcel() 6 Set xlsApp = CreateObject("Excel.Application") '創建Excel對象 7 xlsApp.Visible = False 'true 為顯示excel對象,false為不顯示 8 Set xlsWorkBook = xlsApp.Workbooks.Open (GetTestDataFileAbsolutePath()) '打開指定路徑的Excel表格 9 End Function
關閉excel
Function closeExcel() xlsWorkBook.Close xlsApp.Quit Set RowCount = Nothing Set xlsSheet = Nothing Set xlsWorkBook = Nothing '釋放內存 Set xlsApp = Nothing '釋放Excel對象 End Function
VBS 調用Dos命令
1 '=============================================================================== 2 'Name: NetUseToSlave 3 'Summary: Net use to slave to get the cotrol privilege 4 ' 5 '================================================================================ 6 Function NetUseToSlave(ObjSlave) 7 8 Dim oShell 9 Set oShell = CreateObject("WScript.Shell") 10 oShell.Run ("%comspec% /c " & "NET USE \\" & ObjSlave.SlaveIp &"\Admin$ /delete /yes"),1,True 11 WScript.Sleep(2000) 12 oShell.Run ("%comspec% /c " & "NET USE \\" & ObjSlave.SlaveIp & "\Admin$ " & Passowrd &" /user:" & Username),1,True 13 WScript.Sleep(1000) 14 Set oShell = Nothing 15 16 End Function
vbs判斷文件是否存在:
1 '====================================================================== 2 'Function Name:CheckFileExists 3 'Summary: Check file exists or not 4 'FolderPath: Absolute path, as D:\server\bin\db.log 5 '===================================================================== 6 Function CheckFileExists(FilePath) 7 Dim fso 8 set fso=createobject("scripting.filesystemobject") 9 if fso.FileExists(FilePath) then 10 CheckFileExists = True 11 else 12 CheckFileExists = False 13 end If 14 Set fso =Nothing 15 End Function
vbs判斷文件夾是否存在:
'====================================================================== 'Function Name:CheckFolderExists 'Summary: Check folder exists or not 'FolderPath: Absolute path, as c:\dir '===================================================================== Function CheckFolderExists(FolderPath) Dim fso set fso=createobject("scripting.filesystemobject") if fso.FolderExists(FolderPath) then CheckFolderExists = True else CheckFolderExists = False end If Set fso =Nothing End Function
vbs正則修改文件內容
Function ModifyLaunch(slave) Dim FileName,FS, FileStream,OutStream,FileContents,RFileContensts FileName = slave.CopyFromDir & "\bin\launch.bat" Set FS = CreateObject("Scripting.FileSystemObject") on error resume Next Set FileStream = FS.OpenTextFile(FileName) FileContents = FileStream.ReadAll 'Sub1 : replace Ip Dim regEx Set regEx = New RegExp regEx.Pattern = "1.7.7.\d+" RFileContensts = regEx.Replace(FileContents,"228.7.7." & Split(slave.SlaveIp,".")(3)) on error resume Next Set OutStream = FS.OpenTextFile(FileName, 2, True) OutStream.Write RFileContensts Set FS = Nothing Set FileStream = Nothing Set OutStream = Nothing End Function
Dim xlsApp,xlsWorkBook,xlsSheet Dim RowCount Dim excelpath : excelpath = "D:\CollineAutomation\trunk\Config\TestSuites.xls" Dim arr : arr = Array("2868","3600","3609","4669","4671","4672","4673","4996","5131","5132","6151","6202","6220","6221","6232","6271","6419","6594","6603","6623","6644","6660","6664","6698","6712","6714","6715","6716","6717","6718","6781","6886","6887","6895","7011","7128","7131","7132","7133","7135","7140","7155","7396","7397","7398","7399","7400","7408","7899","7908","7912","14502","14504","14509","14517","14584","14589","14802","14846","14847","14863","14865","20366","20578","20850","20900","20970","23466","23470","3602","4591","4753","4793","4909","4974","5160","6183","6289","6290","6341","6417","6418","6448","6543","6545","6546","6547","6548","6549","6604","6607","6608","6609","6624","6625","6662","6663","6691","6734","6882","6898","6940","6957","6958","6959","7043","7130","7139","7165","7338","7339","7342","7351","7401","7581","7582","7693","14498","14499","14501","14516","14810","14831","14833","14857","16413","16414","19532","20204","20527","20528","20530","23474","23477","23481","23487","23492","6120","6174","6175","6237","6305","6306","6326","6327","6343","6380","6551","6571","6572","6635","6897","6941","6942","7102","7107","7141","7164","7340","7343","7348","7402","7409","7654","7656","7658","7679","7898","7939","7941","14505","14513","14514","14515","14585","14586","14587","14588","14792","14793","14796","14797","14798","14799","14800","14845","14855","14856","14858","14860","14861","14894","14895","14896","16420","16421","20199","20533","20556","23459","23461","3611","4675","4792","4825","6236","6286","6588","6638","6701","6702","6729","6767","6864","7158","7160","7161","7346","7660","7662","7663","7680","7897","7977","14506","14511","14512","14790","14791","14795","14851","20538","20539","20856","23454","23462","23464","23489","23493","23573","6763","6764","6748","6766") Set xlsApp = CreateObject("Excel.Application") '創建Excel對象 xlsApp.Visible = False 'true 為顯示excel對象,false為不顯示 Set xlsWorkBook = xlsApp.Workbooks.Open (excelpath) '打開指定路徑的Excel表格 Set xlsSheet = xlsWorkBook.Sheets("TestCases") '選擇指定Sheet RowCount = xlsSheet.usedRange.Rows.Count '獲取sheet中有內容的Rowcount行數 Dim caseId For j=0 To UBound(arr) caseId = arr(j) For i = 2 To RowCount Dim TESTCASEID TESTCASEID = Trim(xlsSheet.cells(i,4)) If InStr(TESTCASEID, caseId) = 1 Then xlsSheet.cells(i,7) = "Expired" End If Next Next xlsWorkBook.Save xlsWorkBook.Close xlsApp.Quit Set RowCount = Nothing Set xlsSheet = Nothing Set xlsWorkBook = Nothing Set xlsApp = Nothing