#! /bin/bash ############################################################################# # # # DO NOT CHANGE THIS FILE - IT WILL BE OVERWRITTEN !!! # # # ############################################################################# # NAME # qc_shell_std.LIB - Library of shell functions for QAD Cloud scripts # # DESCRIPTION # The following functions will be provided by qc_shell_std.LIB # logMsg - Will write standardize messages to ${qcLOGFILE} # dispHelp - Display help information based on the header # getEnv - Will set DLC, PATH, qcDBLIST, qcLOC, qcENV, # qcLOGFILE and qcPORT # errorHandler - Verify previous command and exit based on ${?} # checkUser - Verify if user is root and set qcCMD # notifyZabbbix - Sent success/failure to zabbix # get_psc_version - Will return the Progress version in the # format: ::: or -1 if failed # getDC - Provide the DataCenter for server based on # IP-range or -1 if nothing found # checkLK - Will return 0 if the process is not running # # The following global variables will be set # qcUTILS - Locations of the QAD Cloud utilities # qcDC - The name of the DataCenter # PROSQL_LOCKWAIT_TIMEOUT # # SYNTAX # . lib/qc_shell_std.LIB # # AUTHOR # Written by John Brink (j6b@qad.com) # # REVISION HISTORY # 1.0 02/19/2016 j6b - Initial version # 1.1 03/01/2016 j6b - Add global qcUTILS variable # 1.2 05/25/2016 j6b - Add qcADMINPORT for multiple env on 1 server # 1.3 08/02/2016 j6b - Use dirname for multiple environments # 1.4 09/06/2016 j6b - Add function YabEnabled # 1.5 02/08/2017 j6b - Add function notifyZabbix # 1.6 09/08/2017 j6b - Add qcZABBIX variable and modify notifyZabbix # 1.7 10/17/2017 j6b - Change permissions if logs directory created # 1.8 11/14/2018 j6b - Add function BoomiInstalled # 1.9 06/03/2020 j6b - CLDT-270 - Add get_psc_version # 2.0 12/16/2020 j6b - CLDT-284 - Add getDC function # ------------------------------------------------------------------------- # vim:ts=4 ##------------------## ## Define Functions ## ##------------------## # Functions and Procedures logMsg() { ######################################################################## # Usage (standard) # logMsg # # Usage (for loglevel "WARNING" and "CRITICAL") # logMsg {{--cat|-c} } {{--obj|-o} } \ # {{--trigger|-t} } {{--execpath|-e} } \ # {{--act|-a} } {{--res|-r} } [{--msg|-m} ] # # Description # Initially this function was used to write some logging, but with # the addition of Cassandra it has been extended for the loglevels # "WARNING" and "CRITICAL". # For these loglevels it's necessary that the main script will be # running as root AND the PMLOGFILE variable is set to # /var/log/sh-tools.log # # Author # Written by John Brink (j6b@qad.com) # # Revision history # 1.0 02/19/2016 j6b - Initial version # 1.1 02/12/2020 j6b - Support for Cassandra logging # 1.2 01/20/2021 j6b - CLDT-370 - Update number of fields for DataLake # ---------------------------------------------------------------------- # Setting local variables typeset _time="$(date "+%D-%H:%M:%S.%3N")" typeset _pmtime="$(date "+%Y-%m-%dT%H:%M:%S.%3N")" PMLOGFILE=${PMLOGFILE:-${qcLOGFILE}} local _prog=$(basename ${0}) local _cat="" local _obj="" local _trigger="" local _execpath="" local _action="" local _result="" local _msg="" # Main if [[ ${#} -gt 2 ]] && ( [[ "$1" = "CRITICAL" ]] || [[ "$1" = "WARNING" ]] ) ; then # Reading input parameters _severity=${1} shift while [[ ${#} -gt 0 ]] ; do case "${1}" in "--cat"|"-c") _cat="${2}" shift 2;; "--obj"|"-o") _obj="${2}" shift 2;; "--trigger"|"-t") _trigger="${2}" shift 2;; "--execpath"|"-e") _execpath="${2}" shift 2;; "--action"|"-a") _action="${2}" shift 2;; "--result"|"-r") _result="${2}" shift 2;; "--msg"|"-m") _msg="${2}" shift 2;; *) _msg="${@}" break;; esac done echo "${_pmtime}|${_severity}|${_prog}|${_cat}|${_obj}|${_trigger}|${_execpath}|${_action}|${_result}|${_msg}" >> ${PMLOGFILE} elif [[ ${#} = 2 ]] ; then echo "${_prog}: ${_time} $1 $2" >> ${qcLOGFILE} tty -s && echo "${_prog}: ${_time} $1 $2" else echo "${_prog}: ${_time} $@" >> ${qcLOGFILE} tty -s && echo "${_prog}: ${_time} $@" fi } dispHelp() { # Display help information based on the header of the script sed -n '/^# NAME$/,/^#$/ { /^#$/d /^# NAME$/d s/.*-[ \t]\(.*$\)/\1/p }' ${0} sed -n '/^# SYNTAX$/,/^#$/ { /^#$/d s/.*SYNTAX$/Usage:/ s/^#[ \t]/ / p }' ${0} } errorHandler() { # Standard error handling _retcode=${1} _retcrit=${2} _retmesg=${3} if [[ ! ${_retcode} == 0 ]] then logMsg "${_retcrit}" "${_retmesg} - ERRNO: ${_retcode}" echo " Use ${qcLOGFILE} for more info" exit ${_retcode} fi } getEnv() { ######################################################################## # Usage # getEnv [env] # # Description # Will set a number of variables based on the configuration file # in /usr/local/etc or based on the parameter that is supplied # # Result # The following parameters will be set: # DLC - The installation directory of PROGRESS # qcDBLIST - List of database with complete pathname # qcLOC - Provides the QAD installation root directory # qcENV - Provides the QAD environment name (like prod, test, dr) # qcPORT - Port where the Progress AdminServer is running # qcLOGFILE - Name of logfile (${_logdir}/$(basename ${0} .sh).log # qcCUST - Customized program that needs to be executed # qcADMINPORT - Additional port for AdminServer if multiple instances are running on 1 server # qcZABBIX - Zabbix server IP address that is used for this server # # Author # Written by John Brink (j6b@qad.com) # # Revision history # 1.0 02/19/2016 j6b - Initial version # 1.1 05/25/2016 j6b - Add qcADMINPORT for multiple env on 1 server # 1.2 08/02/2016 j6b - Use dirname for multiple environments # 1.3 09/08/2017 j6b - Add qcZABBIX because the use of multiple Zabbix servers # ---------------------------------------------------------------------- # Variable definitions _confdir=/usr/local/etc # Location of the configuration files _me=$(basename ${0}) # Name of calling program A_cfg=( ) # Array of configuration files if [[ -d ${_confdir} ]] then A_cfg=(${_confdir}/progress*.cfg) if [[ ${#A_cfg[*]} == 1 ]] then qcLOC=$(grep "^enviro=" ${A_cfg[0]}| cut -d'=' -f2) qcENV=$(grep "^qadenv=" ${A_cfg[0]}| cut -d'=' -f2) DLC=$(grep "^DLC" ${A_cfg[0]} | cut -d'=' -f2) qcDBLIST=$(grep "^databaselist" ${A_cfg[0]} | cut -d'=' -f2) qcPORT=$(grep "^adminServerPort" ${A_cfg[0]} | cut -d'=' -f2) qcZABBIX=$(grep "^server" ${A_cfg[0]} | cut -d'=' -f2) else # Multiple or no progress*.cfg file(s) are found # Returns the QAD environment the script is ran in qcLOC=$(echo $(cd $(dirname ${0}) ; echo $(pwd) | awk -F "/" '{ print $2 }')) if [[ ! -d /${qcLOC}/apps/mfgpro ]] then case ${#} in 1) qcLOC=${1} qcENV=${qcLOC} DLC=/${qcENV}/apps/dlc qcDBLIST=/${qcENV}/db/${qcENV}db/*.db case ${qcENV} in "prod") qcPORT=18000;; "qond") qcPORT=18000;; "test") qcPORT=17000;; "train") qcPORT=16000;; "devl") qcPORT=15000;; "migr") qcPORT=14000;; "base") qcPORT=13000;; *) qcPORT=20931;; esac ;; *) echo "ERROR - Invalid environment: /${qcLOC}/apps/mfgpro doesn't exist" exit 99 ;; esac elif [[ -f ${_confdir}/progress_agent-${qcLOC}.cfg ]]; then # Configuration file found _cfgfile=${_confdir}/progress_agent-${qcLOC}.cfg qcLOC=$(grep "^enviro=" ${_cfgfile}| cut -d'=' -f2) qcENV=$(grep "^qadenv=" ${_cfgfile}| cut -d'=' -f2) DLC=$(grep "^DLC" ${_cfgfile} | cut -d'=' -f2) qcDBLIST=$(grep "^databaselist" ${_cfgfile} | cut -d'=' -f2) qcPORT=$(grep "^adminServerPort" ${_cfgfile} | cut -d'=' -f2) qcZABBIX=$(grep "^server" ${_cfgfile} | cut -d'=' -f2) else # No configuration file found qcENV=${qcLOC} DLC=/${qcENV}/apps/dlc qcDBLIST=/${qcENV}/db/${qcENV}db/*.db case ${qcENV} in "prod") qcPORT=18000;; "qond") qcPORT=18000;; "test") qcPORT=17000;; "train") qcPORT=16000;; "devl") qcPORT=15000;; "migr") qcPORT=14000;; "base") qcPORT=13000;; *) qcPORT=20931;; esac fi fi else echo "ERROR - ${_confdir} could not be found" exit 99 fi # Set logging variables _logdir=/${qcLOC}/apps/mfgpro/scripts/logs if [[ ! -d ${_logdir} ]] ; then mkdir -p ${_logdir} chown mfg: ${_logdir} chmod g+w ${_logdir} fi qcLOGFILE=${_logdir}/${_me%.sh}.log # Set customized program qcCUST=/${qcLOC}/apps/mfgpro/scripts/xx${_me} # Set -adminport value to accomodate multiple AdminServers qcADMINPORT=$((qcPORT + 1)) PATH=${DLC}:${DLC}/bin:${PATH} export qcENV qcLOC DLC qcDBLIST qcPORT PATH qcLOGFILE qcCUST qcADMINPORT qcZABBIX } function checkUser() { # checkUser will verify the user who's running the script # if the user is 'root' is set the variable qcCMD to execute a sudo _user=$(id | cut -d'(' -f2 | cut -d')' -f1) if [[ ${_user} == "root" ]] || [[ ${_user} == "mfg" ]] then if [[ ${_user} == "root" ]] then # Only switch to mfg if user exists grep "mfg" /etc/passwd > /dev/null 2>&1 [[ ${?} == 0 ]] && qcCMD="/usr/bin/sudo -u mfg" else qcCMD="" fi return 0 else return 1 fi export qcCMD } function YabEnabled() { ######################################################################## # Usage # YabEnabled # # Description # Verify if YAB is installed on this server. # # Result # 0 - Yab is used # 1 - Yab is not installed # # Author # Written by John Brink (j6b@qad.com) # # Revision history # 1.0 09/06/2016 j6b - Initial version # 1.1 04/19/2021 j6b - Works fine for user mfg as default permissions # for yab is 744 and owned by mfg, but will fail # for any other user. # ---------------------------------------------------------------------- # v1.1 - Don't look at executable permissions #if [[ -x /usr/local/yab/yab ]] ; then # End - v1.1 if [[ -f /usr/local/yab/yab ]] ; then return 0 else return 1 fi } function BoomiInstalled() { ######################################################################## # Usage # BoomiInstalled # # Description # Verify if Boomi is installed on this server. # # Result # 0 - Boomi is used # 1 - Boomi is not installed # # Author # Written by John Brink (j6b@qad.com) # # Revision history # 1.0 11/14/2018 j6b - Initial version # ---------------------------------------------------------------------- RETVAL=1 for i in base devl devel ldat migr prod qond test train; do for j in /${i}/apps/boomi_qx*; do if [[ -x ${j}/bin/atom ]]; then RETVAL=0 break fi done [[ ${RETVAL} = 0 ]] && break done return ${RETVAL} } notifyZabbix() { ######################################################################## # Usage # notifyZabbix hostname key status # hostname : name of the host the application is running # key : valid key for zabbix / progress_agent # status : 0 for success, 1 for failure # # Description # Notify zabbix for success or failure of script # # Author # Written by John Brink (j6b@qad.com) # # Revision history # 1.0 02/07/2017 j6b - Initial version # 1.1 09/08/2017 j6b - Use qcZABBIX if set # ---------------------------------------------------------------------- # Local variables local _zabbixprod=216.58.134.132 local _zabbixnonprod=216.58.134.142 # Read variables if [[ ! ${#} = 3 ]]; then logMsg ERR "notifyZabbix - Invalid number of parameters" else local _hostname=${1} local _key=${2} local _status=${3} # Identify if a cluster and change host to it _clustername=`/usr/sbin/clustat 2>/dev/null | grep service | awk '{print $1}' | awk -F: '{print $2}'` if [[ "${_clustername}" != "" ]]; then _hostname=${_clustername} fi # Notifify Zabbix about status if [[ ! -z ${qcZABBIX} ]] ; then /usr/local/bin/zabbix_sender -z ${qcZABBIX} --host ${_hostname} --key ${_key} --value ${_status} 1>/dev/null else /usr/local/bin/zabbix_sender -z ${_zabbixprod} --host ${_hostname} --key ${_key} --value ${_status} 1>/dev/null /usr/local/bin/zabbix_sender -z ${_zabbixnonprod} --host ${_hostname} --key ${_key} --value ${_status} 1>/dev/null fi fi # keyname: oe.db.auditarchive..status # 0 - ok # 2 - critical } get_psc_version() { # NAME # get_psc_version - will return the Progress version in the # format: ::: or -1 if failed # # Usage: # get_psc_version # # Examples: # get_psc_version('10.2B0881') returns 10:2B:8:81 # get_psc_version('11.7.5') returns 11:7:5:0 # get_psc_version('12.1') returns 12:1:0:0 # get_psc_version('11.6.4.019') returns 11:6:4:19 # # Revision History # ----------------------------------------------------------------- # 1.0 01/23/2020 j6b - Initial version # 1.1 04/13/2021 j6b - Support older Progress versions and # better error handling # ----------------------------------------------------------------- if [[ ! ${#} = 1 ]] || [[ ! "${1}" =~ "." ]] ; then echo -1 else _pversion=${1} if [[ ${_pversion:0:1} -ge 6 ]] ; then IFS="\." read -a _a <<< "${_pversion}" case ${#_a[1]} in 4) # SP installed echo "${_a[0]}:${_a[1]:0:2}:$((10#${_a[1]:2:2})):0" ;; *) # base installation echo "${_a[0]}:${_a[1]:0:2}:0:0" ;; esac elif [[ ${_pversion:0:2} -gt 10 ]] ; then IFS="\." read -a _a <<< "${_pversion}" case ${#_a[@]} in 4) # HF installed echo "${_a[0]}:${_a[1]}:${_a[2]}:$((10#${_a[3]}))" ;; 3) # SP installed echo "${_a[0]}:${_a[1]}:${_a[2]}:0" ;; *) # base installation echo "${_a[0]}:${_a[1]}:0:0" ;; esac elif [[ ${_pversion:0:2} = 10 ]] ; then IFS="\." read -a _a <<< "${_pversion}" case ${#_a[1]} in 6) # HF installed echo "${_a[0]}:${_a[1]:0:2}:$((10#${_a[1]:2:2})):$((10#${_a[1]:4}))" ;; 4) # SP installed echo "${_a[0]}:${_a[1]:0:2}:$((10#${_a[1]:2:2})):0" ;; *) # base installation echo "${_a[0]}:${_a[1]:0:2}:0:0" ;; esac else echo -1 fi fi } getDC() { # NAME # getDC - will return DataCenter based on IP # and information in /usr/remote/odutils/OD-datacenters # # USAGE: # getDC # # RETURN: # of DC or "-1" if failed # # Revision History # ----------------------------------------------------------------- # 1.0 12/16/2020 j6b - Initial version # ----------------------------------------------------------------- _ODFILE=/usr/remote/odutils/OD-datacenters if [[ -f ${_ODFILE} ]] ; then # Get QAD IP _QADIP=`/sbin/ifconfig | grep inet | grep -i mask | awk '{print $2}' | sed 's/addr://' | grep -ve "^127\.0\.0\.1" -e "^172\.18\." -e "^10\." -e "^119\." -e "^168\.1" | head -1` # Get data center _FINDIP=`echo ${_QADIP} | awk -F. '{print $1"."$2"."$3}'` _IPNUM=`echo ${_QADIP} | awk -F. '{print $4}'` for _ENTRY in $(grep ^${_FINDIP}\. ${_ODFILE} | awk '{print $1","$2","$3}') ; do _IPRANGE=`echo ${_ENTRY} | sed "s/,/ /g"` _FROMIP=`echo ${_IPRANGE} | awk '{print $1}'` _THRUIP=`echo ${_IPRANGE} | awk '{print $2}'` _DCTMP=`echo ${_IPRANGE} | awk '{print $3}'` _FROMNUM=`echo ${_FROMIP} | awk -F. '{print $4}'` _THRUNUM=`echo ${_THRUIP} | awk -F. '{print $4}'` let "_CHECK1=_IPNUM - _FROMNUM" let "_CHECK2=_THRUNUM - _IPNUM" if [ ${_CHECK1} -ge 0 ] && [ ${_CHECK2} -ge 0 ] ; then _DC=${_DCTMP} break fi done fi if [[ ! -z ${_DC} ]] ; then qcDC=$(echo ${_DC} | cut -d'-' -f2) else qcDC="-1" fi } checkLK() { # NAME # checkLK - Check lk-file # # DESCRIPTION # This function will return 0 if an instance is not running, # it will return 1 if the instance is running and 99 if # the lockfile doesn't contain any information # # USAGE # checkLK [-d] lockfile [other parameters] # # RETURN # 0 - Process is not running # 1 - Process is already running # 98 - Process lockfile is not readable # 99 - Something went wrong # # AUTHOR # written by John Brink # # REVISION HISTORY # ---------------------------------------------------------------------- # 0.1 02/10/2021 j6b - Initial Creation # 0.2 02/24/2021 j6b - Change grep command # 0.3 03/17/2021 j6b - Modify grep command for stranded sessions # Also try to look at the provided parameters # ---------------------------------------------------------------------- # vim:ts=4 VERS=0.3 # Version of this script. [[ ! ${#} -gt 0 ]] && return 99 _debug=0 while getopts d opt; do case "${opt}" in d) _debug=1;; esac done shift $((OPTIND - 1)) _lkfile=${1} shift _otherparams=${@} [[ ${_debug} = 1 ]] && echo "checkLK - called from ${0}" if [[ ! -f ${_lkfile} ]] ; then # File doesn't exist, so process not running return 0 elif [[ ! -r ${_lkfile} ]] ; then # File exists, but is not readable return 98 else # Collect information [[ ${_debug} = 1 ]] && echo "${_lkfile} found - continue" _content=$(cat ${_lkfile}) # Layout should be PID [time started] [..] _pid=$(echo ${_content}|cut -d' ' -f1) _time=$(echo ${_content}|cut -d' ' -f2) if [[ ${_debug} = 1 ]] ; then echo "\${_content}: ${_content}" echo "\${_pid}: ${_pid}" echo "\${_time}: ${_time}" echo "\${_otherparams}: ${_otherparams}" fi if [[ -z ${_pid} ]] ; then # No pid value found - cannot verify return 99 else # Verify if pid is already running # v0.2 - Changing grep #_wc=$(ps -ef | grep ${_pid} | \ # grep -e /bin/sh -e /bin/ksh -e /bin/bash -e $(basename ${_lkfile} .lk)| \ # grep -v grep | \ # wc -l) # v0.3 - Changing grep # grep -e /bin/sh -e /bin/ksh -e /bin/bash -e $(basename ${0})| \ # End - v0.3 _wc=$(ps -ef | grep ${_pid} | \ grep "$(basename ${0}) ${_otherparams}"| \ grep -v grep | \ wc -l) # End - v0.2 [[ ${_debug} = 1 ]] && echo "\${_wc}: ${_wc}" return ${_wc} fi fi } ##------------------## ## Global variables ## ##------------------## PROSQL_LOCKWAIT_TIMEOUT=302 [[ -d /usr/remote/odutils ]] && qcUTILS=/usr/remote/odutils export PROSQL_LOCKWAIT_TIMEOUT qcUTILS