Last active
September 29, 2021 10:43
-
-
Save FredIde/825c868f60edbad3c886 to your computer and use it in GitHub Desktop.
Revisions
-
FredIde revised this gist
Jan 13, 2016 . 1 changed file with 2 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -93,11 +93,11 @@ # Syslog facility to use (default is 'local0') # # COPYRIGHT # Apache License V2 # All rights reserved. # # AUTHORS # Fred Ide # # CHANGE HISTORY # 2013-04-26 mk@dvu.eu -
FredIde created this gist
Jan 13, 2016 .There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,2014 @@ #!/bin/bash #set -x #========================================================================== # NAME # aem-control - start, stop, restart or check the status of # an AEM instance (>= 5.5.0) # # SYNOPSIS # aem-control [start|stop|restart|status|activate|sweep|help|version] # # DESCRIPTION # Starts, stops, restartes or checks the status of a AEM instance. # # Mandatory command line arguments are # # start Start the Adobe AEM service # stop Stop the Adobe AEM service # restart Restart the Adobe AEM service # status Check the status of the Adobe AEM service # activate Activate all resolved Apache Felix bundles # sweep Run memory garbage collection # help Display usage information # version Display version information # # FILES # A configuration file "../etc/aem-control.conf" is required to provide # the following configuration variables: # # USERNAME # Operating system user to run this script as # # JAVA_HOME # Home directory of Java JDK # # JAVA_LANG # Value of LANG environment variable to be passed to Java # (e.g. 'en_US.UTF-8') # # JAVA_TZ # Value of TZ environment variable to be passed to Java # (e.g. 'UTC') # # JAVA_EXTRA_OPT_ARRAY # JVM extra options to use (garbage collector etc.) # # AEM_HOME # AEM home directory (the directory in which the 'crx-quickstart' # directory resides) # # AEM_ADDRESS # AEM listen address (usually '0.0.0.0' for all interfaces, otherwise # IP address of specific interface) # # AEM_PORT # AEM port number (usually 4502 for author and 4503 for publish # instances) # # AEM_USERNAME # Username of the administrative AEM user (usually 'admin') # # AEM_PASSWORD # Password of the administrative AEM user # # AEM_RUN_MODES # Comma-delimited list of AEM run modes (must either contain 'author' or 'publish') # # LOG_HOME # Home directory for AEM log directories # # LOG_HISTORY # Maximum number of log directories to keep # # CONNECT_TIMEOUT # Maximum number of seconds to wait for network connection # to be established (default is 5 seconds) # # SOCKET_TIMEOUT # Maximum number of seconds to wait for a complete response # from a host after a request was sent (default is 120 seconds) # # START_TIMEOUT # Timeout for AEM service to start in seconds (default is 600 seconds) # # STOP_TIMEOUT # Timeout for AEM service to stop in seconds (default is 1800 seconds) # # CHECK_DELAY # Delay in between successive functional checks in seconds # (default is 10 seconds) # # SYSLOG_FACILITY # Syslog facility to use (default is 'local0') # # COPYRIGHT # Copyright (c) 2013-2015 Digital Venture Unternehmensberatung GmbH # All rights reserved. # # AUTHORS # Maximilian Kolmhuber (mk@dvu.eu) # # CHANGE HISTORY # 2013-04-26 mk@dvu.eu # Initial release # 2015-10-12 FAI # Bug fixing #========================================================================== #-------------------------------------------------------------------------- # NAME # whence - search for a command and return its absolute file name # # SYNOPSIS # whence [command] # # DESCRIPTION # Searches for a command and returns its absolute file name #-------------------------------------------------------------------------- declare -r PATH='/sbin:/bin:/usr/sbin:/usr/bin' whence() { local -r COMMAND_NAME="$1" local COMMAND_FILE # Search PATH for command COMMAND_FILE="$(type -p "$COMMAND_NAME" 2>/dev/null)" if [[ -x "$COMMAND_FILE" ]]; then # Found echo "$COMMAND_FILE" else # Not found echo -n "Error: \"$COMMAND_NAME\" - command not found" >/dev/tty kill -2 $$ fi } # Declare absolute file names of all external commands used by this script declare -r CAT="$(whence cat)" declare -r CURL="$(whence curl)" declare -r DATE="$(whence date)" declare -r ENV="$(whence env)" declare -r FIND="$(whence find)" declare -r GREP="$(whence grep)" declare -r HOSTNAME="$(whence hostname)" declare -r ID="$(whence id)" declare -r IFCONFIG="$(whence ifconfig)" declare -r LN="$(whence ln)" declare -r LOGGER="$(whence logger)" declare -r MKDIR="$(whence mkdir)" declare -r MV="$(whence mv)" declare -r NOHUP="$(whence nohup)" declare -r PGREP="$(whence pgrep)" declare -r READLINK="$(whence readlink)" declare -r RM="$(whence rm)" declare -r RMDIR="$(whence rmdir)" declare -r SLEEP="$(whence sleep)" declare -r SORT="$(whence sort)" declare -r SU="$(whence su)" declare -r TAIL="$(whence tail)" #-------------------------------------------------------------------------- # NAME # real_path - return the canonicalized absolute pathname of a given # pathname # # SYNOPSIS # real_path [pathname] # # DESCRIPTION # Expands all symbolic links and resolves references to /./, /../ and # extra '/' characters in the specified pathname to produce a # canonicalized absolute pathname. If the specified pathname is invalid, # the function will set the return code to 1. #-------------------------------------------------------------------------- real_path() { local -r REL_PATH="$1" local ABS_PATH ABS_PATH="$("$READLINK" -f "$REL_PATH" 2>/dev/null)" if [[ -z "$ABS_PATH" ]]; then echo "$REL_PATH" return 1 fi echo "$ABS_PATH" return 0 } #-------------------------------------------------------------------------- # Global Variables #-------------------------------------------------------------------------- # General constants declare -r LF=$'\n' # Declare and initialize script-releated variables declare -r MY_VERSION='1.3.0' declare -r MY_SCRIPT_FILE="$(real_path "$0")" declare -r MY_SCRIPT_NAME="${MY_SCRIPT_FILE##*/}" declare -r MY_SCRIPT_DIR="${MY_SCRIPT_FILE%/*}" declare -r MY_SCRIPT_ARGS="$@" declare -r MY_FQDN="$("$HOSTNAME" -f 2>/dev/null)" declare -ri MY_PID=$$ declare -r MY_CWD="$PWD" declare -r MY_IFS="$IFS" declare -r MY_TIMESTAMP="$("$DATE" -u '+%Y-%m-%dT%H:%M:%SZ' 2>/dev/null)" declare MY_LOCK_FILE="/tmp/.${MY_SCRIPT_NAME}.lock" # Declare configuration file variables declare USERNAME declare JAVA_HOME declare JAVA_LANG='en_US.UTF-8' declare JAVA_TZ='UTC' declare JAVA_HEAP_SIZE declare JAVA_PERM_SIZE declare -a JAVA_EXTRA_OPT_ARRAY declare AEM_HOME declare AEM_ADDRESS='0.0.0.0' # default to all interfaces declare AEM_PORT=4502 # default to port 4502 declare AEM_USERNAME='admin' # default to 'admin' declare AEM_PASSWORD='admin' # default to 'admin' declare AEM_RUN_MODES='author' # default to 'author' declare AEM_UMASK='0022' declare -a AEM_EXTRA_OPT_ARRAY declare LOG_HOME declare LOG_HISTORY=7 # default to 7 days declare CONNECT_TIMEOUT=5 # default to 5 seconds declare SOCKET_TIMEOUT=120 # default to 2 minutes declare START_TIMEOUT=1800 # default to 30 minutes declare -a SKIP_BUNDLE_ARRAY declare SKIP_BUNDLE_REGEX declare STOP_TIMEOUT=1800 # default to 30 minutes declare CHECK_DELAY=10 # Default to 10 seconds declare SYSLOG_FACILITY='local0' # default to 'local0' # Declare internal variables declare CONF_FILE declare JAVA declare AEM_BASE_DIR declare AEM_JAR_FILE declare AEM_INSTANCE_NAME declare AEM_AUTHORITY declare AEM_CREDENTIALS declare AEM_PID #-------------------------------------------------------------------------- # NAME # version - print version information and exit # # SYNOPSIS # version # # DESCRIPTION # Writes version information to standard output and terminates the script # with error code 0. #-------------------------------------------------------------------------- version() { echo '' echo "$MY_SCRIPT_NAME version $MY_VERSION" echo '' echo 'Copyright (c) 2013-2015 Digital Venture Unternehmensberatung GmbH' echo 'All rights reserved.' echo '' exit 0 } #-------------------------------------------------------------------------- # NAME # usage - print usage information and exit # # SYNOPSIS # usage [exit_code] # # DESCRIPTION # Writes usage information to standard output and terminates the script # with the specified error code or the default exit code 2. #-------------------------------------------------------------------------- usage() { local -ri EXIT_CODE=${1:-2} echo '' echo "Usage: $MY_SCRIPT_NAME [start|stop|restart|status|help|version] (first)" echo '' echo 'Mandatory Arguments:' echo 'start Start the Adobe AEM service' echo 'stop Stop the Adobe AEM service' echo 'restart Restart the Adobe AEM service' echo 'status Check the status of the Adobe AEM service' echo 'activate Activate all installed/resolved Apache Felix bundles' echo 'sweep Run memory garbage collection' echo 'help Display this message' echo 'version Display version information' echo '' exit $EXIT_CODE } #-------------------------------------------------------------------------- # NAME # log - print and log messages # # SYNOPSIS # log [severity] [message...] # # DESCRIPTION # Writes the specified message to the respecitve log. #-------------------------------------------------------------------------- log() { local SYSLOG_SEVERITY="$1" local SEVERITY local LINE case "$SYSLOG_SEVERITY" in 'emerg') # Emergency: system is unusable SEVERITY='Emergency' ;; 'alert') # Alert: action must be taken immediately SEVERITY='Alert' ;; 'crit') # Critical: critical condition SEVERITY='Critical' ;; 'err') # Error: error condition SEVERITY='Error' ;; 'warning') # Warning: warning condition SEVERITY='Warning' ;; 'notice') # Notice: normal but significant condition SEVERITY='Notice' ;; 'info') # Informational: informational message SEVERITY='Info' ;; 'debug') # Debug: debug-level message SEVERITY='Debug' ;; *) # Invalid severity SYSLOG_SEVERITY='err' SEVERITY='Unknown severity' ;; esac shift echo "$SEVERITY: $1" "$LOGGER" \ -p $SYSLOG_FACILITY.$SYSLOG_SEVERITY \ -t "$MY_SCRIPT_NAME" \ -i "$SEVERITY: $1" \ &>/dev/null shift while (( $# > 0 )); do IFS="$LF" for LINE in $1; do if [[ -n "$LINE" ]]; then echo "Details: $LINE" "$LOGGER" \ -p $SYSLOG_FACILITY.$SYSLOG_SEVERITY \ -t "$MY_SCRIPT_NAME" \ -i "Details: $LINE" \ &>/dev/null fi done IFS="$MY_IFS" shift done } #-------------------------------------------------------------------------- # NAME # crit - print critical error message and exit # # SYNOPSIS # crit [message...] # # DESCRIPTION # Writes the specified error message to standard error and # terminates the script with the specified error code. #-------------------------------------------------------------------------- crit() { log 'crit' "$@" 1>&2 exit 1 } #-------------------------------------------------------------------------- # NAME # err - print error message # # SYNOPSIS # err [message...] # # DESCRIPTION # Writes the specified error message to standard error. #-------------------------------------------------------------------------- err() { log 'err' "$@" 1>&2 } #-------------------------------------------------------------------------- # NAME # warning - print warning message # # SYNOPSIS # warning [message...] # # DESCRIPTION # Writes the specified warning message to standard error. #-------------------------------------------------------------------------- warning() { log 'warning' "$@" 1>&2 } #-------------------------------------------------------------------------- # NAME # notice - print notification message # # SYNOPSIS # notice [message...] # # DESCRIPTION # Writes the specified notification message to standard output. #-------------------------------------------------------------------------- notice() { log 'notice' "$@" } #-------------------------------------------------------------------------- # NAME # info - print informational message # # SYNOPSIS # info [message...] # # DESCRIPTION # Writes the specified informational message to standard output. #-------------------------------------------------------------------------- info() { log 'info' "$@" } #-------------------------------------------------------------------------- # NAME # lock - exit if there is an existing lock file or create a lock file # # SYNOPSIS # lock # # DESCRIPTION # Checks if there is an existing lock file and exits if the PID of the # locking process is still alive. Otherwise, a lock file is created. #-------------------------------------------------------------------------- lock() { local PID # Check if there is an existing lock file if [[ -f "$MY_LOCK_FILE" ]]; then if [[ -r "$MY_LOCK_FILE" ]]; then # Check if process is still running PID=$("$CAT" "$MY_LOCK_FILE") if [[ "$PID" =~ ^[1-9][0-9]*$ ]]; then kill -0 "$PID" &>/dev/null if (( $? == 0 )); then # Process is still running crit "\"$MY_SCRIPT_NAME\" is locked by PID $PID" fi fi else # Process is bein run by someone else crit "\"$MY_SCRIPT_NAME\" is being run by another user" fi fi # Create new lock file echo -n "$MY_PID" 1>"$MY_LOCK_FILE" } #-------------------------------------------------------------------------- # NAME # unlock - delete lock file # # SYNOPSIS # unlock # # DESCRIPTION # Deletes the lock file. #-------------------------------------------------------------------------- unlock() { "$RM" -f "$MY_LOCK_FILE" &>/dev/null } #-------------------------------------------------------------------------- # NAME # check_mode - check the permissions of a file or directory # # SYNOPSIS # check_mode [item] [f][d][r][w][x] # # DESCRIPTION # Checks if the specified file or directory possesses the specified # permissions #-------------------------------------------------------------------------- check_mode() { local ITEM="$1" local FLAGS="$2" if [[ "$FLAGS" == *f* ]]; then if [[ ! -f "$ITEM" ]]; then crit "File \"$ITEM\" not found" fi fi if [[ "$FLAGS" == *d* ]]; then if [[ ! -d "$ITEM" ]]; then crit "Directory \"$ITEM\" not found" fi fi if [[ "$FLAGS" == *r* ]]; then if [[ ! -r "$ITEM" ]]; then crit "No read permission for \"$ITEM\"" fi fi if [[ "$FLAGS" == *w* ]]; then if [[ ! -w "$ITEM" ]]; then crit "No write permission for \"$ITEM\"" fi fi if [[ "$FLAGS" == *x* ]]; then if [[ ! -x "$ITEM" ]]; then crit "No execute permission for \"$ITEM\"" fi fi } #-------------------------------------------------------------------------- # NAME # check_if_addr - check interface address # # SYNOPSIS # check_if_addr [if_addr] # # DESCRIPTION # Checks whether or not the specified interface address belongs to this # host. #-------------------------------------------------------------------------- check_if_addr() { local -r IF_ADDR="$1" local REGEX local -a LINE_ARRAY local LINE local ADDR # Check if the specified address references all interfaces if [[ "$IF_ADDR" == '0.0.0.0' ]]; then return fi # Check if the specified address references an existing interface IFS="$LF" LINE_ARRAY=( $("$IFCONFIG" -a 2>/dev/null) ) IFS="$MY_IFS" REGEX='inet[[:blank:]]+(addr:)?([[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3})' for LINE in "${LINE_ARRAY[@]}"; do if [[ "$LINE" =~ $REGEX ]]; then ADDR="${BASH_REMATCH[2]}" if [[ "$IF_ADDR" == "$ADDR" ]]; then return fi fi done crit "The interface address \"$IF_ADDR\" does not belong to this host" } #-------------------------------------------------------------------------- # NAME # load_config - load configuration file # # SYNOPSIS # load_config # # DESCRIPTION # Sources configuration variables from a configuration file. #-------------------------------------------------------------------------- load_config() { # Assemble absolute pathname of configuration directory local -r CONF_DIR="$(real_path "$MY_SCRIPT_DIR/../etc")" # Assemble name of configuration file local -r CONF_NAME="${MY_SCRIPT_NAME%.*}.conf" # Assemble absolute pathname of configuration file CONF_FILE="$(real_path "$CONF_DIR/$CONF_NAME")" # Make sure that configuration file exists and is readable check_mode "$CONF_FILE" fr # Change to configuration directory to allow configuration file to # source other configuration files by their relative pathname cd "$CONF_DIR" # Source configuration file source "$CONF_FILE" } #-------------------------------------------------------------------------- # NAME # check_config - check configuration variables # # SYNOPSIS # check_config # # DESCRIPTION # Check if the configuration variables contain valid values. #-------------------------------------------------------------------------- check_config() { local NOFILE local -i REQUIRED_EUID local REGEX local LINE local ADDRESS local -a ADDRESS_ARRAY local -i MAX_CHECK_DELAY local -a JAR_ARRAY local -i JAR_COUNT local -i SKIP_BUNDLE_COUNT # Check if syslog facility is defined if [[ -z "$SYSLOG_FACILITY" ]]; then crit "SYSLOG_FACILITY is not defined in configuration file \"$CONF_FILE\"" fi # Check if username is defined if [[ -z "$USERNAME" ]]; then crit "USERNAME is not defined in configuration file \"$CONF_FILE\"" fi # Check if username exists REQUIRED_EUID=$("$ID" -u $USERNAME 2>/dev/null) if (( $? != 0 )); then crit "Username \"$USERNAME\" does not exist" elif (( EUID != REQUIRED_EUID )); then # Check if effective user is root if (( EUID == 0 )); then # Switch to required user "$SU" - $USERNAME -c "cd \"$MY_CWD\"; \"$MY_SCRIPT_FILE\" $MY_SCRIPT_ARGS" # Note: su returns the exit code of the executed program exit $? else crit "Must be run as user \"$USERNAME\"" fi fi # Check if Java home directory is defined if [[ -z "$JAVA_HOME" ]]; then crit "JAVA_HOME is not defined in configuration file \"$CONF_FILE\"" fi # Check if Java home directory exists and is accessible JAVA_HOME="$(real_path "$JAVA_HOME")" check_mode "$JAVA_HOME" drx check_mode "$JAVA_HOME/bin" drx # Check if "java" program exists and is executable JAVA="$JAVA_HOME/bin/java" check_mode "$JAVA" fx # Check if Java heap size is defined and valid if [[ -z "$JAVA_HEAP_SIZE" ]]; then crit "JAVA_HEAP_SIZE is not defined in configuration file \"$CONF_FILE\"" elif [[ ! "$JAVA_HEAP_SIZE" =~ ^[0-9]{4,}$ ]]; then crit "JAVA_HEAP_SIZE must be an integer value greater or equal 1024" elif (( JAVA_HEAP_SIZE < 1024 )); then crit "JAVA_HEAP_SIZE must be an integer value greater or equal 1024" fi # Check if Java permanent generation size is defined and valid if [[ -z "$JAVA_PERM_SIZE" ]]; then crit "JAVA_PERM_SIZE is not defined in configuration file \"$CONF_FILE\"" elif [[ ! "$JAVA_PERM_SIZE" =~ ^[0-9]{3,}$ ]]; then crit "JAVA_PERM_SIZE must be an integer value greater or equal 256" elif (( JAVA_PERM_SIZE < 256 )); then crit "JAVA_PERM_SIZE must be an integer value greater or equal 256" fi # Check if AEM directory is defined if [[ -z "$AEM_HOME" ]]; then crit "AEM_HOME is not defined in configuration file \"$CONF_FILE\"" fi # Check if AEM directory exists and is accessible AEM_HOME="$(real_path "$AEM_HOME")" if [[ "$AEM_HOME" =~ ^/*$ ]]; then crit "Cowardly refusing to accept \"$AEM_HOME\" as AEM instance directory" fi check_mode "$AEM_HOME/" drwx # Check if AEM crx-quickstart directoy exists and is accessible AEM_BASE_DIR="$AEM_HOME/crx-quickstart" check_mode "$AEM_BASE_DIR/" drx # Check if AEM crx-quickstart/app directroy exists and is accessible check_mode "$AEM_BASE_DIR/app/" drx # Check if AEM crx-quickstart/logs directroy exists and is accessible if [[ ! -L "$AEM_BASE_DIR/logs" && -d "$AEM_BASE_DIR/logs/" ]]; then check_mode "$AEM_BASE_DIR/logs/" drwx fi # Check if AEM address is defined and valid if [[ -z "$AEM_ADDRESS" ]]; then crit "AEM_ADDRESS is not defined in configuration file \"$CONF_FILE\"" elif [[ ! "$AEM_ADDRESS" =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then crit "AEM_ADDRESS does not contain a valid IP address" else check_if_addr "$AEM_ADDRESS" fi # Check if AEM port is defined and valid if [[ -z "$AEM_PORT" ]]; then crit "AEM_PORT is not defined in configuration file \"$CONF_FILE\"" elif [[ ! "$AEM_PORT" =~ ^[0-9]{4,5}$ ]]; then crit "AEM_PORT must be an integer value in the interval [1024; 65535]" elif (( AEM_PORT < 1024 || AEM_PORT > 65535 )); then crit "AEM_PORT must be an integer value in the interval [1024; 65535]" fi # Assemble authority part of AEM URL if [[ "$AEM_ADDRESS" == '0.0.0.0' ]]; then AEM_AUTHORITY="127.0.0.1:$AEM_PORT" else AEM_AUTHORITY="$AEM_ADDRESS:$AEM_PORT" fi # Check if AEM username is defined and valid if [[ -z "$AEM_USERNAME" ]]; then crit "AEM_USERNAME is not defined in configuration file \"$CONF_FILE\"" elif [[ "$AEM_USERNAME" =~ [:] ]]; then crit "AEM_USERNAME must not contain a colon character (\":\")" fi # Check if AEM password is defined and valid if [[ -z "$AEM_PASSWORD" ]]; then crit "AEM_PASSWORD is not defined in configuration file \"$CONF_FILE\"" elif [[ "$AEM_PASSWORD" =~ [:] ]]; then crit "AEM_PASSWORD must not contain a colon character (\":\")" fi # Assemble credentials for AEM AEM_CREDENTIALS="$AEM_USERNAME:$AEM_PASSWORD" # Check if AEM run mode is defined and valid if [[ -z "$AEM_RUN_MODES" ]]; then crit "AEM_RUN_MODES is not defined in configuration file \"$CONF_FILE\"" fi REGEX='(^|,)(author|publish)(,|$)' if [[ ! "$AEM_RUN_MODES" =~ $REGEX ]]; then crit "AEM_RUN_MODES must either contain \"author\" or \"publish\"" fi # Check if log directory home is defined, exists and is accessible if [[ -z "$LOG_HOME" ]]; then crit "LOG_HOME is not defined in configuration file \"$CONF_FILE\"" fi # Check if log directory home exists and is accessible LOG_HOME="$(real_path "$LOG_HOME")" check_mode "$LOG_HOME" drwx # Check if log directory is valid REGEX="^$AEM_BASE_DIR/logs(/|\$)" if [[ "$LOG_HOME" =~ $REGEX ]]; then crit "LOG_HOME must not equal or be a subdirectory of \"$AEM_BASE_DIR/logs\"" fi # Check if log history is defined and valid if [[ -z "$LOG_HISTORY" ]]; then crit "LOG_HISTORY is not defined in configuration file \"$CONF_FILE\"" elif [[ ! "$LOG_HISTORY" =~ ^[0-9]+$ ]]; then crit "LOG_HISTORY must be an integer value greater than 0" elif (( LOG_HISTORY == 0 )); then crit "LOG_HISTORY must be an integer value greater than 0" fi # Check if connection timeout is defined and valid if [[ -z "$CONNECT_TIMEOUT" ]]; then crit "CONNECT_TIMEOUT is not defined in configuration file \"$CONF_FILE\"" elif [[ ! "$CONNECT_TIMEOUT" =~ ^[0-9]+$ ]]; then crit "CONNECT_TIMEOUT must be an integer value greater or equal 5" elif (( CONNECT_TIMEOUT < 5 )); then crit "CONNECT_TIMEOUT must be an integer value greater or equal 5" fi # Check if socket timeout is defined and valid if [[ -z "$SOCKET_TIMEOUT" ]]; then crit "SOCKET_TIMEOUT is not defined in configuration file \"$CONF_FILE\"" elif [[ ! "$SOCKET_TIMEOUT" =~ ^[0-9]+$ ]]; then crit "SOCKET_TIMEOUT must be an integer value greater or equal 15" elif (( SOCKET_TIMEOUT < 15 )); then crit "SOCKET_TIMEOUT must be an integer value greater or equal 15" fi # Check if start timeout is valid if [[ ! "$START_TIMEOUT" =~ ^[0-9]{2,}$ ]]; then crit "START_TIMEOUT must be an integer value greater or equal 60" elif (( START_TIMEOUT < 60 )); then crit "START_TIMEOUT must be an integer value greater or equal 60" fi # Check if stop timeout is valid if [[ ! "$STOP_TIMEOUT" =~ ^[0-9]{2,}$ ]]; then crit "STOP_TIMEOUT must be an integer value greater or equal 60" elif (( STOP_TIMEOUT < 60 )); then crit "STOP_TIMEOUT must be an integer value greater or equal 60" fi # Compute maximum value for delay if (( START_TIMEOUT < STOP_TIMEOUT )); then (( MAX_CHECK_DELAY = START_TIMEOUT / 4 )) else (( MAX_CHECK_DELAY = STOP_TIMEOUT / 4 )) fi # Check if check delay is valid if [[ -z "$CHECK_DELAY" ]]; then crit "CHECK_DELAY is not defined in configuration file \"$CONF_FILE\"" elif [[ ! "$CHECK_DELAY" =~ ^[0-9]+$ ]]; then crit "CHECK_DELAY must be an integer value in the interval [1; $MAX_CHECK_DELAY]" elif (( CHECK_DELAY < 1 || CHECK_DELAY > MAX_CHECK_DELAY )); then crit "CHECK_DELAY must be an integer value in the interval [1; $MAX_CHECK_DELAY]" fi # Assemble regular expression for bundle exclusion SKIP_BUNDLE_COUNT=${#SKIP_BUNDLE_ARRAY[*]} while (( SKIP_BUNDLE_COUNT > 1 )); do (( SKIP_BUNDLE_COUNT-- )) SKIP_BUNDLE_REGEX="|${SKIP_BUNDLE_ARRAY[SKIP_BUNDLE_COUNT]}$SKIP_BUNDLE_REGEX" done if (( SKIP_BUNDLE_COUNT > 0 )); then SKIP_BUNDLE_REGEX="\"name\":\"(${SKIP_BUNDLE_ARRAY[0]}$SKIP_BUNDLE_REGEX)\"" else SKIP_BUNDLE_REGEX='^$' fi # Search for Adobe AEM jar file JAR_ARRAY=( $( \ "$FIND" \ "$AEM_BASE_DIR/app" \ -maxdepth 1 \ -name "*.jar" \ ) ) JAR_COUNT=${#JAR_ARRAY[*]} # Check if Adobe AEM jar file exists and is accessible if (( JAR_COUNT < 1 )); then crit "Cannot find any Adobe AEM jar file that matches \"$AEM_BASE_DIR/app/*.jar\"" elif (( JAR_COUNT > 1)); then crit "Found multiple Adobe AEM jar files that match \"$AEM_BASE_DIR/app/*.jar\": ${JAR_ARRAY[*]}" fi AEM_JAR_FILE="${JAR_ARRAY[0]}" check_mode "$AEM_JAR_FILE" fr # Initialize instance name AEM_INSTANCE_NAME="${MY_FQDN}_${AEM_ADDRESS}_${AEM_PORT}" # Initialize lock file name MY_LOCK_FILE="/tmp/.aem_${AEM_INSTANCE_NAME}.lock" # Change back to original directory cd "$MY_CWD" } #-------------------------------------------------------------------------- # NAME # configure_shell - configure shell limits # # SYNOPSIS # configure_shell # # DESCRIPTION # Checks the maximum number of open file descriptors and the maximum # amount of virtual memory available to the shell and sets these # built-in shell limits to their highest possible values. #-------------------------------------------------------------------------- configure_shell() { local -r REGEX='[[:digit:]]+' local VALUE local -i EXIT_STATUS # Check maximum number of open file descriptors VALUE="$(ulimit -n)" if [[ "$VALUE" =~ $REGEX ]]; then if (( VALUE < 65535 )); then # Set maximum number of open file descriptors for VALUE in 65535 63999 32768 16384 8192; do ulimit -n $VALUE &>/dev/null EXIT_STATUS=$? if (( EXIT_STATUS == 0 )); then break fi done if (( EXIT_STATUS != 0 )); then crit "The maximum number of open file descriptors must be at least 8192" fi fi elif [[ "$VALUE" != 'unlimited' ]]; then crit "\"ulimit -n\" returned unknown value \"$VALUE\"" fi # Check maximum amount of virtual memory available to the shell VALUE="$(ulimit -v)" if [[ "$VALUE" != 'unlimited' ]]; then # Set maximum amount of virtual memory available to the shell ulimit -v unlimited &>/dev/null EXIT_STATUS=$? if (( EXIT_STATUS != 0 )); then crit "The maximum amount of virtual memory available to the shell must be unlimited" fi fi # Set file mode mask umask "$AEM_UMASK" } #-------------------------------------------------------------------------- # NAME # rotate_log_dirs - rotate log directories # # SYNOPSIS # rotate_log_dirs # # DESCRIPTION # Deletes old log directory structures, creates a new log directoy # structure and replaces all AEM log directories with symbolic links # to this new log directory structure. #-------------------------------------------------------------------------- rotate_log_dirs() { local -r CURRENT_LOG_DIR='current' local -r LOG_BASE_DIR="$LOG_HOME/$AEM_INSTANCE_NAME" local REGEX local -a LOG_DIR_ARRAY local -i INDEX local LOG_DIR # Create log base directory "$MKDIR" -p "$LOG_BASE_DIR/" &>/dev/null # Get array of all existing log directories sorted alphabetically in reverse order REGEX="^.*/[0-9]+-[0-9]+-[0-9]+T[0-9]+:[0-9]+:[0-9]+Z\$" LOG_DIR_ARRAY=( $( \ "$FIND" \ "$LOG_BASE_DIR" \ -maxdepth 1 \ -regex "$REGEX" \ 2>/dev/null | \ "$SORT" -r \ 2>/dev/null \ ) ) # Delete old log directories INDEX=${#LOG_DIR_ARRAY[*]} while (( INDEX >= LOG_HISTORY )); do (( INDEX-- )) LOG_DIR="${LOG_DIR_ARRAY[INDEX]}" "$RM" -rf "$LOG_DIR" &>/dev/null done # Check if "logs" is a real directory if [[ ! -L "$AEM_BASE_DIR/logs" && -d "$AEM_BASE_DIR/logs/" ]]; then # Move "logs" directory to new log directory "$MV" "$AEM_BASE_DIR/logs" "$LOG_BASE_DIR/$MY_TIMESTAMP" &>/dev/null else # Create new log directory "$MKDIR" -p "$LOG_BASE_DIR/$MY_TIMESTAMP" &>/dev/null fi # Make "current" symbolic link point to new log directoy cd "$LOG_BASE_DIR" "$RM" -f "$CURRENT_LOG_DIR" &>/dev/null "$LN" -s "$MY_TIMESTAMP" "$CURRENT_LOG_DIR" &>/dev/null # Make "logs" symbolic link point to "current" symbolic link "$RM" -f "$AEM_BASE_DIR/logs" &>/dev/null "$LN" -s "$LOG_BASE_DIR/$CURRENT_LOG_DIR" "$AEM_BASE_DIR/logs" &>/dev/null } #-------------------------------------------------------------------------- # NAME # get_aem_pid - get Adobe AEM process ID # # SYNOPSIS # get_aem_pid # # DESCRIPTION # Sets the global AEM_PID variable to the process ID of the # Adobe AEM process. #-------------------------------------------------------------------------- get_aem_pid() { #set -x local -r REGEX="-Daem\\.instance\\.name=${AEM_INSTANCE_NAME//./\\.}" # Get process ID of Adobe AEM process AEM_PID=$("$PGREP" -u $EUID -f -- "$REGEX" 2>/dev/null) # Check if process ID is empty if [[ -z "$AEM_PID" ]]; then # info "Java-process is NOT running for $REGEX " # Check if there is a PID file (maybe AEM was started # with the vanilla start script) if [[ -r "$AEM_BASE_DIR/conf/cq.pid" ]]; then # Get process ID from PID file AEM_PID="$("$CAT" "$AEM_BASE_DIR/conf/cq.pid" 2>/dev/null)" if [[ -n "$AEM_PID" ]]; then # Check if AEM process is still running kill -0 "$AEM_PID" &>/dev/null if (( $? != 0 )); then # AEM process is no longer running AEM_PID='' info "Java-process is NO LONGER running for $REGEX " fi fi fi fi # set +x } #-------------------------------------------------------------------------- # NAME # activate - activate all installed/resolved Apache Felix bundles # # SYNOPSIS # activate # # DESCRIPTION # Activates all resolved Apache Felix bundles. #-------------------------------------------------------------------------- activate() { local URL local OUTPUT local -i EXIT_STATUS local REGEX local -a BUNDLE_ARRAY local -i BUNDLE_COUNT local BUNDLE local -i BUNDLE_ID info "Retrieving all installed or resolved Apache Felix bundles" # Get bundle information from Apache Felix URL="http://$AEM_AUTHORITY/system/console/bundles.json" OUTPUT="$( \ "$CURL" \ --silent \ --show-error \ --connect-timeout $CONNECT_TIMEOUT \ --max-time $SOCKET_TIMEOUT \ --location \ --user "$AEM_CREDENTIALS" \ --request GET \ --url "$URL" \ 2>&1 \ )" EXIT_STATUS=$? if (( EXIT_STATUS != 0 )); then crit "\"$CURL\" returned error code $EXIT_STATUS" "$OUTPUT" fi # Extract all installed or resolved bundles from JSON output REGEX='\{[^\}]*"state"[[:space:]]*:[[:space:]]*"(Installed|Resolved)"[^\}]+\}' IFS="$LF" BUNDLE_ARRAY=( $( \ echo "$OUTPUT" | \ "$GREP" -Eio "$REGEX" 2>/dev/null | \ "$GREP" -Eiv "$SKIP_BUNDLE_REGEX" 2>/dev/null \ ) ) IFS="$MY_IFS" BUNDLE_COUNT=${#BUNDLE_ARRAY[@]} info "Apache Felix reports that there are $BUNDLE_COUNT installed or resolved bundles" if (( BUNDLE_COUNT == 0 )); then return fi # Start all installed or resolved bundles REGEX='"id"[[:space:]]*:[[:space:]]*([[:digit:]]+)' for BUNDLE in "${BUNDLE_ARRAY[@]}"; do if [[ "$BUNDLE" =~ $REGEX ]]; then BUNDLE_ID=${BASH_REMATCH[1]} info "Starting bundle with ID $BUNDLE_ID" URL="http://$AEM_AUTHORITY/system/console/bundles/$BUNDLE_ID" OUTPUT="$( \ "$CURL" \ --silent \ --show-error \ --connect-timeout $CONNECT_TIMEOUT \ --max-time $SOCKET_TIMEOUT \ --location \ --user "$AEM_CREDENTIALS" \ --request POST \ --url "$URL" \ --data 'action=start' \ 2>&1 \ )" EXIT_STATUS=$? if (( EXIT_STATUS != 0 )); then crit "\"$CURL\" returned error code $EXIT_STATUS" "$OUTPUT" fi fi done } #-------------------------------------------------------------------------- # NAME # start - start AEM service # # SYNOPSIS # start # # DESCRIPTION # Starts the AEM service. #-------------------------------------------------------------------------- start() { local -a JAVA_OPT_ARRAY local -a AEM_OPT_ARRAY local URL local OUTPUT local REGEX local REGEX2 local -i EXIT_STATUS local -i START_TIME local -i DURATION local -i REMAINING_TIME local -a BUNDLE_ARRAY local -i BUNDLE_COUNT # Make sure there is no stale PID file "$RM" -f "$AEM_BASE_DIR/conf/cq.pid" &>/dev/null # Start Adobe AEM info "Starting Adobe AEM process" # Assemble Java options JAVA_OPT_ARRAY=( \ '-server' \ "-Xms${JAVA_HEAP_SIZE}m" \ "-Xmx${JAVA_HEAP_SIZE}m" \ "-XX:PermSize=${JAVA_PERM_SIZE}m" \ "-XX:MaxPermSize=${JAVA_PERM_SIZE}m" \ '-Djava.awt.headless=true' \ '-Dfile.encoding=UTF8' \ "-Daem.instance.name=$AEM_INSTANCE_NAME" \ "-Dsling.run.modes=$AEM_RUN_MODES" \ ) # Assemble Adobe AEM options AEM_OPT_ARRAY=( \ 'start' \ '-a' "$AEM_ADDRESS" \ '-p' "$AEM_PORT" \ '-c' "$AEM_BASE_DIR" \ '-i' "$AEM_BASE_DIR/launchpad" \ ) # Start Adobe AEM process configure_shell "$ENV" \ -i \ "LANG=$JAVA_LANG" \ "TZ=$JAVA_TZ" \ "JAVA_HOME=$JAVA_HOME" \ "$NOHUP" \ "$JAVA" \ "${JAVA_OPT_ARRAY[@]}" \ "${JAVA_EXTRA_OPT_ARRAY[@]}" \ -jar "$AEM_JAR_FILE" \ "${AEM_OPT_ARRAY[@]}" \ "${AEM_EXTRA_OPT_ARRAY[@]}" \ 0</dev/null \ 1>"$AEM_BASE_DIR/logs/startup.log" \ 2>&1 \ & # Check for error code EXIT_STATUS=$? if (( EXIT_STATUS != 0 )); then crit \ "Adobe AEM returned error $EXIT_STATUS" \ "$("$TAIL" "$AEM_BASE_DIR/logs/startup.log" 2>/dev/null)" fi START_TIME=$("$DATE" -u '+%s' 2>/dev/null) DURATION=0 while (( DURATION < START_TIMEOUT )); do # Check if Adobe AEM process is running get_aem_pid if [[ -n "$AEM_PID" ]]; then break else info "Adobe AEM process NOT running yet. PLEASE CHECK startup.log" fi # Compute remaining time (( REMAINING_TIME = START_TIMEOUT - DURATION )) info "$REMAINING_TIME seconds remaining" # Wait ... "$SLEEP" $CHECK_DELAY &>/dev/null # Update duration (( DURATION = $("$DATE" -u '+%s' 2>/dev/null) - START_TIME )) done # Check for timeout if (( DURATION >= START_TIMEOUT )); then # Check if Adobe AEM process is running get_aem_pid if [[ -n "$AEM_PID" ]]; then crit \ "Adobe AEM process failed to start within $START_TIMEOUT seconds" "$("$TAIL" "$AEM_BASE_DIR/logs/startup.log" 2>/dev/null)" else crit \ "Adobe AEM process NOT started within $START_TIMEOUT seconds. PLEASE CHECK startup.log" "$("$TAIL" "$AEM_BASE_DIR/logs/startup.log" 2>/dev/null)" fi else # Adjust start timeout (( START_TIMEOUT -= DURATION )) fi # Adobe AEM process is running echo "$AEM_PID" > "$AEM_BASE_DIR/conf/cq.pid" 2>/dev/null info "Adobe AEM process is running with PID $AEM_PID" # Wait for Apache Sling to respond info "Waiting for Apache Sling to become available" REGEX='[[:blank:]]OK$' START_TIME=$("$DATE" -u '+%s' 2>/dev/null) DURATION=0 while (( DURATION < START_TIMEOUT )); do OUTPUT="$(\ "$JAVA" \ -jar "$AEM_JAR_FILE" \ status \ -c "$AEM_BASE_DIR" \ 0</dev/null \ 2>&1 \ )" EXIT_STATUS=$? if (( EXIT_STATUS == 0 )); then # Check for regular expression in output if [[ "$OUTPUT" =~ $REGEX ]]; then # Apache Sling responded properly break fi fi # Compute remaining time (( REMAINING_TIME = START_TIMEOUT - DURATION )) if [[ -z "$OUTPUT" ]]; then info "$REMAINING_TIME seconds remaining - Apache Sling does not respond" else get_aem_pid if [[ -z "$AEM_PID" ]]; then crit \ "Adobe AEM process is no longer running. PLEASE CHECK startup.log or error.log" "$("$TAIL" "$AEM_BASE_DIR/logs/startup.log" 2>/dev/null)" else info "$REMAINING_TIME seconds remaining - Apache Sling responds, but not as expected" fi fi # Wait ... "$SLEEP" $CHECK_DELAY &>/dev/null # Update duration (( DURATION = $("$DATE" -u '+%s' 2>/dev/null) - START_TIME )) done # Check for timeout if (( DURATION >= START_TIMEOUT )); then if (( EXIT_STATUS != 0 )); then crit "Apache Sling failed to respond within $START_TIMEOUT seconds" "$OUTPUT" else crit "Apache Sling failed to start within $START_TIMEOUT seconds" "$OUTPUT" fi else # Adjust start timeout (( START_TIMEOUT -= DURATION )) fi info "Apache Sling is available" # Wait for Apache Felix to start info "Waiting for Apache Felix to become available" URL="http://$AEM_AUTHORITY/system/console/vmstat" REGEX='System is up and running!' START_TIME=$("$DATE" -u '+%s' 2>/dev/null) DURATION=0 while (( DURATION < START_TIMEOUT )); do # Check if Apache Felix is up and running OUTPUT="$( \ "$CURL" \ --silent \ --show-error \ --connect-timeout $CONNECT_TIMEOUT \ --max-time $SOCKET_TIMEOUT \ --location \ --user "$AEM_CREDENTIALS" \ --request GET \ --url "$URL" \ 2>&1 \ )" EXIT_STATUS=$? # Extract status line from output if [[ "$OUTPUT" =~ $REGEX ]]; then break fi # Compute remaining time (( REMAINING_TIME = START_TIMEOUT - DURATION )) if [[ -z "$OUTPUT" ]]; then info "$REMAINING_TIME seconds remaining - Apache Felix does not respond" else info "$REMAINING_TIME seconds remaining - Apache Felix responds, but not as expected" fi # Wait ... "$SLEEP" $CHECK_DELAY &>/dev/null # Update duration (( DURATION = $("$DATE" -u '+%s' 2>/dev/null) - START_TIME )) done # Check for timeout if (( DURATION >= START_TIMEOUT )); then # Check for connection timeout if (( EXIT_STATUS != 0 )); then crit "Apache Felix failed to respond within $START_TIMEOUT seconds" "$OUTPUT" else crit "Apache Felix failed to start within $START_TIMEOUT seconds" "$OUTPUT" fi else # Adjust start timeout (( START_TIMEOUT -= DURATION )) fi URL="http://$AEM_AUTHORITY/system/console/bundles.json" # Filter "Installed", "Resolved" or "Starting" bundles REGEX='\{[^\}]*"state"[[:space:]]*:[[:space:]]*"(Installed|Resolved|Starting)"[^\}]+\}' START_TIME=$("$DATE" -u '+%s' 2>/dev/null) DURATION=0 while (( DURATION < START_TIMEOUT )); do # Get bundle information from Apache Felix OUTPUT="$( \ "$CURL" \ --silent \ --show-error \ --connect-timeout $CONNECT_TIMEOUT \ --max-time $SOCKET_TIMEOUT \ --location \ --user "$AEM_CREDENTIALS" \ --request GET \ --url "$URL" \ 2>&1 \ )" EXIT_STATUS=$? if (( EXIT_STATUS == 0 )); then # Extract all installed or resolved bundles from JSON output IFS="$LF" BUNDLE_ARRAY=( $( \ echo "$OUTPUT" | \ "$GREP" -Eio "$REGEX" 2>/dev/null | \ "$GREP" -Eiv "$SKIP_BUNDLE_REGEX" 2>/dev/null \ ) ) IFS="$MY_IFS" # Get number of installed or resolved bundles BUNDLE_COUNT=${#BUNDLE_ARRAY[@]} if (( BUNDLE_COUNT == 0 )); then # No more installed or resolved bundles break fi fi # Compute remaining time (( REMAINING_TIME = START_TIMEOUT - DURATION )) if (( EXIT_STATUS != 0 || BUNDLE_COUNT < 0 )); then info "$REMAINING_TIME seconds remaining - Apache Felix does not respond" else info "$REMAINING_TIME seconds remaining - Apache Felix reports that $BUNDLE_COUNT bundle(s) are not started yet" fi # Wait ... "$SLEEP" $CHECK_DELAY &>/dev/null # Update duration (( DURATION = $("$DATE" -u '+%s' 2>/dev/null) - START_TIME )) done # Check for timeout if (( DURATION >= START_TIMEOUT )); then # Check for connection timeout if (( EXIT_STATUS != 0 )); then crit "Apache Felix failed to respond within $START_TIMEOUT seconds" "$OUTPUT" else crit "Apache Felix failed to start $BUNDLE_COUNT bundle(s) within $START_TIMEOUT seconds" fi else # Adjust start timeout (( START_TIMEOUT -= DURATION )) fi info "Apache Felix is available" # Wait for Adobe CRX to start info "Waiting for Adobe CRX to become available" URL="http://$AEM_AUTHORITY/crx/packmgr/service.jsp?cmd=ls" REGEX='<status[[:space:]]+code="200"' START_TIME=$("$DATE" -u '+%s' 2>/dev/null) DURATION=0 while (( DURATION < START_TIMEOUT )); do # Check if Adobe CRX is responsive OUTPUT="$( \ "$CURL" \ --silent \ --show-error \ --connect-timeout $CONNECT_TIMEOUT \ --max-time $SOCKET_TIMEOUT \ --location \ --user "$AEM_CREDENTIALS" \ --request GET \ --url "$URL" \ 2>&1 \ )" EXIT_STATUS=$? if (( EXIT_STATUS == 0 )); then # Check for regular expression in output if [[ "$OUTPUT" =~ $REGEX ]]; then # Adobe CRX responded properly break fi fi # Compute remaining time (( REMAINING_TIME = START_TIMEOUT - DURATION )) info "$REMAINING_TIME seconds remaining" # Wait ... "$SLEEP" $CHECK_DELAY &>/dev/null # Update duration (( DURATION = $("$DATE" -u '+%s' 2>/dev/null) - START_TIME )) done # Check for timeout if (( DURATION >= START_TIMEOUT )); then if (( EXIT_STATUS != 0 )); then crit "Adobe CRX failed to respond within $START_TIMEOUT seconds" "$OUTPUT" else crit "Adobe CRX failed to start within $START_TIMEOUT seconds" "$OUTPUT" fi else # Adjust start timeout (( START_TIMEOUT -= DURATION )) fi info "Adobe CRX is available" # Wait for Adobe WCM to start info "Waiting for Adobe WCM to become available" URL="http://$AEM_AUTHORITY/libs/cq/core/content/welcome.html" REGEX='Welcome,[[:space:]]+Administrator\.' START_TIME=$("$DATE" -u '+%s' 2>/dev/null) DURATION=0 while (( DURATION < START_TIMEOUT )); do # Check if Adobe WCM is responsive OUTPUT="$( \ "$CURL" \ --silent \ --show-error \ --connect-timeout $CONNECT_TIMEOUT \ --max-time $SOCKET_TIMEOUT \ --location \ --user "$AEM_CREDENTIALS" \ --request GET \ --url "$URL" \ 2>&1 \ )" EXIT_STATUS=$? if (( EXIT_STATUS == 0 )); then # Check for regular expression in output if [[ "$OUTPUT" =~ $REGEX ]]; then # Adobe WCM responded properly break; fi fi # Compute remaining time (( REMAINING_TIME = START_TIMEOUT - DURATION )) info "$REMAINING_TIME seconds remaining" # Wait ... "$SLEEP" $CHECK_DELAY &>/dev/null # Update duration (( DURATION = $("$DATE" -u '+%s' 2>/dev/null) - START_TIME )) done # Check for timeout if (( DURATION >= START_TIMEOUT )); then if (( EXIT_STATUS != 0 )); then crit "Adobe WCM failed to respond within $START_TIMEOUT seconds" "$OUTPUT" else crit "Adobe WCM failed to start within $START_TIMEOUT seconds" "$OUTPUT" fi fi info "Adobe WCM is available" } #-------------------------------------------------------------------------- # NAME # stop - stop service # SYNOPSIS # stop # # DESCRIPTION # Stops the AEM service #-------------------------------------------------------------------------- stop() { local -i START_TIME local -i DURATION local -i REMAINING_TIME # Stop Adobe AEM info "Stopping Adobe AEM process" cd "$AEM_HOME" ( "$ENV" \ -i \ "LANG=$JAVA_LANG" \ "TZ=$JAVA_TZ" \ "JAVA_HOME=$JAVA_HOME" \ "$JAVA" \ -Djava.awt.headless=true \ -Dfile.encoding=UTF8 \ -jar "$AEM_JAR_FILE" \ stop \ -c "$AEM_BASE_DIR" \ 0</dev/null \ 1>"$AEM_BASE_DIR/logs/shutdown.log" \ 2>&1 ) & START_TIME=$("$DATE" -u '+%s' 2>/dev/null) DURATION=0 while (( DURATION < STOP_TIMEOUT )); do # Check if Adobe AEM process stopped kill -0 $AEM_PID &>/dev/null if (( $? != 0 )); then # Adobe AEM stopped break fi # Compute remaining time (( REMAINING_TIME = STOP_TIMEOUT - DURATION )) info "$REMAINING_TIME seconds remaining" # Wait ... "$SLEEP" $CHECK_DELAY &>/dev/null # Update duration (( DURATION = $("$DATE" -u '+%s' 2>/dev/null) - START_TIME )) done if (( DURATION >= STOP_TIMEOUT )); then err "Adobe AEM process failed to stop" # Stop Adobe AEM process with SIGTERM info "Sending TERM signal to Adobe AEM process running with PID $AEM_PID" kill -15 $AEM_PID &>/dev/null # Wait for Adobe AEM to stop info "Waiting for Adobe AEM process to stop" START_TIME=$("$DATE" -u '+%s' 2>/dev/null) DURATION=0 while (( DURATION < STOP_TIMEOUT )); do # Check if Adobe AEM process stopped kill -0 $AEM_PID &>/dev/null if (( $? != 0 )); then # Adobe AEM stopped break fi # Compute remaining time (( REMAINING_TIME = STOP_TIMEOUT - DURATION )) info "$REMAINING_TIME seconds remaining" # Wait ... "$SLEEP" $CHECK_DELAY &>/dev/null # Update duration (( DURATION = $("$DATE" -u '+%s' 2>/dev/null) - START_TIME )) done if (( DURATION >= STOP_TIMEOUT )); then err "Adobe AEM process failed to stop" # Stop Adobe AEM process with SIGKILL info "Sending KILL signal to Adobe AEM process running with PID $AEM_PID" kill -9 $AEM_PID &>/dev/null fi fi # Adobe AEM process stopped "$RM" -f "$AEM_BASE_DIR/conf/cq.pid" &>/dev/null } #-------------------------------------------------------------------------- # NAME # status - get service status # # SYNOPSIS # service # # DESCRIPTION # Performs elementary functional test. #-------------------------------------------------------------------------- status() { local URL local REGEX local OUTPUT local -a BUNDLE_ARRAY local -i BUNDLE_COUNT local -i RESULT=0 # Get status information from Apache Sling cd "$AEM_HOME" OUTPUT="$( \ "$JAVA" \ -jar "$AEM_JAR_FILE" \ status \ -c "$AEM_BASE_DIR" \ 2>&1 \ )" if (( $? == 0 )); then # Check for regular expression in output REGEX='[[:blank:]]OK$' if [[ "$OUTPUT" =~ $REGEX ]]; then info "Apache Sling is available" else err "Apache Sling did not respond as expected" "$OUTPUT" RESULT=1 fi else err "Apache Sling failed to respond" "$OUTPUT" RESULT=1 fi # Check if Apache Felix is up and running URL="http://$AEM_AUTHORITY/system/console/vmstat" OUTPUT="$( \ "$CURL" \ --silent \ --show-error \ --connect-timeout $CONNECT_TIMEOUT \ --max-time $SOCKET_TIMEOUT \ --location \ --user "$AEM_CREDENTIALS" \ --request GET \ --url "$URL" \ 2>&1 \ )" EXIT_STATUS=$? # Extract status line from output REGEX='System is up and running!' if [[ "$OUTPUT" =~ $REGEX ]]; then # Get bundle information from Apache Felix URL="http://$AEM_AUTHORITY/system/console/bundles.json" OUTPUT="$( \ "$CURL" \ --silent \ --show-error \ --connect-timeout $CONNECT_TIMEOUT \ --max-time $SOCKET_TIMEOUT \ --location \ --user "$AEM_CREDENTIALS" \ --request GET \ --url "$URL" \ 2>&1 \ )" EXIT_STATUS=$? if (( EXIT_STATUS == 0 )); then # Extract all installed or resolved bundles from JSON output REGEX='\{[^\}]*"state"[[:space:]]*:[[:space:]]*"(Installed|Resolved|Starting)"[^\}]+\}' IFS="$LF" BUNDLE_ARRAY=( $( \ echo "$OUTPUT" | \ "$GREP" -Eio "$REGEX" 2>/dev/null | \ "$GREP" -Eiv "$SKIP_BUNDLE_REGEX" 2>/dev/null \ ) ) IFS="$MY_IFS" # Get number of installed or resolved bundles BUNDLE_COUNT=${#BUNDLE_ARRAY[@]} if (( BUNDLE_COUNT == 0 )); then info "Apache Felix is available" else err "Apache Felix failed to start $BUNDLE_COUNT bundles" RESULT=1 fi else err "Apache Felix failed to respond" "$OUTPUT" RESULT=1 fi else err "Apache Felix failed to start" "$OUTPUT" RESULT=1 fi # Check if Adobe CRX is responsive URL="http://$AEM_AUTHORITY/crx/packmgr/service.jsp?cmd=ls" REGEX='<status[[:space:]]+code="200"' OUTPUT="$( \ "$CURL" \ --silent \ --show-error \ --connect-timeout $CONNECT_TIMEOUT \ --max-time $SOCKET_TIMEOUT \ --location \ --user "$AEM_CREDENTIALS" \ --request GET \ --url "$URL" \ 2>&1 \ )" EXIT_STATUS=$? if (( EXIT_STATUS == 0 )); then # Check for regular expression in output if [[ "$OUTPUT" =~ $REGEX ]]; then info "Adobe CRX is available" else err "Adobe CRX did not respond as expected" "$OUTPUT" RESULT=1 fi else err "Adobe CRX failed to respond" "$OUTPUT" RESULT=1 fi # Check if Adobe WCM is responsive URL="http://$AEM_AUTHORITY/libs/cq/core/content/welcome.html" REGEX='Welcome,[[:space:]]+Administrator\.' OUTPUT="$( \ "$CURL" \ --silent \ --show-error \ --connect-timeout $CONNECT_TIMEOUT \ --max-time $SOCKET_TIMEOUT \ --location \ --user "$AEM_CREDENTIALS" \ --request GET \ --url "$URL" \ 2>&1 \ )" EXIT_STATUS=$? if (( EXIT_STATUS == 0 )); then # Check for regular expression in output if [[ "$OUTPUT" =~ $REGEX ]]; then info "Adobe WCM is available" else err "Adobe WCM did not respond as expected" "$OUTPUT" RESULT=1 fi else err "Adobe WCM failed to respond" "$OUTPUT" RESULT=1 fi return $RESULT } #-------------------------------------------------------------------------- # NAME # sweep - Run memory garbage collection # # SYNOPSIS # sweep # # DESCRIPTION # Runs a memory garbage collection. #-------------------------------------------------------------------------- sweep() { local URL local OUTPUT local -i EXIT_STATUS # Run memory garbage collection URL="http://$AEM_AUTHORITY/system/console/memoryusage" OUTPUT="$( \ "$CURL" \ --silent \ --show-error \ --connect-timeout $CONNECT_TIMEOUT \ --max-time $SOCKET_TIMEOUT \ --location \ --user "$AEM_CREDENTIALS" \ --request POST \ --url "$URL" \ --data 'command=gc' \ 2>&1 \ )" EXIT_STATUS=$? if (( EXIT_STATUS != 0 )); then crit "\"$CURL\" returned error code $EXIT_STATUS" "$OUTPUT" fi } #-------------------------------------------------------------------------- # Main program #-------------------------------------------------------------------------- # Source configuration load_config # Check configuration check_config if [ "$2" = "first" ];then (( START_TIMEOUT = START_TIMEOUT * 10 )) info "Set START_TIMEOUT to $START_TIMEOUT due to first start" fi # Analyze command-line argument case "$1" in 'start') # Lock this script lock info "Starting Adobe AEM service" # Check if Adobe AEM process is already running get_aem_pid if [[ -z "$AEM_PID" ]]; then # Rotate log directories rotate_log_dirs # Start Adobe AEM service start fi info "Adobe AEM service started successfully" # Unlock this script unlock ;; 'stop') # Lock this script lock info "Stopping Adobe AEM service" # Check if Adobe AEM process is running get_aem_pid if [[ -n "$AEM_PID" ]]; then # Stop Adobe AEM service stop fi info "Adobe AEM service stopped successfully" # Unlock this script unlock ;; 'restart') # Lock this script lock info "Restarting Adobe AEM service" # Check if Adobe AEM process is already running get_aem_pid if [[ -n "$AEM_PID" ]]; then # Stop Adobe AEM service stop fi # Rotate log directories rotate_log_dirs # Start Adobe AEM service start info "Adobe AEM service restarted successfully" # Unlock this script unlock ;; 'status') info "Checking status of Adobe AEM service" # Check if Adobe AEM process is running get_aem_pid if [[ -z "$AEM_PID" ]]; then err "Adobe AEM service is not available" exit 3 else info "Adobe AEM is running with PID $AEM_PID" # Check if Adobe AEM service is available status if (( $? == 0 )); then info "Adobe AEM service is available" else err "Adobe AEM service is not available" exit 3 fi fi ;; 'activate') # Lock this script lock # Check if Adobe AEM process is running get_aem_pid if [[ -z "$AEM_PID" ]]; then crit "Adobe AEM service is not running" fi info "Activating all installed or resolved Apache Felix bundles" activate # Unlock this script unlock ;; 'sweep') # Lock this script lock # Check if Adobe AEM process is running get_aem_pid if [[ -z "$AEM_PID" ]]; then crit "Adobe AEM service is not running" fi info "Running memory garbage collection" # Run memory garbage collection sweep info "Memory garbage collection complete" # Unlock this script unlock ;; 'help') usage 0 ;; 'version') version ;; *) usage ;; esac exit 0