Created
November 28, 2016 23:26
-
-
Save afscrome/e6c4f3c8e9ca89e9882b1b77fde1e2c0 to your computer and use it in GitHub Desktop.
Script for installing solr as a windows service
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#Requires -Version 3.0 | |
<# | |
.Description | |
Installs Apache Solr | |
.Example | |
.\ServiceInstall.ps1 | |
Installs Apache Solr as the 'solr' service running on port 8983. | |
.Example | |
.\ServiceInstall.ps1 -ServiceName 'MySearch' -DisplayName 'My Search' -Port 6789 | |
Installs Solr as the 'MySearch' service running on port 6789 | |
.Parameter ServiceName | |
The name to use when creating the windows service. Defaults to 'solr'. | |
Must be provided with DisplayName. | |
.Parameter DisplayName | |
The display name to use when creating the windows service. Defaults to 'Solr'. | |
Must be provided with ServiceName. | |
.Parameter Port | |
The port to run solr on. Defaults to 8983. | |
#> | |
param ( | |
[string]$ServiceName = 'solr', | |
[string]$DisplayName = 'Apache Solr', | |
[uint16]$Port = 8983 | |
) | |
#Prerequisites | |
$script:ErrorActionPreference = 'Stop' | |
if(-not ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { | |
Write-Error 'You must be running as an administrator to install Apache Solr' | |
} | |
if (Get-Service $ServiceName -ea SilentlyContinue) { | |
Write-Warning "Service '$ServiceName' already exists." -ErrorAction Continue | |
Write-Warning "Use ServiceUninstall.ps1 to uninstall this existing instance" | |
Write-Warning "If you want to run an additional instance, consider setting up new cores on the existing solr instance instead." | |
Write-Warning "Alternatively, re-run this script providing ServiceName and Port paramaters to install a new search instance." | |
return | |
} | |
#Helper function to validate an external command completed successfully | |
function Exec { | |
param( | |
[Parameter(Mandatory=$true)] | |
[scriptblock]$Command | |
) | |
Write-Debug "Running $command" | |
& $Command | |
if($LASTEXITCODE) { | |
Write-Error "Exit Code $LASTEXITCODE whilst running $Command" | |
} | |
} | |
$startAt = Get-Date | |
try { | |
$SolrRoot = Resolve-Path $PSScriptRoot\.. | |
$nssmExe = if([Environment]::Is64BitOperatingSystem) { "$PSScriptRoot\nssm-x64.exe" } else { "$PSScriptRoot\nssm-x86.exe" } | |
$solrCommand = Join-Path $SolrRoot bin\solr.cmd | |
$solrCommand = """$solrCommand"" start -port $Port -foreground -verbose -Dsolr.log.muteconsole" | |
$solrCommand = $solrCommand.Replace('"', '""') | |
<# | |
When the nssm service is stopped, it issues a Ctrl+C to solr.cmd. Unfortunantly batch files have a lovely feature that | |
provides a prompt to "Terminate batch job (Y/N)?". This blocks indefinitly as the service doesn't take any standard input. | |
To work around this, rather than starting solr.cmd directly, start it through cmd /C, and run solr.cmd, but redirect | |
standard input from nul. This causes the prompt to be bypassed, and allows solr.cmd to exit immediatly. Thus we can now | |
distinguish between solr gracefully shutting down, and solr hanging on shutdown. | |
#> | |
Write-Host "Installing Service" -ForegroundColor Cyan | |
Exec { &$nssmExe install "$ServiceName" cmd.exe "/C $solrCommand < nul" } | |
Write-Host "Updating Service MetaData" -ForegroundColor Cyan | |
Exec { &$nssmExe set $ServiceName DisplayName $DisplayName } | |
Exec { &$nssmExe set $ServiceName Description "Apache Solr (Port $Port)" } | |
Exec { &$nssmExe set $ServiceName AppDirectory $SolrRoot\server\tmp } # Workaround for https://issues.apache.org/jira/browse/SOLR-9760 | |
Exec { &$nssmExe set $ServiceName AppStopMethodConsole 120000 } | |
Exec { &$nssmExe set $ServiceName AppExit Default Exit } | |
$logDir = Join-Path $SolrRoot data\logs | |
Exec { &$nssmExe set $ServiceName AppStdoutCreationDisposition 2 } | |
Exec { &$nssmExe set $ServiceName AppStderrCreationDisposition 2 } | |
Exec { &$nssmExe set $ServiceName AppStdout $logDir\nssm.log } | |
Exec { &$nssmExe set $ServiceName AppStderr $logDir\nssm.log } | |
#Create needed directories | |
@('data\logs', 'server\tmp') |% { | |
$fullPath = Join-Path $SolrRoot $_ | |
if(-not(Test-Path $fullPath)) { | |
New-Item $fullPath -Type Directory | out-null | |
} | |
} | |
#Use service specific Virtual Service account to grant | |
$ServiceAccount = "NT SERVICE\$ServiceName" | |
Write-Host "Configuring service to run as '$ServiceAccount'" -ForegroundColor Cyan | |
Exec { sc.exe config $ServiceName obj= "$ServiceAccount" } | |
Write-Host "Granting file system permissions for '$ServiceAccount'" -ForegroundColor Cyan | |
Exec { icacls $SolrRoot /grant "${ServiceAccount}:(OI)(CI)RX" } | |
Exec { icacls $SolrRoot\data /grant "${ServiceAccount}:(OI)(CI)M" } | |
Exec { icacls $SolrRoot\server\tmp /grant "${ServiceAccount}:(OI)(CI)M" } | |
} | |
catch { | |
if(Get-Service $ServiceName -ea SilentlyContinue) { | |
Write-Warning "Installation failed - rolling back service installation" | |
&"$PSScriptRoot\ServiceUninstall.ps1" -ServiceName $ServiceName | |
} | |
throw | |
} | |
Write-Host "Starting $ServiceName" -ForegroundColor Cyan | |
try{ | |
Exec { &$nssmExe start $ServiceName } | |
Write-Host "Solr has been successfully installed to http://localhost:$Port/solr/" -ForegroundColor Green | |
} | |
catch { | |
$solrLog = Join-Path $SolrRoot data\logs\solr.log | |
$nssmLog = Join-Path $SolrRoot data\logs\nssm.log | |
$nssmLogLastModify = (Get-Item $nssmLog -ErrorAction SilentlyContinue).LastWriteTime | |
$solrLogLastModify = (Get-Item $solrLog -ErrorAction SilentlyContinue).LastWriteTime | |
if($solrLogLastModify -and $solrLogLastModify -gt $nssmLogLastModify -and $solrLogLastModify -ge $startAt) { | |
$solrLogOutput = Get-Content $solrLog -Tail 10 | |
if ($solrLogOutput) { | |
Write-Host 'Last 10 lines of $solrLog' -ForegroundColor Yellow | |
$solrLogOutput | |
} | |
Write-Error "$ServiceName was installed, but failed to launch. Review '$solrLog' for more details." | |
} | |
else { | |
$nssmEvents = Get-EventLog -LogName Application -Source nssm -After $startAt -EntryType Error | select TimeGenerated, EntryType, Message | |
if ($nssmEvents -and $nssmLogLastModify -ge $startAt) { | |
Write-Host "Nssm errors from windows event logs" -ForegroundColor Yellow | |
$nssmEvents | Format-List | |
} | |
else { | |
$nssmLogOutput = Get-Content $nssmLog -Tail 10 | |
if ($nssmLogOutput) | |
{ | |
Write-Host "Last 10 lines of $nssmLog" -ForegroundColor Yellow | |
$nssmLogOutput | |
} | |
} | |
Write-Error "$ServiceName was installed, but failed to launch. Review the windows event log and '$nssmLog' for more details." | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment