Skip to content

Automating AEM Installation using Powershell

DISCLAIMER

If you require any more information or have any questions about our site’s disclaimer, please feel free to contact us by email at [email protected]

All the information on this website – https://skydevops.co.in – is published in good faith and for general information purpose only. SKYDEVOPS does not make any warranties about the completeness, reliability and accuracy of this information. Any action you take upon the information you find on this website (skydevops), is strictly at your own risk.
SKYDEVOPS will not be liable for any losses and/or damages in connection with the use of our website.

From our website, you can visit other websites by following hyperlinks to such external sites. While we strive to provide only quality links to useful and ethical websites, we have no control over the content and nature of these sites. These links to other websites do not imply a recommendation for all the content found on these sites. Site owners and content may change without notice and may occur before we have the opportunity to remove a link which may have gone ‘bad’.

Please be also aware that when you leave our website, other sites may have different privacy policies and terms which are beyond our control. Please be sure to check the Privacy Policies of these sites as well as their “Terms of Service” before engaging in any business or uploading any information.

CONSENT

By using our website, you hereby consent to our disclaimer and agree to its terms.

UPDATE

Should we update, amend or make any changes to this document, those changes will be prominently posted here.

-== & ==-

DESCRIPTION:

Following is a powershell script to automate the installation of AEM Author/Publish environments along with NAS storage and installation of necessary packages through a single script and deploy AEM as windows service with LogOn details.

The script is run locally on a VM where AEM environment is to be created. The script is broken into several sections, which are explained in detail.

SCRIPT:

Following are the parameters used

$ErrorActionPreference = "Stop"
$WarningPreference = "SilentlyContinue"
$AEMINST = Read-Host "Choose Author/Publish Instance to Setup [Author/Publish]"
$AEMPORT = Read-Host "Enter the CQ Port [4502/4503]"
$SRCPATH = "C:UsersSKYDEVOPSAEMzinstaller"
$BASEPATH = "C:UsersSKYDEVOPSAEMinstances$AEMINST"
$SERVICEPATH = "$BASEPATHcrx-quickstartopthelpers"
$JARFILE = "$SRCPATHaem-$AEMINST-p$AEMPORT.jar"
$LicensePath = "$SRCPATHlicense.properties"
$AEMUNPACK = "java -jar $JARFILE -unpack"
$ServiceName = "AEMPRD"
$USERNAME = "SKYDEVOPS"
$HOSTNAME = "192.168.2.8"
$CQ_PORT = "4503"
$CQ_USER = "admin"
$CQ_PASS = "admin"
$CURLEXE = 'C:toolscurl761bincurl.exe'
$GCURL = "http://${HOSTNAME}:${AEMPORT}/crx/packmgr/service.jsp"
$DOCUNSTORECFG = "org.apache.jackrabbit.oak.plugins.document.DocumentNodeStoreService.config"
$FILEDSTORECFG = "org.apache.jackrabbit.oak.plugins.blob.datastore.FiledataStore.config"
$PKGPATH01 = "$SRCPATHaemgit.ui.apps-1.0-SNAPSHOT.zip"
$PKGPATH02 = "$SRCPATHaemgit.ui.content-1.0-SNAPSHOT.zip"
$repository = "$BASEPATHcrx-quickstartrepository"

Description of each and every parameter is as following

.PARAMETER AEMINST
Author or Publish Environment
.PARAMETER AEMPORT
Author/Publish Port [4502/4503]
.PARAMETER SRCPATH
Common location for installation files. Example: AEM jar file, packages etc.
.PARAMETER BASEPATH
AEM installation directory
.PARAMETER SERVICEPATH
AEM instsrv.bat file location
.PARAMETER JARFILE
AEM jar file [aem-author-p4502.jar]
.PARAMETER LicensePath
license.properties file location
.PARAMETER AEMUNPACK
command to unpack AEM
.PARAMETER ServiceName
AEM service name
.PARAMETER USERNAME
username for AEM service LogOn
.PARAMETER MPass
password for serive LogOn
.PARAMETER HOSTNAME
Host on which AEM is installed
.PARAMETER CQ_PORT
AEM port
.PARAMETER CQ_USER
AEM login username
.PARAMETER CQ_PASS
AEM login password
.PARAMETER CURLEXE
cURL executable location
.PARAMETER GCURL
CRXDE url
.PARAMETER DOCUNSTORECFG
Document Node Store configuration
.PARAMETER FILEDSTORECFG
File Data Store configuration
.PARAMETER PKGPATH##
AEM package location and name
.PARAMETER repository
Location of Datastore repository

.NOTES
Author: Shashi Yebbare
Organization: Skydevops Pvt. Ltd.
Version: 3.5.2

Logic to check if AEM base directory exists, if not create it, then copy the necessary jar and license file and unpack AEM Author/Publish. If AEM Author/Publish directory exists then check for crx-quickstart folder and if its present then terminate the installation

if (!(Test-Path -Path $BASEPATH)) {
    Write-Output "$AEMINST Installation Directory Not Found"
    Write-Output "Creating Folder at $BASEPATH"
    New-Item -ItemType directory -Path $BASEPATH
    Copy-Item -Path $LicensePath -Destination $BASEPATH
    Set-Location -Path $BASEPATH
    Write-Output ""
    Write-Output "Unpacking $AEMINST"
    Invoke-Expression -Command:"cmd.exe /c $AEMUNPACK"

    if ($AEMINST -eq "Author") {
        Write-Output "Creating INSTALL Folder"
        New-Item -ItemType directory -Path "$BASEPATHcrx-quickstartinstall"
        Write-Output ""
        Write-Output "Copying Configurations to Install Directory"
        Copy-Item -Path "$SRCPATH$DOCUNSTORECFG" -Destination "$BASEPATHcrx-quickstartinstall"
        Copy-Item -Path "$SRCPATH$FILEDSTORECFG" -Destination "$BASEPATHcrx-quickstartinstall"
    }
    Set-Location -Path "C:UsersSKYDEVOPSDocumentsscripts"
}else {

    Write-Output "$BASEPATH Exists"
    Write-Output "Checking crx-quickstart Directory"
    if (!(Test-Path -Path $BASEPATHcrx-quickstart)) {
        Write-Output "crx-quickstart Not Found, Unpacking $AEMINST"
        Set-Location -Path $BASEPATH
        Write-Output "Unpacking $AEMINST"

        Invoke-Expression -Command:"cmd.exe /c $AEMUNPACK"
        if ($AEMINST -eq "Author") {
            Write-Output "Creating INSTALL Folder"
            New-Item -ItemType directory -Path "$BASEPATHcrx-quickstartinstall"
            Write-Output ""
            Write-Output "Copying Configurations to Install Directory"
            Copy-Item -Path "$SRCPATH$DOCUNSTORECFG" -Destination "$BASEPATHcrx-quickstartinstall"
            Copy-Item -Path "$SRCPATH$FILEDSTORECFG" -Destination "$BASEPATHcrx-quickstartinstall"
        }
    }else {

        Write-Output "crx-quickstart Found, Terminating Installation."
        Set-Location -Path "C:UsersSKYDEVOPSDocumentsscripts"
        Exit
    }
}

Creating AEM service, adding LogOn details and starting AEM service

$AEMSERVICEPATH = "$BASEPATHcrx-quickstartopthelpersinstsrv.bat"
Rename-Item -Path "$AEMSERVICEPATH" -NewName  "instsrv.bat.bak"
Copy-Item -Path "${SRCPATH}instsrv-${AEMINST}.bat" -Destination "${SERVICEPATH}instsrv.bat"
$AEMSERVICEPATH = "$BASEPATHcrx-quickstartopthelpersinstsrv.bat"
$AEMCommand = "$AEMSERVICEPATH $ServiceName"
$MPass="shashi"
Write-Output "Creating $ServiceName Service"
Invoke-Expression -Command:"cmd.exe /c $AEMCommand"
$LogOnD = Get-WmiObject -Class Win32_Service -Filter "Name='$ServiceName'"
Write-Output "Adding LogOn Details"
$LogOnD.Change($null,$null,$null,$null,$null,$null,".$USERNAME","$MPass",$null,$null,$null)
Start-Sleep -seconds 5
$arrservice = (Get-Service $ServiceName)
Write-Output "Starting $ServiceName Service"
Start-Service -Name $arrservice.Name
$arrservice.WaitForStatus("Running")
Write-Output "$ServiceName Successfully Started."

Checking if CQ Package Manager is up and running, once ifs UP, install necessary packages

$count = 0
$success = $null

if ($AEMINST -eq "Author") {
    Write-Output "Checking if CQ PackageMgr is UP"
    do{
            $HTCODE = cmd.exe /c curl -Is http://${CQ_USER}:${CQ_PASS}@${HOSTNAME}:${AEMPORT}/crx/packmgr/index.jsp | findstr "HTTP"
            $RESCODE = $HTCODE | %{ $_.Split(' ')[1]; }
            if ($RESCODE -eq 200) {
                Write-Output ""
                Write-Output "CQ PackageMgr Started"
                $success = $true
            }else {
                Write-Host -NoNewLine "."
                Start-sleep -Seconds 10
            }
            $count++
    }until($count -eq 180 -or $RESCODE -eq 200)
    if(-not($success)){
        Write-Output "Timed Out or CQ $AEMINST Dint start Properly"
        Write-Output "Package Installation Aborted."
        Exit
    }
}elseif ($AEMINST -eq "Publish") {
        Write-Output "Checking if CQ PackageMgr is UP"
    do{
            $HTCODE = cmd.exe /c curl -Is http://${CQ_USER}:${CQ_PASS}@${HOSTNAME}:${AEMPORT}/crx/packmgr/index.jsp | findstr "HTTP"
            $RESCODE = $HTCODE | %{ $_.Split(' ')[1]; }
            if ($RESCODE -eq 200) {
                Write-Output ""
                Write-Output "CQ PackageMgr Started"
                $success = $true
            }else {
                Write-Host -NoNewLine "."
                Start-sleep -Seconds 10
            }
            $count++
    }until($count -eq 50 -or $RESCODE -eq 200)
    if(-not($success)){
        Write-Output "Timed Out or CQ $AEMINST Dint start Properly"
        Write-Output "Package Installation Aborted."
        Exit
    }
}

Installing AEM packages using cURL

Write-Output "Installing APPS Package"
cmd.exe /c $CURLEXE -u "${CQ_USER}:${CQ_PASS}" -F file=@"$PKGPATH01" -F name="aemgit.ui.apps" -F force=true -F install=false "$GCURL" | Out-Null
Write-Output "Package Installation Complete"

Checking if AEM is completely installed and running

$COUNTNAS = 0
$NASSuccess = $null

if ($AEMINST -eq "Author") {
    Write-Output "Checking if CQ Author is UP"
    do{
        $CPCODE = cmd.exe /c curl -Is "http://${HOSTNAME}:${AEMPORT}/libs/granite/core/content/login.html" | findstr "HTTP"
        $RESCPCODE = $CPCODE | %{ $_.Split(' ')[1]; }
        if ($RESCPCODE -eq 200) {
            Write-Output ""
            Write-Output "CQ $AEMINST Started"
            $NASSuccess = $true
        }else {
            Write-Host -NoNewLine "."
            Start-sleep -Seconds 10
        }
        $COUNTNAS++
    }until($COUNTNAS -eq 180 -or $RESCPCODE -eq 200)
    if(-not($NASSuccess)){
        Write-Output "Timed Out or CQ $AEMINST Dint start Properly"
        Write-Output "Package Installation Aborted."
        Exit
    }
}elseif ($AEMINST -eq "Publish") {
        Write-Output "Checking if CQ Publish is UP"
    do{
        $CPCODE = cmd.exe /c curl -Is "http://${HOSTNAME}:${AEMPORT}/libs/granite/core/content/login.html" | findstr "HTTP"
        $RESCPCODE = $CPCODE | %{ $_.Split(' ')[1]; }
        if ($RESCPCODE -eq 200) {
            Write-Output ""
            Write-Output "CQ $AEMINST Started"
            $NASSuccess = $true
        }else {
            Write-Host -NoNewLine "."
            Start-sleep -Seconds 10
        }
        $COUNTNAS++
    }until($COUNTNAS -eq 50 -or $RESCPCODE -eq 200)
    if(-not($NASSuccess)){
        Write-Output "Timed Out or CQ $AEMINST Dint start Properly"
        Write-Output "Package Installation Aborted."
        Exit
    }
}
Write-Output "AEM $AEMINST Installation Successfully Completed."

Adding NAS storage, checking if AEM is up, stopping AEM completely, then creating a symlink for AEM NAS datastore and copying to NAS nad starting AEM

Write-Output "Commencing NAS Drive Setup for CQ $AEMINST"

$arrStatus = (Get-WmiObject -Class Win32_Service -Filter "Name='$ServiceName'").state
$AEMSERVICE = Get-Service -Name $ServiceName -ErrorAction SilentlyContinue
if ($AEMSERVICE.status -eq 'Running') {
    Write-Output "$ServiceName is Up and Running"
    Write-Output "Stopping $ServiceName Service"
    Stop-Service $ServiceName
    $AEMSERVICE.WaitForStatus("Stopped")
    Start-Sleep -seconds 60
    Write-Output "$ServiceName Service Stopped"
    Write-Output "Renaming the Datastore Directory"
    Rename-Item -Path "${repository}datastore" -NewName  "${repository}datastore-old" -Force
    Write-Output "Creating SymbolicLink for Datastore"
    New-Item -Path "${repository}datastore" -ItemType SymbolicLink -Value "C:UsersSKYDEVOPSAEMNASdr_$AEMINST" | Out-Null
    Write-Output "Copying files from Datastore to NAS"
    Get-ChildItem "${repository}datastore-old" | Copy -Destination "${repository}datastore" -Recurse -Force
    Write-Output "Copying Complete."
    Write-Output "Starting $ServiceName Service"
    Start-Service -Name $ServiceName
    $AEMSERVICE.WaitForStatus("Running")
    Start-Sleep -seconds 120
    Write-Output "$ServiceName Successfully Started."
}

Here is the final complete script

$ErrorActionPreference      =   "Stop"
$WarningPreference          =   "SilentlyContinue"
$AEMINST                    =   Read-Host "Choose Author/Publish Instance to Setup [Author/Publish]"
$AEMPORT                    =   Read-Host "Enter the CQ Port [4502/4503]"
$SRCPATH                    =   "C:UsersSKYDEVOPSAEMzinstaller"
$BASEPATH                   =   "C:UsersSKYDEVOPSAEMinstances$AEMINST"
$SERVICEPATH                =   "$BASEPATHcrx-quickstartopthelpers"
$JARFILE                    =   "$SRCPATHaem-$AEMINST-p$AEMPORT.jar"
$LicensePath                =   "$SRCPATHlicense.properties"
$AEMUNPACK                  =   "java -jar $JARFILE -unpack"
$ServiceName                =   "AEMPRD"
$USERNAME                   =   "SKYDEVOPS"
$HOSTNAME                   =   "192.168.2.8"
$CQ_PORT                    =   "4503"
$CQ_USER                    =   "admin"
$CQ_PASS                    =   "admin"
$CURLEXE                    =   'C:toolscurl761bincurl.exe'
$GCURL                      =   "http://${HOSTNAME}:${AEMPORT}/crx/packmgr/service.jsp"
$DOCUNSTORECFG              =   "org.apache.jackrabbit.oak.plugins.document.DocumentNodeStoreService.config"
$FILEDSTORECFG              =   "org.apache.jackrabbit.oak.plugins.blob.datastore.FiledataStore.config"
$PKGPATH01                  =   "$SRCPATHaemgit.ui.apps-1.0-SNAPSHOT.zip"
$PKGPATH02                  =   "$SRCPATHaemgit.ui.content-1.0-SNAPSHOT.zip"
$repository                 =   "$BASEPATHcrx-quickstartrepository"

if (!(Test-Path -Path $BASEPATH)) {
    Write-Output "$AEMINST Installation Directory Not Found"
    Write-Output "Creating Folder at $BASEPATH"
    New-Item -ItemType directory -Path $BASEPATH
    Copy-Item -Path $LicensePath -Destination $BASEPATH
    Set-Location -Path $BASEPATH
    Write-Output ""
    Write-Output "Unpacking $AEMINST"
    Invoke-Expression -Command:"cmd.exe /c $AEMUNPACK"

    if ($AEMINST -eq "Author") {
        Write-Output "Creating INSTALL Folder"
        New-Item -ItemType directory -Path "$BASEPATHcrx-quickstartinstall"
        Write-Output ""
        Write-Output "Copying Configurations to Install Directory"
        Copy-Item -Path "$SRCPATH$DOCUNSTORECFG" -Destination "$BASEPATHcrx-quickstartinstall"
        Copy-Item -Path "$SRCPATH$FILEDSTORECFG" -Destination "$BASEPATHcrx-quickstartinstall"
    }
    Set-Location -Path "C:UsersSKYDEVOPSDocumentsscripts"
}else {

    Write-Output "$BASEPATH Exists"
    Write-Output "Checking crx-quickstart Directory"
    if (!(Test-Path -Path $BASEPATHcrx-quickstart)) {
        Write-Output "crx-quickstart Not Found, Unpacking $AEMINST"
        Set-Location -Path $BASEPATH
        Write-Output "Unpacking $AEMINST"

        Invoke-Expression -Command:"cmd.exe /c $AEMUNPACK"
        if ($AEMINST -eq "Author") {
            Write-Output "Creating INSTALL Folder"
            New-Item -ItemType directory -Path "$BASEPATHcrx-quickstartinstall"
            Write-Output ""
            Write-Output "Copying Configurations to Install Directory"
            Copy-Item -Path "$SRCPATH$DOCUNSTORECFG" -Destination "$BASEPATHcrx-quickstartinstall"
            Copy-Item -Path "$SRCPATH$FILEDSTORECFG" -Destination "$BASEPATHcrx-quickstartinstall"
        }
    }else {

        Write-Output "crx-quickstart Found, Terminating Installation."
        Set-Location -Path "C:UsersSKYDEVOPSDocumentsscripts"
        Exit
    }
}

$AEMSERVICEPATH = "$BASEPATHcrx-quickstartopthelpersinstsrv.bat"
Rename-Item -Path "$AEMSERVICEPATH" -NewName  "instsrv.bat.bak"
Copy-Item -Path "${SRCPATH}instsrv-${AEMINST}.bat" -Destination "${SERVICEPATH}instsrv.bat"
$AEMSERVICEPATH = "$BASEPATHcrx-quickstartopthelpersinstsrv.bat"
$AEMCommand = "$AEMSERVICEPATH $ServiceName"
$MPass="shashi"
Write-Output "Creating $ServiceName Service"
Invoke-Expression -Command:"cmd.exe /c $AEMCommand"
$LogOnD = Get-WmiObject -Class Win32_Service -Filter "Name='$ServiceName'"
Write-Output "Adding LogOn Details"
$LogOnD.Change($null,$null,$null,$null,$null,$null,".$USERNAME","$MPass",$null,$null,$null)
Start-Sleep -seconds 5
$arrservice = (Get-Service $ServiceName)
Write-Output "Starting $ServiceName Service"
Start-Service -Name $arrservice.Name
$arrservice.WaitForStatus("Running")
Write-Output "$ServiceName Successfully Started."
Write-Output "Waiting for AEM Services to Come Up"
# Start-Sleep -s 480
$count = 0
$success = $null

if ($AEMINST -eq "Author") {
    Write-Output "Checking if CQ PackageMgr is UP"
    do{
            $HTCODE = cmd.exe /c curl -Is http://${CQ_USER}:${CQ_PASS}@${HOSTNAME}:${AEMPORT}/crx/packmgr/index.jsp | findstr "HTTP"
            $RESCODE = $HTCODE | %{ $_.Split(' ')[1]; }
            if ($RESCODE -eq 200) {
                Write-Output ""
                Write-Output "CQ PackageMgr Started"
                $success = $true
            }else {
                Write-Host -NoNewLine "."
                Start-sleep -Seconds 10
            }
            $count++
    }until($count -eq 180 -or $RESCODE -eq 200)
    if(-not($success)){
        Write-Output "Timed Out or CQ $AEMINST Dint start Properly"
        Write-Output "Package Installation Aborted."
        Exit
    }
}elseif ($AEMINST -eq "Publish") {
        Write-Output "Checking if CQ PackageMgr is UP"
    do{
            $HTCODE = cmd.exe /c curl -Is http://${CQ_USER}:${CQ_PASS}@${HOSTNAME}:${AEMPORT}/crx/packmgr/index.jsp | findstr "HTTP"
            $RESCODE = $HTCODE | %{ $_.Split(' ')[1]; }
            if ($RESCODE -eq 200) {
                Write-Output ""
                Write-Output "CQ PackageMgr Started"
                $success = $true
            }else {
                Write-Host -NoNewLine "."
                Start-sleep -Seconds 10
            }
            $count++
    }until($count -eq 50 -or $RESCODE -eq 200)
    if(-not($success)){
        Write-Output "Timed Out or CQ $AEMINST Dint start Properly"
        Write-Output "Package Installation Aborted."
        Exit
    }
}
Write-Output "Installing APPS Package"
cmd.exe /c $CURLEXE -u "${CQ_USER}:${CQ_PASS}" -F file=@"$PKGPATH01" -F name="aemgit.ui.apps" -F force=true -F install=false "$GCURL" | Out-Null
Write-Output "Package Installation Complete"

$COUNTNAS = 0
$NASSuccess = $null

if ($AEMINST -eq "Author") {
    Write-Output "Checking if CQ Author is UP"
    do{
        $CPCODE = cmd.exe /c curl -Is "http://${HOSTNAME}:${AEMPORT}/libs/granite/core/content/login.html" | findstr "HTTP"
        $RESCPCODE = $CPCODE | %{ $_.Split(' ')[1]; }
        if ($RESCPCODE -eq 200) {
            Write-Output ""
            Write-Output "CQ $AEMINST Started"
            $NASSuccess = $true
        }else {
            Write-Host -NoNewLine "."
            Start-sleep -Seconds 10
        }
        $COUNTNAS++
    }until($COUNTNAS -eq 180 -or $RESCPCODE -eq 200)
    if(-not($NASSuccess)){
        Write-Output "Timed Out or CQ $AEMINST Dint start Properly"
        Write-Output "Package Installation Aborted."
        Exit
    }
}elseif ($AEMINST -eq "Publish") {
        Write-Output "Checking if CQ Publish is UP"
    do{
        $CPCODE = cmd.exe /c curl -Is "http://${HOSTNAME}:${AEMPORT}/libs/granite/core/content/login.html" | findstr "HTTP"
        $RESCPCODE = $CPCODE | %{ $_.Split(' ')[1]; }
        if ($RESCPCODE -eq 200) {
            Write-Output ""
            Write-Output "CQ $AEMINST Started"
            $NASSuccess = $true
        }else {
            Write-Host -NoNewLine "."
            Start-sleep -Seconds 10
        }
        $COUNTNAS++
    }until($COUNTNAS -eq 50 -or $RESCPCODE -eq 200)
    if(-not($NASSuccess)){
        Write-Output "Timed Out or CQ $AEMINST Dint start Properly"
        Write-Output "Package Installation Aborted."
        Exit
    }
}
Write-Output "AEM $AEMINST Installation Successfully Completed."
Write-Output "Commencing NAS Drive Setup for CQ $AEMINST"

$arrStatus = (Get-WmiObject -Class Win32_Service -Filter "Name='$ServiceName'").state
$AEMSERVICE = Get-Service -Name $ServiceName -ErrorAction SilentlyContinue
if ($AEMSERVICE.status -eq 'Running') {
    Write-Output "$ServiceName is Up and Running"
    Write-Output "Stopping $ServiceName Service"
    Stop-Service $ServiceName
    $AEMSERVICE.WaitForStatus("Stopped")
    Start-Sleep -seconds 60
    Write-Output "$ServiceName Service Stopped"
    Write-Output "Renaming the Datastore Directory"
    Rename-Item -Path "${repository}datastore" -NewName  "${repository}datastore-old" -Force
    Write-Output "Creating SymbolicLink for Datastore"
    New-Item -Path "${repository}datastore" -ItemType SymbolicLink -Value "C:UsersSKYDEVOPSAEMNASdr_$AEMINST" | Out-Null
    Write-Output "Copying files from Datastore to NAS"
    Get-ChildItem "${repository}datastore-old" | Copy -Destination "${repository}datastore" -Recurse -Force
    Write-Output "Copying Complete."
    Write-Output "Starting $ServiceName Service"
    Start-Service -Name $ServiceName
    $AEMSERVICE.WaitForStatus("Running")
    Start-Sleep -seconds 120
    Write-Output "$ServiceName Successfully Started."
}

Shashi View All

A passionate devops and automation engineer

Leave a comment