应用在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:三数之和【15】
LeetCode:三数之和[15] 题目描述 给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的 ...
- web端自动化——Python读取txt文件、csv文件、xml文件
1.读取txt文件 txt文件是我们经常操作的文件类型,Python提供了以下几种读取txt文件的方式. 1)read(): 读取整个文件. 2)readline(): 读取一行数据. 3)readl ...
- 开发规范——MYSQL数据库
数据库规范 这里主要针对mysql数据库,其他数据库也可以借鉴 表 1.统一使用表命名规范 表名规范:分层+项目名缩写+实体名(小写)[+下划线+实体名+rel] 例子 表名:bc_user 分层: ...
- dotnet core use Redis to publish and subscribe
安装Redis 同样我这边再次使用Docker, 方便快捷: # 拉取镜像 docker pull redis # 运行镜像 docker run -d -p 6379:6379 --name red ...
- Linux安装Python3流程
安装必要的依赖库文件 yum -y install zlib zlib-devel bzip2 bzip2-devel ncurses ncurses-devel readline readline- ...
- 《C++语言程序设计》初学者必备教材
很多刚开始学习C++语言的同学,都会遇到一个问题:很多教材都不适合零基础的初学者.它们有的枯燥乏味,让人难以消化吸收,有的层次结构混乱,很难理清楚知识点,有的更是难度太大,没有代码的过渡,就开始讲解算 ...
- 【LEETCODE】36、121题,Best Time to Buy and Sell Stock
package y2019.Algorithm.array; /** * @ProjectName: cutter-point * @Package: y2019.Algorithm.array * ...
- Scratch(四)舞台区详解
在Scratch里面,所有的表现结果都在“舞台区”呈现,前面我们学习的“石头剪刀布”游戏,也是在“舞台区”完成的. 舞台区是非常重要的区域,所以我们今天单独用一个章节来详细说说这个舞台. 既然是一个舞 ...
- jmeter中生成UUID作为唯一标识符
在测试过程中,我们有时候需要一个唯一不重复的值(比如order_id).我之前一直用的时间戳+计数器/随机函数拼接,但是有时候效果不太好,今天知道了UUID这玩意,可以来操作下.jmeter也提供了U ...
- AQS独占式同步队列入队与出队
入队 Node AQS同步队列和等待队列共用同一种节点结构Node,与同步队列相关的属性如下. prev 前驱结点 next 后继节点 thread 入队的线程 入队节点的状态 INITIAl 0 初 ...