Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
A PowerShell script to help installing Solr as a service - See https://jermdavis.wordpress.com/2017/10/30/low-effort-solr-installs/ for details
Param(
$solrVersion = "6.6.2",
$installFolder = "c:\solr",
$solrPort = "8983",
$solrHost = "solr",
$solrSSL = $true,
$nssmVersion = "2.24",
$JREVersion = "1.8.0_151"
)
$JREPath = "C:\Program Files\Java\jre$JREVersion" ## Note that if you're running 32bit java, you will need to change this path
$solrName = "solr-$solrVersion"
$solrRoot = "$installFolder\$solrName"
$nssmRoot = "$installFolder\nssm-$nssmVersion"
$solrPackage = "https://archive.apache.org/dist/lucene/solr/$solrVersion/$solrName.zip"
$nssmPackage = "https://nssm.cc/release/nssm-$nssmVersion.zip"
$downloadFolder = "~\Downloads"
## Verify elevated
## https://superuser.com/questions/749243/detect-if-powershell-is-running-as-administrator
$elevated = [bool](([System.Security.Principal.WindowsIdentity]::GetCurrent()).groups -match "S-1-5-32-544")
if($elevated -eq $false)
{
throw "In order to install services, please run this script elevated."
}
function downloadAndUnzipIfRequired
{
Param(
[string]$toolName,
[string]$toolFolder,
[string]$toolZip,
[string]$toolSourceFile,
[string]$installRoot
)
if(!(Test-Path -Path $toolFolder))
{
if(!(Test-Path -Path $toolZip))
{
Write-Host "Downloading $toolName..."
Start-BitsTransfer -Source $toolSourceFile -Destination $toolZip
}
Write-Host "Extracting $toolName to $toolFolder..."
Expand-Archive $toolZip -DestinationPath $installRoot
}
}
# download & extract the solr archive to the right folder
$solrZip = "$downloadFolder\$solrName.zip"
downloadAndUnzipIfRequired "Solr" $solrRoot $solrZip $solrPackage $installFolder
# download & extract the nssm archive to the right folder
$nssmZip = "$downloadFolder\nssm-$nssmVersion.zip"
downloadAndUnzipIfRequired "NSSM" $nssmRoot $nssmZip $nssmPackage $installFolder
# Ensure Java environment variable
$jreVal = [Environment]::GetEnvironmentVariable("JAVA_HOME", [EnvironmentVariableTarget]::Machine)
if($jreVal -ne $JREPath)
{
Write-Host "Setting JAVA_HOME environment variable"
[Environment]::SetEnvironmentVariable("JAVA_HOME", $JREPath, [EnvironmentVariableTarget]::Machine)
}
# if we're using HTTP
if($solrSSL -eq $false)
{
# Update solr cfg to use right host name
if(!(Test-Path -Path "$solrRoot\bin\solr.in.cmd.old"))
{
Write-Host "Rewriting solr config"
$cfg = Get-Content "$solrRoot\bin\solr.in.cmd"
Rename-Item "$solrRoot\bin\solr.in.cmd" "$solrRoot\bin\solr.in.cmd.old"
$newCfg = $newCfg | % { $_ -replace "REM set SOLR_HOST=192.168.1.1", "set SOLR_HOST=$solrHost" }
$newCfg | Set-Content "$solrRoot\bin\solr.in.cmd"
}
}
# Ensure the solr host name is in your hosts file
if($solrHost -ne "localhost")
{
$hostFileName = "c:\\windows\system32\drivers\etc\hosts"
$hostFile = [System.Io.File]::ReadAllText($hostFileName)
if(!($hostFile -like "*$solrHost*"))
{
Write-Host "Updating host file"
"`r`n127.0.0.1`t$solrHost" | Add-Content $hostFileName
}
}
# if we're using HTTPS
if($solrSSL -eq $true)
{
# Generate SSL cert
$existingCert = Get-ChildItem Cert:\LocalMachine\Root | where FriendlyName -eq "$solrName"
if(!($existingCert))
{
Write-Host "Creating & trusting an new SSL Cert for $solrHost"
# Generate a cert
# https://docs.microsoft.com/en-us/powershell/module/pkiclient/new-selfsignedcertificate?view=win10-ps
$cert = New-SelfSignedCertificate -FriendlyName "$solrName" -DnsName "$solrHost" -CertStoreLocation "cert:\LocalMachine" -NotAfter (Get-Date).AddYears(10)
# Trust the cert
# https://stackoverflow.com/questions/8815145/how-to-trust-a-certificate-in-windows-powershell
$store = New-Object System.Security.Cryptography.X509Certificates.X509Store "Root","LocalMachine"
$store.Open("ReadWrite")
$store.Add($cert)
$store.Close()
# remove the untrusted copy of the cert
$cert | Remove-Item
}
# export the cert to pfx using solr's default password
if(!(Test-Path -Path "$solrRoot\server\etc\solr-ssl.keystore.pfx"))
{
Write-Host "Exporting cert for Solr to use"
$cert = Get-ChildItem Cert:\LocalMachine\Root | where FriendlyName -eq "$solrName"
$certStore = "$solrRoot\server\etc\solr-ssl.keystore.pfx"
$certPwd = ConvertTo-SecureString -String "secret" -Force -AsPlainText
$cert | Export-PfxCertificate -FilePath $certStore -Password $certpwd | Out-Null
}
# Update solr cfg to use keystore & right host name
if(!(Test-Path -Path "$solrRoot\bin\solr.in.cmd.old"))
{
Write-Host "Rewriting solr config"
$cfg = Get-Content "$solrRoot\bin\solr.in.cmd"
Rename-Item "$solrRoot\bin\solr.in.cmd" "$solrRoot\bin\solr.in.cmd.old"
$newCfg = $cfg | % { $_ -replace "REM set SOLR_SSL_KEY_STORE=etc/solr-ssl.keystore.jks", "set SOLR_SSL_KEY_STORE=$certStore" }
$newCfg = $newCfg | % { $_ -replace "REM set SOLR_SSL_KEY_STORE_PASSWORD=secret", "set SOLR_SSL_KEY_STORE_PASSWORD=secret" }
$newCfg = $newCfg | % { $_ -replace "REM set SOLR_SSL_TRUST_STORE=etc/solr-ssl.keystore.jks", "set SOLR_SSL_TRUST_STORE=$certStore" }
$newCfg = $newCfg | % { $_ -replace "REM set SOLR_SSL_TRUST_STORE_PASSWORD=secret", "set SOLR_SSL_TRUST_STORE_PASSWORD=secret" }
$newCfg = $newCfg | % { $_ -replace "REM set SOLR_HOST=192.168.1.1", "set SOLR_HOST=$solrHost" }
$newCfg | Set-Content "$solrRoot\bin\solr.in.cmd"
}
}
# install the service & runs
$svc = Get-Service "$solrName" -ErrorAction SilentlyContinue
if(!($svc))
{
Write-Host "Installing Solr service"
&"$installFolder\nssm-$nssmVersion\win64\nssm.exe" install "$solrName" "$solrRoot\bin\solr.cmd" "-f" "-p $solrPort"
$svc = Get-Service "$solrName" -ErrorAction SilentlyContinue
}
if($svc.Status -ne "Running")
{
Write-Host "Starting Solr service"
Start-Service "$solrName"
}
# finally prove it's all working
$protocol = "http"
if($solrSSL -eq $true)
{
$protocol = "https"
}
Invoke-Expression "start $($protocol)://$($solrHost):$solrPort/solr/#/"
@TakeitEasyAlan

This comment has been minimized.

Show comment Hide comment
@TakeitEasyAlan

TakeitEasyAlan Nov 3, 2017

Hi,

I used the script, but when it tries to start the service I get an error, and in the windows log I get the following:

Program c:\solr\solr-6.6.2\bin\solr.cmd for service solr-6.6.2 exited with return code 3221225781

I can start solr from a powershell window (i.e. bin\solr.cmd start)

Any ideas?

Hi,

I used the script, but when it tries to start the service I get an error, and in the windows log I get the following:

Program c:\solr\solr-6.6.2\bin\solr.cmd for service solr-6.6.2 exited with return code 3221225781

I can start solr from a powershell window (i.e. bin\solr.cmd start)

Any ideas?

@patelcp

This comment has been minimized.

Show comment Hide comment
@patelcp

patelcp Nov 3, 2017

@TakeitEasyAlan do you have the JAVA_HOME set under System Variable? I had the variable set for my user but not as a system variable so was able to run it via command line but not via NSSM.

patelcp commented Nov 3, 2017

@TakeitEasyAlan do you have the JAVA_HOME set under System Variable? I had the variable set for my user but not as a system variable so was able to run it via command line but not via NSSM.

@TakeitEasyAlan

This comment has been minimized.

Show comment Hide comment
@TakeitEasyAlan

TakeitEasyAlan Nov 6, 2017

Yes It was setup correctly? strange!

Yes It was setup correctly? strange!

@isaadansari

This comment has been minimized.

Show comment Hide comment
@isaadansari

isaadansari Jan 20, 2018

same thing happened with me. the Solr service is set to paused, I don't know why. and the powershell is unable to start the service.

isaadansari commented Jan 20, 2018

same thing happened with me. the Solr service is set to paused, I don't know why. and the powershell is unable to start the service.

@psx790

This comment has been minimized.

Show comment Hide comment
@psx790

psx790 Feb 2, 2018

I am seeing similar issues. It appears that nssm is creating the service with the executable path set to nssm.exe's path, instead of the path to the solr.cmd file. I even tried using the nssm GUI and it does the same thing.

psx790 commented Feb 2, 2018

I am seeing similar issues. It appears that nssm is creating the service with the executable path set to nssm.exe's path, instead of the path to the solr.cmd file. I even tried using the nssm GUI and it does the same thing.

@JamesSkemp

This comment has been minimized.

Show comment Hide comment
@JamesSkemp

JamesSkemp Feb 14, 2018

@psx790 if you're looking at the Services interface it seems like nssm is actually called and it manages the task to run. You can run .\nssm.exe edit solor-6.6.2 to see what it's actually doing. See https://stackoverflow.com/a/48661426/11912

@psx790 if you're looking at the Services interface it seems like nssm is actually called and it manages the task to run. You can run .\nssm.exe edit solor-6.6.2 to see what it's actually doing. See https://stackoverflow.com/a/48661426/11912

@JamesSkemp

This comment has been minimized.

Show comment Hide comment
@JamesSkemp

JamesSkemp Feb 14, 2018

This script won't work for Windows Server 2012 R2. Instead of using -FriendlyName to find an existing cert, switch these (there's a couple instances) to Subject -eq "CN=$solrHost" and then remove the -FriendlyName from New-SelfSignedCertificate.

This script won't work for Windows Server 2012 R2. Instead of using -FriendlyName to find an existing cert, switch these (there's a couple instances) to Subject -eq "CN=$solrHost" and then remove the -FriendlyName from New-SelfSignedCertificate.

@KillianW

This comment has been minimized.

Show comment Hide comment
@KillianW

KillianW Mar 1, 2018

Am I correct in saying your script will install NSSM below c:\solr?
If so, is there a particular reason for that or could it be installed elsewhere?

KillianW commented Mar 1, 2018

Am I correct in saying your script will install NSSM below c:\solr?
If so, is there a particular reason for that or could it be installed elsewhere?

@cassidydotdk

This comment has been minimized.

Show comment Hide comment
@cassidydotdk

cassidydotdk Mar 26, 2018

@TakeitEasyAlan I ran into the same issue. I manually changed how NSSM launches SOLR by modifying this line:

&"$installFolder\nssm-$nssmVersion\win64\nssm.exe" install "$solrName" "$solrRoot\bin\solr.cmd start" "-f" "-p $solrPort"

I basically added "start" after "solr.cmd". Then everything worked.

Further edit. I had to make the above change as I was originally running the 32 bit Java RTE. I then decided to revert my checkpoint and install the 64 bit RTE instead - and there, the script failed when I had "start" as part of the start command. Not exactly sure what the root cause is for this change in behaviour - but it might explain a few things.

cassidydotdk commented Mar 26, 2018

@TakeitEasyAlan I ran into the same issue. I manually changed how NSSM launches SOLR by modifying this line:

&"$installFolder\nssm-$nssmVersion\win64\nssm.exe" install "$solrName" "$solrRoot\bin\solr.cmd start" "-f" "-p $solrPort"

I basically added "start" after "solr.cmd". Then everything worked.

Further edit. I had to make the above change as I was originally running the 32 bit Java RTE. I then decided to revert my checkpoint and install the 64 bit RTE instead - and there, the script failed when I had "start" as part of the start command. Not exactly sure what the root cause is for this change in behaviour - but it might explain a few things.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment