应用在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 这个文件夹拷贝到远程机器上去,可以用如下命令:
xcopy c:\programs\baseDir \\RemoteIp\remotefolder\
但是这样做,有一个前提,是 RemoteIp所对应的机器需要把 remotefolder设置为共享,并且允许可写,如果每次都复制到这个目录还好,如果我临时想换一个目录,那么又要新建一个目录,并设置共享,这 “显然不美” (最近在看《测试之美》,呵呵,只有美的东西才容易被别人喜欢,比如美女),所以我换了一种方式,直接xcopy 到Remote机器上的根目录,比如如下所示:
xcopy c:\programs\baseDir \\RemoteIp\c$\dirA\dirB\
这样只需要知道对方的IP,至少一个盘符(比如C盘,就用C$),那么就可以复制到任意文件夹下面,xcopy如果检测到在相应盘符下面没有文件夹,会自动创建,但是如果直接执行这个命令的话,很有可能会碰到如下提示:
Access Is Dennied
除了这个提示以外,没有任何其它提示,在此表示微软的bug report封装的太厉害了,经过苦苦搜索,终于解决了这个问题,Xcopy如果直接拷贝到对方绝对路径,需要先授权,在这里授权 用 net use 命令:(如果 不熟悉此命令,可以在Dos窗口 输入 net use /? 来看说明)
Net use \\RemoteIp\Admin$ password /user:username
注意这里的Admin$,这个应该是windows的默认共享,选中computer--右键 manage--System Tools --Share Folders--Shares 可以看得到,
如果这里不加Admin$的话,可能会提示:
Invalid drive specification
File(s) copied
执行net use之后,dos窗口应该有提示:
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个月运行一次。。。
schtasks /create /S RemoteIp /u admin /p password /sc monthly /mo 12 /tn TaskName /tr C:\dirA\dirB\Slave1Run.bat /F
此时会显示创建成功,然后去触发这个任务
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配置好以后,执行以下命令:
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的个数:
'================================================================================
'Function Name : CountNumberOfCMD
'Summary :
' Count All cmd processes in system
'===================================================================================
Function CountNumberOfCMD()
Dim objWMIService, processItems, processName
processName = "cmd.exe"
Set objWMIService = GetObject("winmgmts:\\.\root\cimv2")
Set processItems = objWMIService.ExecQuery("Select * from Win32_Process where Name='" & processName & "'")
CountNumberOfCMD = processItems.Count
End Function
获取当前位置:
'==========================================================================
'Function Name: GetTestDataFileAbsolutePath
'Summary: Get The Config Excel's Absolute Path
'==========================================================================
Function GetTestDataFileAbsolutePath()
Dim ws
set ws=CreateObject("Scripting.FileSystemObject")
GetTestDataFileAbsolutePath = ws.GetFile(Wscript.ScriptFullName).ParentFolder.Path & "\Config\Config.xls"
'GetTestDataFileAbsolutePath = "C:\AD\Config\Config.xls"
Set ws = Nothing
End Function
打开一个excel
'===========================================================================
'Function Name: openExcel
'Summary: Open Excel File
'===========================================================================
Function openExcel()
Set xlsApp = CreateObject("Excel.Application") '创建Excel对象
xlsApp.Visible = False 'true 为显示excel对象,false为不显示
Set xlsWorkBook = xlsApp.Workbooks.Open (GetTestDataFileAbsolutePath()) '打开指定路径的Excel表格
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命令
'===============================================================================
'Name: NetUseToSlave
'Summary: Net use to slave to get the cotrol privilege
'
'================================================================================
Function NetUseToSlave(ObjSlave) Dim oShell
Set oShell = CreateObject("WScript.Shell")
oShell.Run ("%comspec% /c " & "NET USE \\" & ObjSlave.SlaveIp &"\Admin$ /delete /yes"),,True
WScript.Sleep()
oShell.Run ("%comspec% /c " & "NET USE \\" & ObjSlave.SlaveIp & "\Admin$ " & Passowrd &" /user:" & Username),,True
WScript.Sleep()
Set oShell = Nothing End Function
vbs判断文件是否存在:
'======================================================================
'Function Name:CheckFileExists
'Summary: Check file exists or not
'FolderPath: Absolute path, as D:\server\bin\db.log
'=====================================================================
Function CheckFileExists(FilePath)
Dim fso
set fso=createobject("scripting.filesystemobject")
if fso.FileExists(FilePath) then
CheckFileExists = True
else
CheckFileExists = False
end If
Set fso =Nothing
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,".")())
on error resume Next
Set OutStream = FS.OpenTextFile(FileName, , 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
应用在Windows系统中的自动化部署实践的更多相关文章
- UEFI+GPT模式下的Windows系统中分区结构和默认分区大小及硬盘整数分区研究
内容摘要:本文主要讨论和分析在UEFI+GPT模式下的Windows系统(主要是最新的Win10X64)中默认的分区结构和默认的分区大小,硬盘整数分区.4K对齐.起始扇区.恢复分区.ESP分区.MSR ...
- jenkins+windows+springboot+.net项目自动化部署图文教程
之前一直在linux中使用jenkins部署程序,正好现在的项目包括了winfrom程序,所以需要部署到windows系统中 jenkins官网:https://jenkins.io/ 下载之后运行j ...
- WSL2:在Windows系统中开发Linux程序的又一神器
作 者:道哥,10+年的嵌入式开发老兵. 公众号:[IOT物联网小镇],专注于:C/C++.Linux操作系统.应用程序设计.物联网.单片机和嵌入式开发等领域. 公众号回复[书籍],获取 Linux. ...
- 关于Linux系统和Windows系统中文件夹的命名规范
Windows系统中. 1.在创建文件夹的时候不能以"."开头(但是文件以多个点开头并且还有其他合法字符的话就是合法的) 但是在windows系统中确实见过以一个点".& ...
- mysql绿色版在windows系统中的启动
mysql绿色版在windows系统中的启动 1.下载mysql免安装版 例如:mysql-5.7.11-winx64 2.修改配置文件,my-default.ini名称改为:my.ini,文件里面的 ...
- 在Windows系统中安装集成的PHP开发环境
原文:在Windows系统中安装集成的PHP开发环境 刚想学php的,又不会配置复杂php的环境,可以使用集成的,目前网上提供常用的PHP集成环境主要有AppServ.phpStudy.WAMP和XA ...
- 获取Windows系统中的所有可用和在用串口
目的:获取Windows系统中的所有可用和在用串口 方法:注册表查询法 优点:简单.实用.快速.无遗漏,无多余结果. 说明:另外还有8种方法可以枚举串口,但都不如此法. 代码和详细注释如下: //-- ...
- Windows系统中设置Python程序定时运行方法
Windows系统中设置Python程序定时运行方法 一.环境 win7 + Python3.6 二.步骤 1,在Windows开始菜单中搜索“计划任务”,并且点击打开“计划任务”: 2.点击“创建基 ...
- 【其他】【服务器】【4】删除Windows系统中不想要的服务
步骤: 1,开始菜单栏查找“服务”,打开后找到想要删除的服务 2,右键单击想要删除的服务,选择“属性”-“常规”-“服务名称”,记下服务名称(AA) 3,开始菜单栏输入“cmd”打开命令行窗口,输入s ...
随机推荐
- 【Leetcode_easy】893. Groups of Special-Equivalent Strings
problem 893. Groups of Special-Equivalent Strings 题意: 感觉参考代码也是有点问题的... 参考 1. Leetcode_easy_893. Grou ...
- js中的eval方法
eval(string) eval函数接收一个参数string,如果string不是字符串,则直接返回string.否则执行string语句.如果string语句执行结果是一个值,则返回此值,否则返回 ...
- WPF TextBlock 文本换行的两种方式
第一种: <TextBlock> This is line 1.<LineBreak/> This is line 2. </TextBlock> 第二种 < ...
- C++ 枚举定义
我们在平常的编程中,时常需要为一些属性定义一组可以选择的值,比如文件打开的状态可能会有三种:输入 输出和追加 我们一般情况下记录这些状态是让每一个状态和一个常数相对应 比如 ; ; ; 这个方法虽 ...
- spring添加事物
<context:component-scan base-package="com.zlkj" > <context:include-filter type=&q ...
- 【剑指offer】面试题 25. 合并两个排序的链表
面试题 25. 合并两个排序的链表 NowCoder 题目描述 输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则. Java 实现 ListNode Clas ...
- 035 Android Volley框架进行网络请求
1.volley入门介绍 开发Android应用的时候不可避免地都需要用到网络技术,而多数情况下应用程序都会使用HTTP协议来发送和接收网络数据.Android系统中主要提供了两种方式来进行HTTP通 ...
- QT release版QAudioDeviceInfo获取不到音频设备,而debug版可以获取到
新添加了两个模块:QCharts和Multimedia 但自己没有重新打包更新里面的库文件什么的... 坑爹... 害我找了这么久... 解决办法: 方法一: 将Qt安装目录下的plugins文件夹中 ...
- 通过tushare获取股票价格
# Author llll # coding=utf-8 # ---描述# 完成股票 价格查询和展示# 不直接根据网页进行爬虫获取股票价格,而是通过已有组件查询股票价格,并保存到csv文件或者exce ...
- PAT(B) 1039 到底买不买(Java)字符串
题目链接:1039 到底买不买 (20 point(s)) 题目描述 小红想买些珠子做一串自己喜欢的珠串.卖珠子的摊主有很多串五颜六色的珠串,但是不肯把任何一串拆散了卖.于是小红要你帮忙判断一下,某串 ...