应用在Windows系统中的自动化部署实践

  因为公司的产品有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

 

  

posted on 2014-03-21 15:15  woxiangbo  阅读(6078)  评论(2编辑  收藏  举报