-
-
Save tnebe/c4c430c13fd636b78117370f2134dacb to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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 | |
# Apache License V2 | |
# All rights reserved. | |
# | |
# AUTHORS | |
# Fred Ide | |
# | |
# 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 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment