All Articles

Installing and Uninstalling Solr with Powershell

Solr Installation with Powershell

The following script from Mark Cassidy is quick and easy to install Solr with Powershell.

Param(  
    $installFolder = "c:\solr",
    $solrPort = "8662",
    $solrHost = "solr",
    $solrSSL = $true,
    $solrVersion = "6.6.2",
    $downloadFolder = "$PSScriptRoot"
)
$solrName = "solr-$solrVersion"
$solrPackage = "https://archive.apache.org/dist/lucene/solr/$solrVersion/$solrName.zip"
$solrRoot = "$installFolder\$solrName"

$nssmFolder = "c:\nssm"
$nssmVersion = "2.24"
$nssmPackage = "https://nssm.cc/release/nssm-$nssmVersion.zip"
$nssmRoot = "$nssmFolder\nssm-$nssmVersion"

$JavaOJDKBuildVersion = "1.8.0.201-1"
$JavaOJDKBuildZip = "java-1.8.0-openjdk-$JavaOJDKBuildVersion.b09.ojdkbuild.windows.x86_64.zip"
$JavaOJDKBuildPackage = "https://github.com/ojdkbuild/ojdkbuild/releases/download/$JavaOJDKBuildVersion/$JavaOJDKBuildZip"
$JavaOJDKBuildInstallFolder = "$env:ProgramFiles\ojdkbuild"
$JREPath = "$JavaOJDKBuildInstallFolder\java-1.8.0-openjdk-$JavaOJDKBuildVersion.b09.ojdkbuild.windows.x86_64"

[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12

## 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,
        [bool]$isSolr = $false,
        [string]$solrFolder=""
    )

    if(!(Test-Path -Path $installRoot) -or ($isSolr -and !(Test-Path -Path $solrFolder)))
    {
        if(!(Test-Path -Path $toolZip))
        {
            Write-Host "Downloading $toolName..."
            <#
            Start-BitsTransfer -Source $toolSourceFile -Destination $toolZip
            # github releases has issues with BitsTransfer
            # Invoke-WebRequest is very slow in PowerShell 5.1 when showing progress bar
            #>

            $previousProgressPreference = $ProgressPreference
            $ProgressPreference = 'SilentlyContinue'
            Invoke-WebRequest -Uri $toolSourceFile -OutFile $toolZip 
            $ProgressPreference = $previousProgressPreference
        }

        if(!(Test-Path -Path $toolZip))
        {
            Write-Error "Unable to find $toolZip or download $toolSourceFile" -ErrorAction Stop
        }

        Write-Host "Extracting $toolName to $toolFolder..."
        Expand-Archive $toolZip -DestinationPath $installRoot
    }
}
if($env:JAVA_HOME -eq $null) {
    # download & extract the java archive to the right folder
    $javaZip = "$downloadFolder\$JavaOJDKBuildZip"
    downloadAndUnzipIfRequired "Java" $JavaOJDKBuildInstallFolder $javaZip $JavaOJDKBuildPackage $JavaOJDKBuildInstallFolder -ErrorAction Stop

    # Ensure Java environment variables
    Write-Host "Setting JAVA_HOME environment variable"
    [Environment]::SetEnvironmentVariable("JAVA_HOME", $JREPath, [EnvironmentVariableTarget]::Machine)
	$env:JAVA_HOME = $JREPath

    $oldPath = [Environment]::GetEnvironmentVariable("PATH", [EnvironmentVariableTarget]::Machine)
    if(!$oldPath.Contains("$JREPath\bin")) {
        $newPath = "$JREPath\bin;$oldPath"
        Write-Host "Updating PATH: $newPath"
        [Environment]::SetEnvironmentVariable("PATH", $newPath, [EnvironmentVariableTarget]::Machine)
		$env:Path = $newPath
    }

    Write-Host "Verifying install ..."
    Write-Host "java -version"
    # Redirecting Stderr to Stdout and converting to string works around NativeCommandError.
    # See https://stackoverflow.com/a/20950421 
    java.exe -version 2>&1 | %{ "$_" }
    Write-Host "javac -version"
    javac.exe -version 2>&1 | %{ "$_" }
}
# download & extract the solr archive to the right folder
$solrZip = "$downloadFolder\$solrName.zip"
downloadAndUnzipIfRequired "Solr" $solrRoot $solrZip $solrPackage $installFolder $true $solrRoot -ErrorAction Stop

# download & extract the nssm archive to the right folder
$nssmZip = "$downloadFolder\nssm-$nssmVersion.zip"
downloadAndUnzipIfRequired "NSSM" $nssmRoot $nssmZip $nssmPackage $nssmFolder -ErrorAction Stop

# 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
    $certName = "$solrName-$solrHost"
    $existingCert = Get-ChildItem Cert:\LocalMachine\Root | where FriendlyName -eq "$certName"
    if($existingCert)
    {
        Write-Host "Removing the existing certificate to create a new one"
        $existingCert | Remove-Item
    }
    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 "$certName" -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 "$certName"
    
        $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"
    &"$nssmRoot\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/#/"

Steps to be followed:

  1. Copy the contents from the above script and paste it into a file naming “Install-Solr.ps1”.
  2. Change the parameters in the top of the script:

    • installFolder : The path to the directory where solr needs to be installed. (By default, it is “C:\Solr”, you may change if required)
    • solrPort : The port which the solr service will be using. Make sure to give a port that is unused.
    • solrSSL : $true by default. Installs, and configures the solr instance with https. Change to $false if https is not required.
    • solrVersion : The version of solr to be installed.
    • downloadFolder : Need not change, but can be changed if you want the files being downloaded by the script to be done in some other path.
  3. Run Powershell as Administrator.
  4. Execute the below commands.
cd <path_to_the_folder_where_script_is_copied>
.\Install-Solr.ps1
  1. The script will download the jre, nssm and solr installation files and install them. Also, it will configure https if solrSSL is marked as true.
  2. Possible errors that you may face and solutions:

    • Start Solr error: Delete the downloaded files, use the uninstall script to uninstall the solr instance, and rerun the script. This may happen if the files downloaded are incomplete.
    • Start Solr error: Another case is when you already have a JRE version installed. Go to your System Environment Variables and remove the existing JAVA_HOME variable. Uninstall the solr instance, restart your machine and rerun the installation script.

Uninstall Solr with Powershell

The below script from Diego Saavedra San Juan is very useful for uninstalling Solr instances:

Param(
    $solrLocation="C:\Solr\solr-6.6.2",
    $solrServiceName="solr-6.6.2"
)
# Uninstall Service
Write-Host "Checking if Solr service is installed"
$isSolrServiceInstalled = Get-Service | Where-Object {$_.Name -like "*$solrServiceName*"}
if ($null -ne $isSolrServiceInstalled) 
{
    Write-Host "Removing Solr service $solrServiceName" -ForegroundColor Cyan

    # Stop the service 
    sc.exe stop $solrServiceName

    sc.exe delete $solrServiceName 
    Start-Sleep 2
    $isSolrServiceInstalled = sc.exe query $solrServiceName
    if ( $isSolrServiceInstalled[0].Contains("1060") )
    {
        Write-Host "Removal of Solr service completed sucessfully" -ForegroundColor Green
    }
    else 
    { 
        Write-Host "Something went wrong removing Solr service named $solrServiceName" -ForegroundColor Red
        exit 1
    }

}
else 
{ 
    Write-Host "Solr service already removed, good" -ForegroundColor Green
}


# Remove folder
if ( Test-Path $solrLocation )
{
    Remove-Item -Recurse $solrLocation
    if ( -Not ( Test-Path $solrLocation ))
    {
        Write-Host "Correctly removed Solr directory at $solrLocation" -ForegroundColor Green
    }
    else 
    { 
        Write-Host "Something went wrong trying to remove the solr directory" -ForegroundColor Red
        exit 1
    }
}
else { Write-Host "Solr location $solrLocation already removed, good" -ForegroundColor Green }

Write-Host "Completed uninstallation of Solr" -ForegroundColor Green

Steps to be followed

  1. Copy the contents from the above script and paste it into a file naming “Uninstall-Solr.ps1”.
  2. Change the parameters in the top of the script:

    • solrLocation : The directory in which solr is installed.
    • solrServiceName : The name of the solr service.
  3. Run Powershell as Administrator.
  4. Run the below commands.
cd <path_to_folder_where_file_is_saved>
.\Uninstall-Solr.ps1
  1. The script will uninstall the solr instance and delete the files in the solr directory.

I hope these scripts will be helpful for you.

Please feel free to ask questions/drop suggestions in the comments.

Happy Sitecoring.