#!/bin/bash ### ### Copyright 2019, 2025, Instana Inc. ### ### Licensed under the Apache License, Version 2.0 (the "License"); ### you may not use this file except in compliance with the License. ### You may obtain a copy of the License at ### ### http://www.apache.org/licenses/LICENSE-2.0 ### ### Unless required by applicable law or agreed to in writing, software ### distributed under the License is distributed on an "AS IS" BASIS, ### WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ### See the License for the specific language governing permissions and ### limitations under the License. ### set -o pipefail AGENT_DIR="/opt/instana/agent" AGENT_DIR_ZOS="${PWD}/instana-agent" AGENT_DIR_ZOS_OLD="${PWD}/instana-agent-old" # AIX, Darwin, Linux, SunOS OS=$(uname -s) MACHINE="" FAMILY="unknown" INIT="sysv" PKG_URI=packages.instana.io AGENT_TYPE="dynamic" OPEN_J9="false" PROMPT=true ENABLE_SERVICE=false RESTART=false LOCATION= ENDPOINT="" MODE="apm" GIT_REPO= GIT_BRANCH= GIT_USERNAME= GIT_PASSWORD= INSTANA_AGENT_SYSTEMD_TYPE=simple # Logging configuration — can be overridden via environment variables or CLI flags. # INSTANA_AGENT_ONE_LINER_LOG_LEVEL: TRACE | DEBUG | INFO | WARN | ERROR (default: INFO) # INSTANA_AGENT_ONE_LINER_LOG_TO_CONSOLE: true | false (default: true) # INSTANA_AGENT_ONE_LINER_LOG_TO_FILE: path to log file (default: empty, no file logging) # INSTANA_AGENT_ONE_LINER_LOG_CREDENTIALS: true | false (default: false) # When false (default) credentials and keys are masked as '****' in log output. # Set to true (or pass --log-credentials) to include actual values — use only in # controlled/trusted environments where the log output cannot be observed by others. INSTANA_AGENT_ONE_LINER_LOG_LEVEL="${INSTANA_AGENT_ONE_LINER_LOG_LEVEL:-INFO}" INSTANA_AGENT_ONE_LINER_LOG_TO_CONSOLE="${INSTANA_AGENT_ONE_LINER_LOG_TO_CONSOLE:-true}" INSTANA_AGENT_ONE_LINER_LOG_TO_FILE="${INSTANA_AGENT_ONE_LINER_LOG_TO_FILE:-}" INSTANA_AGENT_ONE_LINER_LOG_CREDENTIALS="${INSTANA_AGENT_ONE_LINER_LOG_CREDENTIALS:-false}" INSTANA_AGENT_KEY="$INSTANA_AGENT_KEY" INSTANA_DOWNLOAD_KEY="$INSTANA_DOWNLOAD_KEY" INSTANA_AGENT_HOST="$INSTANA_AGENT_HOST" INSTANA_AGENT_PORT="${INSTANA_AGENT_PORT:-443}" INSTANA_AGENT_NON_ROOT="$INSTANA_AGENT_NON_ROOT" INSTANA_AGENT_USER="$INSTANA_AGENT_USER" INSTANA_AGENT_GROUP="$INSTANA_AGENT_GROUP" # Explicit opt-out of non-root for Agent 2.0 (set by --run-as-root flag). # When true, INSTANA_AGENT_NON_ROOT is forced to "false" before export. INSTANA_AGENT_RUN_AS_ROOT=false INSTANA_AWS_REGION_CONFIG="" gpg_check=1 function exists { if which "$1" >/dev/null 2>&1; then return 0 else return 1 fi } download_command='none' function download_to_stdout { case "${download_command}" in 'curl') download_to_stdout_curl $@ ;; 'wget') download_to_stdout_wget $@ ;; *) log_error "Unknown download command '${download_command}'" exit 1; esac } function download_to_stdout_curl { local request_method="" if [[ "$1" == "GET" || "$1" == "POST" || "$1" == "PUT" ]]; then request_method="-X ${1}" shift fi local url="$1" local header_parameter if [[ "$2" == "-H" ]]; then header_parameter="-H ${3}" shift 2 fi # Auth is passed in curl format: : local authentication="$2" local authentication_parameters # Connection timeout, default 2 secs local connect_timeout="${3:-2}" if [ -n "${authentication}" ]; then authentication_parameters="-u ${authentication}" fi local masked_auth="" if [ -n "${authentication}" ]; then local _auth_user _auth_user=$(awk -F ':' '{print $1}' <<< "${authentication}") masked_auth="${_auth_user}:$(_mask_key "$(awk -F ':' '{print $2}' <<< "${authentication}")")" fi log_trace "curl ${request_method} ${header_parameter:+$header_parameter }${masked_auth:+-u $masked_auth }${url} (timeout: ${connect_timeout}s)" curl -s --fail --connect-timeout "${connect_timeout}" ${request_method} ${header_parameter} ${authentication_parameters} "${url}" local retval=$? log_trace "curl exit: ${retval} url: ${url}" return ${retval} } function download_to_stdout_wget { local request_method="" if [[ "$1" == "GET" || "$1" == "POST" || "$1" == "PUT" ]]; then request_method="--method=${1}" shift fi local url="$1" local header_parameter if [[ "$2" == "-H" ]]; then header_parameter="--header ${3}" shift 2 fi # Auth is passed in curl format: : local authentication="$2" local authentication_parameters # Connection timeout, default 2 secs local connect_timeout="${3:-2}" if [ -n "${authentication}" ]; then local username; username=$(awk -F ':' '{ print $1}' <<< "${authentication}") local password password=$(awk -F ':' '{ print $2}' <<< "${authentication}") authentication_parameters="--auth-no-challenge --http-user=${username} --http-password=${password}" fi local masked_auth="" if [ -n "${authentication}" ]; then local _wuser _wuser=$(awk -F ':' '{print $1}' <<< "${authentication}") masked_auth="--http-user=${_wuser} --http-password=$(_mask_key "$(awk -F ':' '{print $2}' <<< "${authentication}")")" fi log_trace "wget ${request_method} ${header_parameter:+$header_parameter }${masked_auth:+$masked_auth }${url} (timeout: ${connect_timeout}s)" wget --timeout="${connect_timeout}" ${request_method} ${header_parameter} -qO- ${authentication_parameters} "${url}" local retval=$? log_trace "wget exit: ${retval} url: ${url}" return ${retval} } # Ensure a log file and its parent directory exist before writing to it. function ensure_file_exists { local file="$1" local dir dir="$(dirname "$file")" if [ ! -d "$dir" ]; then mkdir -p "$dir" fi if [ ! -f "$file" ]; then touch "$file" fi } # Map a level name to a numeric priority (case-insensitive). function log_level_value { case "${1^^}" in TRACE) echo 0 ;; DEBUG) echo 1 ;; INFO) echo 2 ;; WARN) echo 3 ;; ERROR) echo 4 ;; *) echo 2 ;; # Default to INFO if unknown esac } # Base structured logging function. # Usage: log_message LEVEL CALLER_FUNC MESSAGE... function log_message { local level="$1" local func_name="$2" shift 2 local message="$*" local current_level_value current_level_value=$(log_level_value "$INSTANA_AGENT_ONE_LINER_LOG_LEVEL") local message_level_value message_level_value=$(log_level_value "$level") if [ "$message_level_value" -ge "$current_level_value" ]; then local timestamp timestamp=$(date '+%Y-%m-%dT%H:%M:%S%z') local log_entry log_entry=$(printf '%-20.28s | %-5.5s | %-22.22s | %s\n' "$timestamp" "$level" "$func_name" "$message") if [ "$INSTANA_AGENT_ONE_LINER_LOG_TO_CONSOLE" = "true" ]; then echo "$log_entry" >&2 fi if [ -n "$INSTANA_AGENT_ONE_LINER_LOG_TO_FILE" ]; then ensure_file_exists "$INSTANA_AGENT_ONE_LINER_LOG_TO_FILE" echo "$log_entry" >> "$INSTANA_AGENT_ONE_LINER_LOG_TO_FILE" fi fi } function log_trace { log_message "TRACE" "${FUNCNAME[1]}" "$@" } function log_debug { log_message "DEBUG" "${FUNCNAME[1]}" "$@" } function log_info { log_message "INFO" "${FUNCNAME[1]}" "$@" } function log_warn { log_message "WARN" "${FUNCNAME[1]}" "$@" } function log_error { log_message "ERROR" "${FUNCNAME[1]}" "$@" } function log_error_and_die { log_message "ERROR" "${FUNCNAME[1]}" "$@" exit 1 } # Return the value masked as '****' unless INSTANA_AGENT_ONE_LINER_LOG_CREDENTIALS=true. # Usage: $(_mask_key "$some_secret") function _mask_key { if [ "${INSTANA_AGENT_ONE_LINER_LOG_CREDENTIALS}" = "true" ]; then echo "$1" else echo "****" fi } # warn_flag_env_conflict # # Called inside a flag case branch before the variable is overwritten. # At that point the variable still holds the value read from the environment # at script startup (e.g. INSTANA_AGENT_KEY="$INSTANA_AGENT_KEY" at line 46). # # Decision table: # env var not set (empty) -> silent, return immediately # env var set, same as flag value -> log_info: both inputs agree # env var set, differs from flag value -> log_warn: flag overrides env var function warn_flag_env_conflict() { local flag_name="$1" local env_value="$2" local flag_value="$3" if [[ -z "$env_value" ]]; then return fi if [[ "$env_value" == "$flag_value" ]]; then log_info "Flag $flag_name and env var are both set to the same value." else log_warn "Flag $flag_name overrides env var (env: '$env_value', flag: '$flag_value'). Flag value will be used." fi } function receive_confirmation() { read -r -p "$1 [y/N] " response if [[ ! $response =~ ^([yY][eE][sS]|[yY])$ ]]; then return 1 fi return 0 } function check_zOS_prerequisites() { if command -v gzip > /dev/null && command -v pax > /dev/null; then log_info 'pax and gzip are available on the system' else log_error 'This script requires pax and gzip to be installed on this system. Aborting installation.' exit 1 fi } function check_user_privilege() { if [ "$(id -u)" -eq 0 ]; then echo "You are root!" else echo "You are not root Aborting Agent Installation. Switch to the user which has root privilege and retry" exit 1 fi } function check_prerequisites() { if exists curl; then download_command='curl' elif exists wget; then download_command='wget' else log_error 'This script requires either curl or wget to be installed on this system. Aborting installation.' exit 1 fi log_debug "Download command: ${download_command}" if ! which gpg > /dev/null 2>&1; then log_warn 'The "gpg" program is not installed on this system: the verification of the Instana agent packages cannot be performed.' if [ $PROMPT = true ]; then if ! receive_confirmation 'Do you want to continue?'; then exit 1 fi fi log_warn 'The verification of the Instana agent packages will be skipped.' gpg_check=0 else log_debug "gpg is available; package signature verification enabled" fi } function check_download_key() { # Retry the download-key check a few times with increasing timeout as this appeared to be unreliable at times # Timeout is identified by exit code 28 for curl, and 4 for wget. local check_url="https://${PKG_URI}/agent/generic/x86_64/repodata/repomd.xml" log_debug "Verifying download key against: ${check_url} (download key: $(_mask_key "${INSTANA_DOWNLOAD_KEY}"))" local retval local n=1 while [ ${n} -le 5 ] do # Use an increasing timeout of "n*3" seconds log_trace "Download key check attempt ${n}/5 (timeout: $((n * 3))s)" download_to_stdout "${check_url}" "_:${INSTANA_DOWNLOAD_KEY}" $((n * 3)) > /dev/null retval=$? log_trace "Download key check attempt ${n}/5 exit code: ${retval}" if [ ${retval} -ne 28 ] && [ ${retval} -ne 4 ] then break fi n=$((n + 1)) done if [ ${retval} -eq 28 ] || [ ${retval} -eq 4 ]; then log_error "Verifying the Instana agent download key timed-out, please try again." exit 1 elif [ ${retval} -ne 0 ]; then log_error "The Instana agent download key provided seems to be invalid, please check the agent key and try again." exit 1 fi log_debug "Download key verified successfully" } function detect_family() { if which apt-get &> /dev/null; then FAMILY="apt" log_debug "Detected package family: apt" return 0 fi if type dnf &>/dev/null then FAMILY="dnf" log_debug "Detected package family: dnf" return 0 fi if type yum &>/dev/null then FAMILY="yum" log_debug "Detected package family: yum" return 0 fi if which zypper &> /dev/null; then FAMILY="zypper" log_debug "Detected package family: zypper" return 0 fi if [ "$OS" = "OS/390" ]; then FAMILY="zOS" log_debug "Detected package family: zOS" return 0 fi log_warn "Could not detect package family (OS: ${OS})" } function detect_init() { if ls -l /sbin/init | grep systemd &> /dev/null; then INIT="systemd" log_debug "Detected init system: systemd" return 0 fi if /sbin/init --version | grep upstart &> /dev/null; then INIT="upstart" log_debug "Detected init system: upstart" return 0 fi log_debug "Could not detect init system; defaulting to: ${INIT}" } function resolve_non_root() { # Non-root is Linux/systemd only. if [ "$OS" = "Linux" ]; then # Mirror postinst implicit-enable: both user AND group set implies non-root. # Applied once after full parsing — covers flags, env vars, or a mix. if [[ -n "$INSTANA_AGENT_USER" && -n "$INSTANA_AGENT_GROUP" ]]; then INSTANA_AGENT_NON_ROOT=true log_debug "Non-root mode implicitly enabled: both --non-root-user (${INSTANA_AGENT_USER}) and --non-root-group (${INSTANA_AGENT_GROUP}) are set." fi # --run-as-root and --run-as-non-root are mutually exclusive. if [ "$INSTANA_AGENT_RUN_AS_ROOT" = "true" ] && [ "$INSTANA_AGENT_NON_ROOT" = "true" ]; then log_error "Conflicting flags: --run-as-root and --run-as-non-root cannot be used together." exit 1 fi # --run-as-root forces INSTANA_AGENT_NON_ROOT=false so the pkg-scripts # skip non-root setup regardless of the agent version default. if [ "$INSTANA_AGENT_RUN_AS_ROOT" = "true" ]; then log_info "Flag --run-as-root set: agent will be installed as root." INSTANA_AGENT_NON_ROOT=false fi if [[ "$INSTANA_AGENT_NON_ROOT" = "true" && "$INIT" != "systemd" ]]; then log_error "Non-root installation requires systemd. Unset non root mode and rerun." exit 1 fi else # Non-root flags are Linux-only. Warn and continue as root. if [[ -n "$INSTANA_AGENT_NON_ROOT" || -n "$INSTANA_AGENT_USER" || -n "$INSTANA_AGENT_GROUP" ]]; then log_warn "Non-root flags (--run-as-non-root, --non-root-user, --non-root-group) are only supported on Linux. Installing as root." fi fi } function detect_machine() { if [ "$OS" = "AIX" ]; then MACHINE=$(uname -p) elif [ "$OS" = "Darwin" ]; then MACHINE=$(uname -m) elif [ "$OS" = "Linux" ]; then MACHINE=$(uname -m) elif [ "$OS" = "SunOS" ]; then MACHINE=$(uname -m) elif [ "$OS" = "OS/390" ]; then MACHINE=$(uname -s) else log_info "Could not detect machine for OS: $OS" MACHINE="unknown" fi log_debug "Detected machine architecture: ${MACHINE} (OS: ${OS})" } function get_endpoint() { if [ -n "${ENDPOINT}" ]; then local split=(${ENDPOINT//:/ }) INSTANA_AGENT_HOST="${split[0]}" INSTANA_AGENT_PORT="${split[1]}" log_debug "Endpoint set from --endpoint flag: host=${INSTANA_AGENT_HOST} port=${INSTANA_AGENT_PORT}" elif [[ "${LOCATION}" == "eu" ]]; then INSTANA_AGENT_HOST="saas-eu-west-1.instana.io" log_debug "Endpoint resolved from location 'eu': host=${INSTANA_AGENT_HOST}" elif [[ "${LOCATION}" == "us" ]]; then INSTANA_AGENT_HOST="saas-us-west-2.instana.io" log_debug "Endpoint resolved from location 'us': host=${INSTANA_AGENT_HOST}" elif [[ "${LOCATION}" == "red" ]]; then INSTANA_AGENT_HOST="ingress-red-saas.instana.io" log_debug "Endpoint resolved from location 'red': host=${INSTANA_AGENT_HOST}" elif [[ "${LOCATION}" == "blue" ]]; then INSTANA_AGENT_HOST="ingress-blue-saas.instana.io" log_debug "Endpoint resolved from location 'blue': host=${INSTANA_AGENT_HOST}" elif [[ "${LOCATION}" == "green" ]]; then INSTANA_AGENT_HOST="ingress-green-saas.instana.io" log_debug "Endpoint resolved from location 'green': host=${INSTANA_AGENT_HOST}" else log_debug "Endpoint from env/flags: host=${INSTANA_AGENT_HOST} port=${INSTANA_AGENT_PORT}" fi } function use_internal_packages () { if [ "${USE_INTERNAL_PACKAGES}" = 'true' ]; then local MVN_CFG_FILE='/opt/instana/agent/etc/org.ops4j.pax.url.mvn.cfg' log_info "Configuring internal repository usage in ${MVN_CFG_FILE} file" sed -i 's/features-public@id=features/features-internal@id=features/' "${MVN_CFG_FILE}" fi } function setup_agent() { local gpg_uri="https://${PKG_URI}/Instana.gpg" case "$FAMILY" in 'apt') log_info "Setting up Instana APT repository" # For whatever reason debian uses rando arch names instead of what is reported by uname local arch="$MACHINE" case "${MACHINE}" in 'x86_64') arch='amd64' ;; 'aarch64') arch='arm64' ;; 'ppc64le') arch='ppc64el' ;; esac local INSTANA_AUTH_CONF_FILE='/etc/apt/auth.conf.d/instana-packages.conf' if [ -d "$(dirname "${INSTANA_AUTH_CONF_FILE}")" ]; then # We should use /etc/apt/auth.conf.d rather than hard-coding the credentials in the `apt url`. if ! echo "machine ${PKG_URI} login _ password ${INSTANA_DOWNLOAD_KEY} " > "${INSTANA_AUTH_CONF_FILE}"; then log_error "Cannot create the ${INSTANA_AUTH_CONF_FILE} file to configure authentication for the ${PKG_URI} repository" exit 1 fi log_info "Authentication for the ${PKG_URI} repository has been added to apt via the ${INSTANA_AUTH_CONF_FILE} file" local apt_uri="deb [arch=${arch} signed-by=/usr/share/keyrings/instana-agent.gpg] https://${PKG_URI}/agent/deb generic main" else local apt_uri="deb [arch=${arch} signed-by=/usr/share/keyrings/instana-agent.gpg] https://_:${INSTANA_DOWNLOAD_KEY}@${PKG_URI}/agent/deb generic main" fi if ! echo "$apt_uri" > /etc/apt/sources.list.d/instana-agent.list; then log_error "Instana APT repository setup failed" exit 1 fi if [ "${gpg_check}" -eq 1 ]; then log_info "Importing Instana GPG key" # Retry the gpg key download a few times as the network connection appear to be unreliable in certain environments # Timeout is identified by exit code 28 for curl, and 4 for wget. local retval local n=1 while [ ${n} -le 5 ] do log_trace "GPG key download attempt ${n}/5: ${gpg_uri}" download_to_stdout "$gpg_uri" > Instana.gpg retval=$? log_trace "GPG key download attempt ${n}/5 exit code: ${retval}" if [ ${retval} -ne 28 ] && [ ${retval} -ne 4 ] then break fi n=$((n + 1)) done if [ ${retval} -eq 28 ] || [ ${retval} -eq 4 ]; then log_error "Downloading the Instana GPG key timed-out, please try again." exit 1 elif [ ${retval} -ne 0 ]; then log_error "Downloading the Instana GPG key failed, please try again." exit 1 fi # Modern approach: Use signed-by with /usr/share/keyrings/ # This method works on Debian 9+, Ubuntu 16.04+ and is the recommended approach # It replaces the deprecated apt-key command and works with Debian 13+ log_info "Installing GPG key to /usr/share/keyrings/instana-agent.gpg" # Create keyrings directory if it doesn't exist if [ ! -d /usr/share/keyrings ]; then if ! mkdir -p /usr/share/keyrings; then log_error "Failed to create /usr/share/keyrings directory" rm -f Instana.gpg exit 1 fi fi # Convert ASCII-armored key to binary format and install if ! gpg --dearmor < Instana.gpg > /usr/share/keyrings/instana-agent.gpg 2>/dev/null; then log_error "Instana GPG key import failed" rm -f Instana.gpg exit 1 fi # Set proper permissions chmod 644 /usr/share/keyrings/instana-agent.gpg log_info "GPG key successfully installed" rm -f Instana.gpg else AUTHENTICATION_PARAM='--allow-unauthenticated -o Acquire::AllowInsecureRepositories=true' fi log_info "Updating apt metadata" if ! apt-get ${AUTHENTICATION_PARAM} update -o Dir::Etc::sourcelist="sources.list.d/instana-agent.list" -o Dir::Etc::sourceparts="-" -o APT::Get::List-Cleanup="0" > /dev/null; then log_error "APT repository metadata update failed" exit 1 fi log_info "Installing Instana agent" # retry download 5 times, add connection timeouts for downloads if ! apt-get ${AUTHENTICATION_PARAM} -o Acquire::Retries=5 -o Acquire::http::Timeout=60 -o Acquire::ftp::Timeout=60 -o DPkg::lock::Timeout=120 install -y instana-agent-${AGENT_TYPE} > /dev/null; then log_error "Instana agent package install failed" exit 1 fi use_internal_packages ;; 'dnf') log_info "Setting up Instana RPM repository" local yum_repo read -r -d '' yum_repo < /etc/yum.repos.d/Instana-Agent.repo; then log_error "Instana YUM repository setup failed" exit 1 fi log_info "Updating YUM metadata" if ! dnf makecache -y > /dev/null 2>&1; then log_error "YUM repository metadata update failed" exit 1 fi log_info "Installing Instana agent" if ! dnf install -y instana-agent-$AGENT_TYPE > /dev/null; then log_error "Instana agent package install failed" exit 1 fi use_internal_packages ;; 'yum') log_info "Setting up Instana YUM repository" local yum_repo read -r -d '' yum_repo < /etc/yum.repos.d/Instana-Agent.repo; then log_error "Instana YUM repository setup failed" exit 1 fi log_info "Updating YUM metadata" if ! yum makecache -y fast > /dev/null 2>&1; then log_error "YUM repository metadata update failed" exit 1 fi log_info "Installing Instana agent" if ! yum install -y instana-agent-$AGENT_TYPE > /dev/null; then log_error "Instana agent package install failed" exit 1 fi use_internal_packages ;; 'zypper') log_info "Setting up Instana zypper repository" local zypp_repo read -r -d '' zypp_repo < /etc/zypp/repos.d/Instana-Agent.repo; then log_error "Instana zypper repository setup failed" exit 1 fi if [ "${gpg_check}" -eq 1 ]; then log_info "Importing Instana GPG key" if ! rpm --import "$gpg_uri"; then log_error "Instana GPG key import failed" exit 1 fi fi log_info "Updating zypper metadata" if ! zypper -n refresh Instana > /dev/null 2>&1; then log_error "zypper repository metadata update failed" exit 1 fi log_info "Installing Instana agent" if ! zypper -n install instana-agent-$AGENT_TYPE > /dev/null; then log_error "Instana agent package install failed" exit 1 fi use_internal_packages ;; 'zOS') log_info "Cheking on Prereq. for Installing Instana agent" check_user_privilege check_zOS_prerequisites check_zOS_server_update_prerequisites check_existing_instana_agent check_existing_instana_agent_process log_info "Installing Instana agent" EXPECTED_FILE="org.apache.felix.framework-*.jar" DIR="$AGENT_DIR_ZOS/system/org/apache/felix/org.apache.felix.framework/" if [ $AGENT_TYPE = "dynamic" ]; then # Get latest version from Artifactory API local _zos_version_url="https://artifact-public.instana.io/artifactory/api/search/latestVersion?repos=rel-generic-instana-virtual&g=com.instana&a=agent-assembly" log_info "Fetching latest agent version..." log_debug "Fetching version from: ${_zos_version_url} (download key: $(_mask_key "${INSTANA_DOWNLOAD_KEY}"))" AGENT_VERSION=$(curl -s -u "_:${INSTANA_DOWNLOAD_KEY}" "${_zos_version_url}") local _retval=$? log_debug "Version fetch exit code: ${_retval} version: ${AGENT_VERSION}" if [ ${_retval} -ne 0 ] || [ -z "${AGENT_VERSION}" ]; then log_error "Failed to fetch latest agent version (exit: ${_retval})" exit 1 fi log_info "Latest version: ${AGENT_VERSION}" # Download agent assembly local _zos_asm_url="https://artifact-public.instana.io/artifactory/instana-team-release-generic-virtual/com/instana/agent-assembly/${AGENT_VERSION}/agent-assembly-${AGENT_VERSION}-linux-s390x.tar.gz" log_info "Downloading agent assembly..." log_debug "Downloading from: ${_zos_asm_url}" if ! curl -# -u "_:${INSTANA_DOWNLOAD_KEY}" "${_zos_asm_url}" \ -o agent-assembly-linux-dynamic-s390x.tar.gz; then log_error "Failed to download agent assembly from ${_zos_asm_url}" exit 1 fi log_debug "Agent assembly download complete" log_info "Extracting agent assembly..." gzip -d agent-assembly-linux-dynamic-s390x.tar.gz pax -r -f agent-assembly-linux-dynamic-s390x.tar fi if [ $AGENT_TYPE = "static" ]; then # Get latest version from Artifactory API local _zos_version_url="https://artifact-public.instana.io/artifactory/api/search/latestVersion?repos=rel-generic-instana-virtual&g=com.instana&a=agent-assembly-offline" log_info "Fetching latest agent version..." log_debug "Fetching version from: ${_zos_version_url} (download key: $(_mask_key "${INSTANA_DOWNLOAD_KEY}"))" AGENT_VERSION=$(curl -s -u "_:${INSTANA_DOWNLOAD_KEY}" "${_zos_version_url}") local _retval=$? log_debug "Version fetch exit code: ${_retval} version: ${AGENT_VERSION}" if [ ${_retval} -ne 0 ] || [ -z "${AGENT_VERSION}" ]; then log_error "Failed to fetch latest agent version (exit: ${_retval})" exit 1 fi log_info "Latest version: ${AGENT_VERSION}" # Download agent assembly local _zos_asm_url="https://artifact-public.instana.io/artifactory/instana-team-release-generic-virtual/com/instana/agent-assembly-offline/${AGENT_VERSION}/agent-assembly-offline-${AGENT_VERSION}-linux-s390x.tar.gz" log_info "Downloading agent assembly..." log_debug "Downloading from: ${_zos_asm_url}" if ! curl -# -u "_:${INSTANA_DOWNLOAD_KEY}" "${_zos_asm_url}" \ -o agent-assembly-linux-static-s390x.tar.gz; then log_error "Failed to download agent assembly from ${_zos_asm_url}" exit 1 fi log_debug "Agent assembly download complete" log_info "Extracting agent assembly..." gzip -d agent-assembly-linux-static-s390x.tar.gz pax -r -f agent-assembly-linux-static-s390x.tar fi if ls "$DIR"/*/org.apache.felix.framework-*.jar 2>/dev/null | grep -q .; then echo "The required file is available for further installation process of instana-agent i.e. $EXPECTED_FILE" else echo "The required file NOT found: i.e. $EXPECTED_FILE, Issue during download/Untar of build aborting further installation" exit 1 fi #Will have Remaining logic to handle and convert code page tagging and all... export _BPXK_AUTOCVT=ON echo 'INFO: Auto Character Conversion (export _BPXK_AUTOCVT=ON) is enabled for this session. For convenience it is recommended to set this in your User Profile, so you don’t need to export it each time you log in' echo 'Enabling codepage Setting' chtag -R -tc 819 ${AGENT_DIR_ZOS}/bin chtag -R -tc 819 ${AGENT_DIR_ZOS}/etc echo 'Codepage Setting for required folder of Instana-Agent has been enabled' configure_server_details set_java_home_and_start_agent ;; *) log_error 'Unsupported package manager. The supported packages managers are: apt, dnf, yum, zypper' exit 1; esac } function check_existing_instana_agent_process() { # Check if the process is running process_command="/bin/sh ${AGENT_DIR_ZOS}/bin/karaf server" echo $process_command pid=$(ps -ef | grep "$process_command" | grep -v grep | awk '{print $2}') if [ -n "$pid" ]; then echo "Process is running with PID: $pid" echo "Stopping running agent process and cleaning the directory" if [ $PROMPT = true ]; then if ! receive_confirmation 'Do you want to continue to stop the running process?'; then exit 1 fi echo "Stopping current running agent" kill -9 ${pid} rm -rf ${AGENT_DIR_ZOS} fi else echo "Process is not running." fi } function check_existing_instana_agent() { # Check if the instana-agent path exists in the current directory if [ -d "${AGENT_DIR_ZOS}" ]; then echo "Instana agent path is available in the current directory." mkdir ${AGENT_DIR_ZOS_OLD} echo ls cp "${AGENT_DIR_ZOS}/etc/mvn-settings.xml" "${AGENT_DIR_ZOS_OLD}" cp "${AGENT_DIR_ZOS}/etc/org.ops4j.pax.url.mvn.cfg" "${AGENT_DIR_ZOS_OLD}" cp "${AGENT_DIR_ZOS}/etc/instana/com.instana.agent.bootstrap.AgentBootstrap.cfg" "${AGENT_DIR_ZOS_OLD}" cp "${AGENT_DIR_ZOS}/etc/instana/com.instana.agent.main.config.UpdateManager.cfg" "${AGENT_DIR_ZOS_OLD}" cp "${AGENT_DIR_ZOS}/etc/instana/configuration.yaml" "${AGENT_DIR_ZOS_OLD}" cp "${AGENT_DIR_ZOS}/etc/instana/com.instana.agent.main.config.Agent.cfg" "${AGENT_DIR_ZOS_OLD}" cp "${AGENT_DIR_ZOS}/etc/instana/com.instana.agent.main.sender.Backend.cfg" "${AGENT_DIR_ZOS_OLD}" else echo "Instana agent path is NOT available in the current directory." fi } function check_zOS_server_update_prerequisites() { if command -v sed > /dev/null; then log_info 'sed are available on the system' else log_error 'This script requires sed to be installed on this system. Aborting installation.' exit 1 fi } function set_java_home_and_start_agent(){ echo " To Start the Agent we need JAVA_HOME path, checking with installed java on the system" java_version=$(java -version 2>&1 | head -n 1 | sed -E 's/.*"([^"]+)".*/\1/') # Check if the Java command succeeded if [ $? -ne 0 ]; then echo "Java is not installed or not in the PATH." echo "Please provide the path to the JAVA_HOME directory, ensuring it is located before the 'bin' directory; for example: /usr/lpp/java/11.0" read -p "Enter JAVA_HOME: " JAVA_HOME echo "Entered JAVA_HOME is: $JAVA_HOME" else echo "Java version detected: $java_version" fi # Extract the major version number if echo "$java_version" | grep -q "^1\."; then # For version like 1.8.x (Java 8), extract the second part of the version major_version=$(echo $java_version | cut -d. -f2) else # For versions like 9.x.x, 11.x.x, etc., the major version starts from the first number major_version=$(echo $java_version | cut -d. -f1) fi # Check if the version is exactly Java 11 if [ "$major_version" -eq 11 ]; then echo "Java version $java_version is installed and is a supported version." else echo "Java version $java_version is installed, but it is not a supported version. Supported version is JAVA 11." log_warn 'Please provide the path to the JAVA_HOME directory with a supported version, ensuring it is located before the "bin" directory; for example : /usr/lpp/java/11.0' read JAVA_HOME echo "Enterd JAVA_HOME is : $JAVA_HOME" fi echo 'Setting JAVA_HOME for Instana-Agent' FILE="${AGENT_DIR_ZOS}/bin/setenv" sed '/# unset JAVA_HOME/ { s/# unset JAVA_HOME/unset JAVA_HOME/; }' "$FILE" > "$FILE.tmp" echo "export JAVA_HOME=$JAVA_HOME" >> "$FILE.tmp" mv "$FILE.tmp" "$FILE" echo 'Updated JAVA_HOME for Instana-Agent' echo 'Ready to start the agent, will start the agent' if test -d "${AGENT_DIR_ZOS_OLD}"; then test -f "${AGENT_DIR_ZOS_OLD}/mvn-settings.xml" && cp "${AGENT_DIR_ZOS_OLD}/mvn-settings.xml" "${AGENT_DIR_ZOS}/etc/" test -f "${AGENT_DIR_ZOS_OLD}/org.ops4j.pax.url.mvn.cfg" && cp "${AGENT_DIR_ZOS_OLD}/org.ops4j.pax.url.mvn.cfg" "${AGENT_DIR_ZOS}/etc/" test -f "${AGENT_DIR_ZOS_OLD}/com.instana.agent.bootstrap.AgentBootstrap.cfg" && cp "${AGENT_DIR_ZOS_OLD}/com.instana.agent.bootstrap.AgentBootstrap.cfg" "${AGENT_DIR_ZOS}/etc/instana/" test -f "${AGENT_DIR_ZOS_OLD}/com.instana.agent.main.config.UpdateManager.cfg" && cp "${AGENT_DIR_ZOS_OLD}/com.instana.agent.main.config.UpdateManager.cfg" "${AGENT_DIR_ZOS}/etc/instana/" test -f "${AGENT_DIR_ZOS_OLD}/configuration.yaml" && cp "${AGENT_DIR_ZOS_OLD}/configuration.yaml" "${AGENT_DIR_ZOS}/etc/instana/" test -f "${AGENT_DIR_ZOS_OLD}/com.instana.agent.main.config.Agent.cfg" && cp "${AGENT_DIR_ZOS_OLD}/com.instana.agent.main.config.Agent.cfg" "${AGENT_DIR_ZOS}/etc/instana" test -f "${AGENT_DIR_ZOS_OLD}/com.instana.agent.main.sender.Backend.cfg" && cp "${AGENT_DIR_ZOS_OLD}/com.instana.agent.main.sender.Backend.cfg" "${AGENT_DIR_ZOS}/etc/instana" chtag -R -tc 819 ${AGENT_DIR_ZOS}/etc rm -rf ${AGENT_DIR_ZOS_OLD}/ else echo "No configuration files are copied from the previously installed agent" fi ./instana-agent/bin/start echo 'Now, you can check logs at instana-agent/data/log/agent.log ' } function configure_server_details() { log_debug "Writing backend host=${INSTANA_AGENT_HOST} port=${INSTANA_AGENT_PORT} key=$(_mask_key "${INSTANA_AGENT_KEY}") to Backend.cfg" sed "s/host=\${env:INSTANA_HOST}/host=${INSTANA_AGENT_HOST}/" ${AGENT_DIR_ZOS}/etc/instana/com.instana.agent.main.sender.Backend.cfg > ${AGENT_DIR_ZOS}/etc/instana/com.instana.agent.main.sender.Backend.cfg.tmp && mv ${AGENT_DIR_ZOS}/etc/instana/com.instana.agent.main.sender.Backend.cfg.tmp instana-agent/etc/instana/com.instana.agent.main.sender.Backend.cfg sed "s/port=\${env:INSTANA_PORT}/port=${INSTANA_AGENT_PORT}/" ${AGENT_DIR_ZOS}/etc/instana/com.instana.agent.main.sender.Backend.cfg > ${AGENT_DIR_ZOS}/etc/instana/com.instana.agent.main.sender.Backend.cfg.tmp && mv ${AGENT_DIR_ZOS}/etc/instana/com.instana.agent.main.sender.Backend.cfg.tmp instana-agent/etc/instana/com.instana.agent.main.sender.Backend.cfg sed "s/key=\${env:INSTANA_KEY}/key=${INSTANA_AGENT_KEY}/" ${AGENT_DIR_ZOS}/etc/instana/com.instana.agent.main.sender.Backend.cfg > ${AGENT_DIR_ZOS}/etc/instana/com.instana.agent.main.sender.Backend.cfg.tmp && mv ${AGENT_DIR_ZOS}/etc/instana/com.instana.agent.main.sender.Backend.cfg.tmp instana-agent/etc/instana/com.instana.agent.main.sender.Backend.cfg log_debug "Writing download key to mvn-settings.xml (download key: $(_mask_key "${INSTANA_DOWNLOAD_KEY}"))" sed -e "s|_|${INSTANA_DOWNLOAD_KEY}|g" ${AGENT_DIR_ZOS}/etc/mvn-settings.xml > ${AGENT_DIR_ZOS}/etc/mvn-settings.xml.tmp && mv instana-agent/etc/mvn-settings.xml.tmp ${AGENT_DIR_ZOS}/etc/mvn-settings.xml log_info "Server details configured successfully" return 0 } function configure_mode() { if [ "${MODE}" = 'apm' ]; then log_info "Configuring agent mode: APM" if [ "$FAMILY" = "zOS" ]; then echo "mode = APM" >> "${AGENT_DIR_ZOS}/etc/instana/com.instana.agent.main.config.Agent.cfg" log_info "Agent mode APM configured (zOS)" return 0 else /bin/cp "${AGENT_DIR}/etc/instana/com.instana.agent.main.config.Agent.cfg.template" "${AGENT_DIR}/etc/instana/com.instana.agent.main.config.Agent.cfg" echo "mode = APM" >> "${AGENT_DIR}/etc/instana/com.instana.agent.main.config.Agent.cfg" log_debug "Agent mode APM written to ${AGENT_DIR}/etc/instana/com.instana.agent.main.config.Agent.cfg" return 0 fi fi if [ "${MODE}" = 'aws' ]; then log_info 'Configuring agent mode: AWS' # Get region from metadata endpoint local _imds_token_url="http://169.254.169.254/latest/api/token" log_debug "Fetching IMDSv2 token from: ${_imds_token_url}" export INSTANA_AWS_TOKEN=$(download_to_stdout PUT "${_imds_token_url}" -H X-aws-ec2-metadata-token-ttl-seconds:21600) log_debug "IMDSv2 token acquired: ${INSTANA_AWS_TOKEN:+yes (masked)}${INSTANA_AWS_TOKEN:-no}" if [ -n "${INSTANA_AWS_REGION_CONFIG}" ]; then log_info "Using the AWS region ${INSTANA_AWS_REGION_CONFIG} configured via the 'INSTANA_AWS_REGION_CONFIG' environment variable" export INSTANA_AWS_REGION_CONFIG elif [ -z ${INSTANA_AWS_TOKEN+x} ]; then local _imds_doc_url="http://169.254.169.254/latest/dynamic/instance-identity/document" log_debug "Fetching AWS region from instance identity document (no IMDSv2 token): ${_imds_doc_url}" if ! INSTANA_AWS_REGION_CONFIG=$(download_to_stdout "${_imds_doc_url}" | awk -F\" '/region/ {print $4}'); then log_error "Error querying AWS metadata. It seems this virtual machine is not running on EC2. Please set the 'INSTANA_AWS_REGION_CONFIG' environment variable manually." exit 1 fi log_debug "Resolved AWS region: ${INSTANA_AWS_REGION_CONFIG}" else local _imds_doc_url="http://169.254.169.254/latest/dynamic/instance-identity/document" log_debug "Fetching AWS region from instance identity document (IMDSv2): ${_imds_doc_url}" if ! INSTANA_AWS_REGION_CONFIG=$(download_to_stdout "${_imds_doc_url}" -H "X-aws-ec2-metadata-token:${INSTANA_AWS_TOKEN}" | awk -F\" '/region/ {print $4}'); then log_error "Error querying AWS metadata via token. It seems this virtual machine is not running on EC2. Please set the 'INSTANA_AWS_REGION_CONFIG' environment variable manually." exit 1 fi log_debug "Resolved AWS region: ${INSTANA_AWS_REGION_CONFIG}" fi ROLES_FOUND=false if [ -z ${INSTANA_AWS_TOKEN+x} ]; then log_debug "Checking IAM instance role (no IMDSv2 token)" if download_to_stdout http://169.254.169.254/latest/meta-data/iam/security-credentials/ > /dev/null; then ROLES_FOUND=true fi else log_debug "Checking IAM instance role (IMDSv2)" if download_to_stdout http://169.254.169.254/latest/meta-data/iam/security-credentials/ -H "X-aws-ec2-metadata-token:${INSTANA_AWS_TOKEN}" > /dev/null; then ROLES_FOUND=true fi fi log_debug "IAM instance role found: ${ROLES_FOUND}" if [ "$ROLES_FOUND" = "false" ]; then if [ -z "$AWS_ACCESS_KEY_ID" ] || [ -z "$AWS_SECRET_ACCESS_KEY" ]; then log_error "AWS_ACCESS_KEY_ID and/or AWS_SECRET_ACCESS_KEY not exported, and no IAM instance role detected to allow AWS API access." exit 1 fi log_debug "Using static AWS credentials (AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY)" fi /bin/cp "${AGENT_DIR}/etc/instana/com.instana.agent.main.config.Agent.cfg.template" "${AGENT_DIR}/etc/instana/com.instana.agent.main.config.Agent.cfg" echo "mode = INFRASTRUCTURE" >> "${AGENT_DIR}/etc/instana/com.instana.agent.main.config.Agent.cfg" log_debug "Agent mode INFRASTRUCTURE (aws) written to ${AGENT_DIR}/etc/instana/com.instana.agent.main.config.Agent.cfg" return 0 fi if [ "$MODE" = "infra" ]; then log_info "Configuring agent mode: INFRASTRUCTURE" if [ "$FAMILY" = "zOS" ]; then echo "mode = INFRASTRUCTURE" >> "${AGENT_DIR_ZOS}/etc/instana/com.instana.agent.main.config.Agent.cfg" log_info "Agent mode INFRASTRUCTURE configured (zOS)" return 0 else /bin/cp "${AGENT_DIR}/etc/instana/com.instana.agent.main.config.Agent.cfg.template" "${AGENT_DIR}/etc/instana/com.instana.agent.main.config.Agent.cfg" echo "mode = INFRASTRUCTURE" >> "${AGENT_DIR}/etc/instana/com.instana.agent.main.config.Agent.cfg" log_debug "Agent mode INFRASTRUCTURE written to ${AGENT_DIR}/etc/instana/com.instana.agent.main.config.Agent.cfg" return 0 fi fi } function delete_git_repo() { log_debug "Removing pre-existing Git repository: ${AGENT_DIR}/etc/.git" rm -rf "${AGENT_DIR}/etc/.git" log_info "Pre-existing Git repository removed: ${AGENT_DIR}/etc/.git" } function check_preexisting_git_repository() { if [ -n "${GIT_REPO}" ] && [ -d "${AGENT_DIR}/etc/.git" ]; then log_warn "The Git options have been specified, but there is already a Git repository in '${AGENT_DIR}/etc/.git'. To continue, we need to remove the current Git repository." if [ $PROMPT = true ]; then if receive_confirmation 'Do you want to continue?'; then delete_git_repo fi else delete_git_repo fi else log_debug "No pre-existing Git repository found; nothing to remove" fi } function configure_env() { local env_content="" local env_path="" if [ "$INIT" = "systemd" ]; then env_path=/opt/instana/agent/etc/systemd.env else if [ "$FAMILY" = "zypper" ] || [ "$FAMILY" = "yum" ]; then env_path=/etc/sysconfig/instana-agent fi if [ "$FAMILY" = "apt" ]; then env_path=/etc/default/instana-agent fi fi log_debug "Writing agent environment file: ${env_path:-'(none — zOS skipped)'}" [[ -n "$INSTANA_AWS_REGION_CONFIG" ]] && env_content+="$(get_env_line INSTANA_AWS_REGION_CONFIG $INSTANA_AWS_REGION_CONFIG)\n" [[ -n "$AWS_ACCESS_KEY_ID" ]] && env_content+="$(get_env_line AWS_ACCESS_KEY_ID $AWS_ACCESS_KEY_ID)\n" [[ -n "$AWS_SECRET_ACCESS_KEY" ]] && env_content+="$(get_env_line AWS_SECRET_ACCESS_KEY "$AWS_SECRET_ACCESS_KEY")\n" [[ -n "$GIT_REPO" && -n "$GIT_BRANCH" ]] && env_content+="$(get_env_line INSTANA_GIT_REMOTE_REPOSITORY "$GIT_REPO")\n$(get_env_line INSTANA_GIT_REMOTE_BRANCH "$GIT_BRANCH")\n" if [ -n "$GIT_USERNAME" ]; then env_content+="$(get_env_line INSTANA_GIT_REMOTE_USERNAME "$GIT_USERNAME")\n" if [ -n "$GIT_PASSWORD" ]; then env_content+="$(get_env_line INSTANA_GIT_REMOTE_PASSWORD "$GIT_PASSWORD")\n" else env_content+="$(get_env_line INSTANA_GIT_REMOTE_PASSWORD "")\n" fi fi if [ $MACHINE != "OS/390" ]; then printf "$env_content" > "$env_path" log_info "Agent environment file written: ${env_path}" else log_debug "Skipping environment file write (zOS)" fi } function get_env_line() { local key=$1 local val=$2 if [ "$INIT" = "systemd" ]; then echo "${key}=${val}" else echo "export ${key}=${val}" fi } function update_custom_systemd_unit_file () { # file does not exists -> new installation indicator if [ "$INIT" = "systemd" ] && [ ! -e /lib/systemd/system/instana-agent.service ]; then log_debug "New installation detected (no existing instana-agent.service); writing systemd drop-in (Type=${INSTANA_AGENT_SYSTEMD_TYPE})" mkdir -p /etc/systemd/system/instana-agent.service.d/ local systemd_custom_start_conf read -r -d '' systemd_custom_start_conf < /etc/systemd/system/instana-agent.service.d/agent-custom-start.conf; then log_warn "Failed to create '/etc/systemd/system/instana-agent.service.d/agent-custom-start.conf'" else log_info "Systemd drop-in written: /etc/systemd/system/instana-agent.service.d/agent-custom-start.conf (Type=${INSTANA_AGENT_SYSTEMD_TYPE})" fi fi } function disable_autostart_on_systemd() { if [ "$INIT" != "systemd" ]; then INSTANA_AGENT_AUTOSTART=true log_debug "Non-systemd init (${INIT}): INSTANA_AGENT_AUTOSTART=true (package postinst will start the agent)" return 0 fi INSTANA_AGENT_AUTOSTART=false export INSTANA_AGENT_AUTOSTART log_debug "systemd detected: INSTANA_AGENT_AUTOSTART=false (service start managed by this script)" } function start_agent() { if systemctl is-active instana-agent > /dev/null 2>&1; then log_info "Instana agent service is active and agent is reinstalled. Service will be restarted" RESTART=true fi if [ $ENABLE_SERVICE = false ] && [ $RESTART = false ] && [ $INSTANA_AGENT_AUTOSTART = true ]; then log_debug "Skipping service start: ENABLE_SERVICE=false, RESTART=false, INSTANA_AGENT_AUTOSTART=true (package postinst handles autostart)" return 0 fi if [ "$INIT" = "systemd" ]; then if grep -iq 'SUSE' /etc/*release 2>/dev/null; then # remove SysV file on SUSE linux before enabling the service if [ -f /etc/init.d/instana-agent ]; then rm -f /etc/init.d/instana-agent fi fi if [ $ENABLE_SERVICE = true ]; then if ! systemctl daemon-reload > /dev/null 2>&1; then log_error "systemctl daemon reload failed" exit 1 fi if ! systemctl reset-failed > /dev/null 2>&1; then log_error "systemctl reset-failed failed" exit 1 fi if ! systemctl enable instana-agent > /dev/null 2>&1; then log_error "Instana agent service enable on boot failed" exit 1 fi log_info "Instana agent enabled on boot" fi log_info "Starting instana-agent" if ! systemctl restart instana-agent > /dev/null 2>&1; then log_error "Instana agent service start failed" exit 1 fi log_info "Instana agent service started up" else log_warn "Instana agent automatic enable/startup by this script is only supported for systemd" log_warn "Utilize your distribution's init system methods to enable/start the agent" fi } function print_usage() { echo "Usage: setup_agent.sh [OPTIONS]" echo "" echo "Options:" echo " -a, --agent-key (required) The agent key to authenticate monitoring data in the backend" echo " -d, --download-key (optional) The download key to retrieve additional artifacts from the backend" echo " -e, --endpoint (required) The Instana backend endpoint URL and port for the agent backend connection" echo " -m, --agent-mode (optional) The agent mode: OFF | INFRA | APM | AWS (default: apm)" echo " -t, --agent-type (optional) The agent install type: dynamic (default) or static" echo " -n, --systemd-type-notify Run Instana agent with systemd type 'notify'" echo " -s, --enable-agent-service (optional) Enable and start the agent as a system service" echo " -i, --use-internal-packages Use internal packages" echo " -j, --j9-java-runtime (optional) Install Instana Agent with IBM J9 runtime, only for Agent 1. Agent 2.0 will ignore this flag" echo " -y, --assume-yes (optional) Do not prompt for confirmation when asked during the installation, but assume 'yes' as the default answer" echo " -g, --git-ops-repository The git remote URL for agent git-ops remote management" echo " -b, --git-ops-branch The git branch name for agent git-ops remote management" echo " -u, --git-ops-username The git username for agent git-ops remote management" echo " -p, --git-ops-password The git password / auth-token for agent git-ops remote management" echo " -l DEPRECATED. Still accepted (silent drop)" echo " -h, --help Print all available flags, options and help text" echo " --log-level (optional) Set log level: TRACE | DEBUG | INFO | WARN | ERROR (default: INFO)" echo " -v, --verbose (optional) Shorthand for --log-level TRACE" echo " --log-file (optional) Write structured log output to a file in addition to console" echo " --log-credentials (optional) Include actual credential/key values in log output (default: masked). Use only in trusted environments." echo "" echo "Linux only:" echo " --run-as-non-root Install the agent running as a non-root user (systemd only)" echo " --run-as-root Install Agent 2.0 as root, overriding the non-root default (no effect on Agent 1)" echo " --non-root-user The non-root user account" echo " --non-root-group The non-root group name" } # parse_flags: long + short flags for all supported OSes. # Non-root flags (--run-as-non-root, --run-as-root, --non-root-user, --non-root-group) are Linux-only function parse_flags() { while [[ $# -gt 0 ]]; do case "$1" in -a | --agent-key) warn_flag_env_conflict "--agent-key" "$INSTANA_AGENT_KEY" "$2" INSTANA_AGENT_KEY=$2 shift 2 ;; -b | --git-ops-branch) GIT_BRANCH=$2 shift 2 ;; -l) LOCATION=$2 shift 2 ;; -d | --download-key) warn_flag_env_conflict "--download-key" "$INSTANA_DOWNLOAD_KEY" "$2" INSTANA_DOWNLOAD_KEY=$2 shift 2 ;; -e | --endpoint) if [[ -n "$INSTANA_AGENT_HOST" ]]; then warn_flag_env_conflict "--endpoint" "${INSTANA_AGENT_HOST}:${INSTANA_AGENT_PORT}" "$2" fi ENDPOINT=$2 shift 2 ;; -g | --git-ops-repository) GIT_REPO=$2 shift 2 ;; -m | --agent-mode) MODE=$2 shift 2 ;; -n | --systemd-type-notify) INSTANA_AGENT_SYSTEMD_TYPE=notify shift 1 ;; -p | --git-ops-password) GIT_PASSWORD=$2 shift 2 ;; -u | --git-ops-username) GIT_USERNAME=$2 shift 2 ;; -s | --enable-agent-service) ENABLE_SERVICE=true shift 1 ;; -i | --use-internal-packages) USE_INTERNAL_PACKAGES=true shift 1 ;; -j | --j9-java-runtime) OPEN_J9="true" shift 1 ;; -t | --agent-type) AGENT_TYPE=$2 # full and minimal are deprecated # remove this when the packages are removed if [ "$AGENT_TYPE" = "full" ]; then AGENT_TYPE=dynamic fi if [ "$AGENT_TYPE" = "minimal" ]; then AGENT_TYPE=dynamic fi shift 2 ;; -y | --assume-yes) PROMPT=false shift 1 ;; --run-as-non-root) if [ "$OS" = "Linux" ]; then warn_flag_env_conflict "--run-as-non-root" "$INSTANA_AGENT_NON_ROOT" "true" INSTANA_AGENT_NON_ROOT=true else log_warn "Flag --run-as-non-root is only supported on Linux and will be ignored." fi shift 1 ;; --non-root-user) if [ "$OS" = "Linux" ]; then warn_flag_env_conflict "--non-root-user" "$INSTANA_AGENT_USER" "$2" INSTANA_AGENT_USER=$2 else log_warn "Flag --non-root-user is only supported on Linux and will be ignored." fi shift 2 ;; --non-root-group) if [ "$OS" = "Linux" ]; then warn_flag_env_conflict "--non-root-group" "$INSTANA_AGENT_GROUP" "$2" INSTANA_AGENT_GROUP=$2 else log_warn "Flag --non-root-group is only supported on Linux and will be ignored." fi shift 2 ;; --log-level) INSTANA_AGENT_ONE_LINER_LOG_LEVEL="${2^^}" shift 2 ;; -v | --verbose) INSTANA_AGENT_ONE_LINER_LOG_LEVEL="TRACE" shift 1 ;; --log-file) INSTANA_AGENT_ONE_LINER_LOG_TO_FILE="$2" shift 2 ;; --log-credentials) INSTANA_AGENT_ONE_LINER_LOG_CREDENTIALS="true" shift 1 ;; --run-as-root) if [ "$OS" = "Linux" ]; then INSTANA_AGENT_RUN_AS_ROOT=true else log_warn "Flag --run-as-root is only supported on Linux and will be ignored." fi shift 1 ;; -h | --help) print_usage exit 0 ;; *) echo "Invalid option: $1" >&2 exit 1 ;; esac done } parse_flags "$@" log_debug "Resolved configuration: agent_key=$(_mask_key "${INSTANA_AGENT_KEY}") download_key=$(_mask_key "${INSTANA_DOWNLOAD_KEY}") endpoint=${INSTANA_AGENT_HOST}:${INSTANA_AGENT_PORT} mode=${MODE} agent_type=${AGENT_TYPE} log_level=${INSTANA_AGENT_ONE_LINER_LOG_LEVEL} log_credentials=${INSTANA_AGENT_ONE_LINER_LOG_CREDENTIALS}" if [ "$(id -u)" != "0" ]; then log_error "This script must be executed as a user with root privileges" exit 1 fi if [ "$OS" = "Darwin" ]; then log_error "Agent install script does not support macOS. Please download the macOS package from the 'Installing Instana Agents' wizard." exit 1 fi if [ "$OS" = "AIX" ]; then log_error "Agent install script does not support AIX. Please download the AIX package from the 'Installing Instana Agents' wizard." exit 1 fi if [ "$OS" = "SunOS" ]; then log_error "Agent install script does not support Solaris. Please download the Solaris package from the 'Installing Instana Agents' wizard." exit 1 fi detect_machine if [ $MACHINE != "x86_64" ] && [ $MACHINE != "aarch64" ] && [ $MACHINE != "s390x" ] && [ $MACHINE != "ppc64le" ] && [ $MACHINE != "OS/390" ]; then log_error "Systems architecture: $MACHINE not supported" exit 1 fi if [ ! "$INSTANA_AGENT_KEY" ]; then echo "-a INSTANA_AGENT_KEY required!" exit 1 fi if [ ! "$INSTANA_DOWNLOAD_KEY" ]; then INSTANA_DOWNLOAD_KEY="$INSTANA_AGENT_KEY" fi if [ $AGENT_TYPE != "static" ] && [ $AGENT_TYPE != "dynamic" ]; then log_error "Invalid agent type specified $AGENT_TYPE" exit 1 fi if [ "$ENDPOINT" != "" ]; then if ! echo "$ENDPOINT" | grep ":" &>/dev/null; then log_error "Agent endpoint must be in the format of :" exit 1 fi fi if [ -n "${LOCATION}" ]; then log_warn "The -l parameter is deprecated and will not be updated to cover new SaaS regions going forward. Use -e instead." if [ "${LOCATION}" != "eu" ] && [ "${LOCATION}" != "us" ] && [ "${LOCATION}" != "red" ] && [ "${LOCATION}" != "blue" ] && [ "${LOCATION}" != "green" ]; then log_error "Invalid location '${LOCATION}' specified. Please select 'blue', 'red' or 'green'." exit 1 fi fi if [ "$MODE" != "apm" ] && [ "$MODE" != "aws" ] && [ "$MODE" != "infra" ]; then log_error "Invalid mode specified. Supported modes: apm | aws | infra." exit 1 fi if [ $OPEN_J9 = "false" ]; then if [ $MACHINE = "s390x" ] || [ $MACHINE = "ppc64le" ]; then log_info "For the '${MACHINE}' architecture only OpenJ9 JDK is available. Enforcing OpenJ9 agent runtime." OPEN_J9="true" fi fi if [ $OPEN_J9 = "true" ]; then AGENT_TYPE="${AGENT_TYPE}-j9" fi if [ ! "$INSTANA_DOWNLOAD_KEY" ]; then INSTANA_DOWNLOAD_KEY="$INSTANA_AGENT_KEY" fi if [ -n "${GIT_REPO}" ]; then if [ -z "${GIT_BRANCH}" ]; then log_error "The '-g' option for the Git repository has been specified without the '-b' option to specify the remote branch." exit 1 fi else if [ -n "${GIT_BRANCH}" ]; then log_error "The '-b' option for the remote branch has been specified without the '-g' option to specify the Git repository." exit 1 fi if [ -n "${GIT_USERNAME}" ]; then log_error "The '-u' option for the username to authenticate with has been specified without the '-g' option to specify the Git repository." exit 1 fi if [ -n "${GIT_PASSWORD}" ]; then log_error "The '-p' option for the password to authenticate with has been specified without the '-g' option to specify the Git repository." exit 1 fi fi if [ -n "${GIT_PASSWORD}" ]; then if [ -z "${GIT_USERNAME}" ]; then log_error "The '-p' option for the password to authenticate with has been specified without the '-u' option to specify the username." exit 1 fi fi detect_family detect_init resolve_non_root log_info "Setting up the ${AGENT_TYPE} Instana agent for ${OS} (family: ${FAMILY}, arch: ${MACHINE})" if [ $PROMPT = false ]; then response=y else if ! receive_confirmation "Are you sure?"; then exit 1 fi fi check_prerequisites export INSTANA_AGENT_KEY export INSTANA_DOWNLOAD_KEY export INSTANA_AGENT_HOST export INSTANA_AGENT_PORT # Non-root vars are consumed by postinst at package install time (Linux only). if [ "$OS" = "Linux" ]; then export INSTANA_AGENT_NON_ROOT export INSTANA_AGENT_USER export INSTANA_AGENT_GROUP fi check_download_key get_endpoint disable_autostart_on_systemd update_custom_systemd_unit_file if ! setup_agent; then exit 1 fi configure_mode check_preexisting_git_repository configure_env if ! start_agent; then exit 1 fi