At work we need to sometimes install a several tomcat instances on multiple machines. This was quite tedious to do manually so in order to speed things up, I wrote a powershell script which automates the installation.
So the only thing I would need to do is to download the specific version that is needed and then run the script like:
.\install-tomcat.ps1 .\apache-tomcat-8.5.43-windows-x64.zip c:\applications\
and it would install the X number of instances.
Below is a simplified script which installs one instance automatically.
Parameters#
Let’s create a new powershell file called install-tomcat.ps1 which takes two parameters, the zip-file (of tomcat) and the $destination. Save the directory where the script is for later use.
1
2
| param( $tomcatZip, $destination )
$currentDir = $PSScriptRoot
|
This is all good but lets add some parameter validation so that the file and destination has to exist
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
| param(
[Parameter(Mandatory=$True)]
[ValidateNotNullorEmpty()]
[ValidateScript({
if( -Not ($_ | Test-Path) ){
throw "File '$_' does not exist"
}
if(-Not ($_ | Test-Path -PathType Leaf) ){
throw "The tomcatZip argument must be a file. Folder paths are not allowed."
}
if($_ -notmatch "(\.zip)"){
throw "The file specified in the path argument must be of type zip"
}
return $true
})]
[System.IO.FileInfo]$tomcatZip
,
[Parameter(Mandatory=$True)]
[ValidateNotNullorEmpty()]
[ValidateScript({
if( -Not ($_ | Test-Path) ){
throw "File or folder '$_' does not exist"
}
return $true
})]
[System.IO.FileInfo]$Destination
)
$currentDir = $PSScriptRoot
|
Unzip tomcat-zip#
First we need to get the version number from the zip-filename to use later.
29
30
31
32
33
| $currentDir = $PSScriptRoot
# Get version number from tomcatZip
$tomcatZip.BaseName -match "apache-tomcat-(?<content>.*)-windows*"
$versionNumber = $matches['content']
|
Now we can unzip the tomcat-zip file to a temporary directory
35
36
37
38
39
| # Check if temporary directory exist and expand archive
$unpackedTomcatExists = Get-ChildItem -Directory -Filter apache-tomcat-*
if (!$unpackedTomcatExists) {
Expand-Archive "$($tomcatZip.FullName)" -DestinationPath "$currentDir\"
}
|
Copy directory to destination#
Now we can copy the tomcat directory to the destination with the corret name.
41
42
| # Copy to destination
Copy-Item -Path "$currentDir\$unpackedTomcat" -Recurse -Destination "$destination\Tomcat$versionNumber"
|
In case we dont want to use the default ports of 8080/8005/8009 we need to change the values in tomcats server.xml.
We can enter our desired values in a json-file in the same directory.
ports.json:
1
2
3
4
5
| {
"port": "8383",
"shutdownPort" : "8335",
"ajpPort" : "8339"
}
|
Now we need to read the json-file from powershell
43
| $ports = Get-Content "$PSScriptRoot\ports.json" -raw | ConvertFrom-Json
|
What we now need to do is to change the values in server.xml
45
46
47
48
49
50
| # Change ports in server.xml
(Get-Content "$destination\Tomcat$versionNumber\conf\server.xml")
.replace('8005', "$($ports.shutdownPort)")
.replace('8080', "$($ports.port)")
.replace('8009', "$($ports.ajpPort)") |
Set-Content "$destination\Tomcat$versionNumber\conf\server.xml"
|
Since I wanted to use the version number in the service name I had to rename tomcat8w.exe to the correct name also:
52
53
| # Rename tomcatXw.exe to correct name.
Rename-Item -Path "$destination\Tomcat$versionNumber\bin\tomcat8w.exe" -NewName "Tomcat$versionNumberw.exe"
|
Now the only thing left is to install the services. Now you could make this value a parameter but like the other two but lets make it a promtable choice.
55
56
57
| # Ask if to install service
$choices = '&Yes', '&No'
$installService = $Host.UI.PromptForChoice('', 'Do you want to install services?', $choices, 1)
|
Now the only thing left is to install the services. Now you could make this value a parameter but like the other two but lets make it a promtable choice. Then we install it as a service and at the same time change some of the default configuration for it as well.
59
60
61
62
63
64
65
66
67
68
| if ($installService -eq 0) {
#Installing Tomcat$versionNumber as a service"
Set-Location $destination\Tomcat$versionNumber\bin
cmd.exe /c "service.bat install Tomcat$($versionNumber)"
$logConfig = $($logbackFile.FullName)
# Change default configuration of service
cmd.exe /c "tomcat8.exe //US//Tomcat$($versionNumber) --Startup=auto --JvmMs=256 --JvmMx=1024"
Set-Location $currentDir
}
|
Complete script#
Here’s the complete script in it’s glory.
install-tomcat.ps1:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
| param(
[Parameter(Mandatory=$True)]
[ValidateScript({
if( -Not ($_ | Test-Path) ){
throw "File '$_' does not exist"
}
if(-Not ($_ | Test-Path -PathType Leaf) ){
throw "The tomcatZip argument must be a file. Folder paths are not allowed."
}
if($_ -notmatch "(\.zip)"){
throw "The file specified in the path argument must be of type zip"
}
return $true
})]
[System.IO.FileInfo]$tomcatZip
,
[Parameter(Mandatory=$True)]
[ValidateScript({
if( -Not ($_ | Test-Path) ){
throw "File or folder '$_' does not exist"
}
return $true
})]
[System.IO.FileInfo]$destination
)
$currentDir = $PSScriptRoot
# Get version number from tomcatZip
$tomcatZip.BaseName -match "apache-tomcat-(?<content>.*)-windows*"
$versionNumber = $matches['content']
Write-Output $versionNumber
# Check if temporary directory exist and expand archive
$unpackedTomcatExists = Get-ChildItem -Directory -Filter apache-tomcat-*
if (!$unpackedTomcatExists) {
Expand-Archive "$($tomcatZip.FullName)" -DestinationPath "$currentDir\"
}
# Copy to destination
Copy-Item -Path "$currentDir\$unpackedTomcat" -Recurse -Destination "$destination\Tomcat$versionNumber"
$ports = Get-Content "$PSScriptRoot\ports.json" -raw | ConvertFrom-Json
# Change ports in server.xml
(Get-Content "$destination\Tomcat$versionNumber\conf\server.xml")
.replace('8005', "$($ports.shutdownPort)")
.replace('8080', "$($ports.port)")
.replace('8009', "$($ports.ajpPort)") |
Set-Content "$destination\Tomcat$versionNumber\conf\server.xml"
# Rename tomcatXw.exe to correct name.
Rename-Item -Path "$destination\Tomcat$versionNumber\bin\tomcat8w.exe" -NewName "Tomcat$versionNumberw.exe"
# Ask if to install service
$choices = '&Yes', '&No'
$installService = $Host.UI.PromptForChoice('', 'Do you want to install services?', $choices, 1)
if ($installService -eq 0) {
#Installing Tomcat$versionNumber as a service"
Set-Location $destination\Tomcat$versionNumber\bin
cmd.exe /c "service.bat install Tomcat$($versionNumber)"
$logConfig = $($logbackFile.FullName)
# Change default configuration of service
cmd.exe /c "tomcat8.exe //US//Tomcat$($versionNumber) --Startup=auto --JvmMs=256 --JvmMx=1024"
Set-Location $currentDir
}
|
ports.json:
1
2
3
4
5
| {
"port": "8383",
"shutdownPort" : "8335",
"ajpPort" : "8339"
}
|
If you need to install several tomcat instances, then you would need to loop through the number of instances and copy unpacked the tomcat-folder to the destination (with different names of course) to save some time and not need to unpack it several times
Comments