diff --git a/check_sympa_spool_msg_dir.sh b/check_sympa_spool_msg_dir.sh new file mode 100755 index 0000000..e08c5df --- /dev/null +++ b/check_sympa_spool_msg_dir.sh @@ -0,0 +1,528 @@ +#!/usr/bin/env bash + +script_name="$(basename $(realpath $0))" +working_dir="$(dirname $(realpath $0))" + +conf_file="${working_dir}/conf/${script_name%%.*}.conf" + +LOCK_DIR="/tmp/${script_name%%.*}.LOCK" +log_file="${LOCK_DIR}/${script_name%%.*}.log" + +# Sending alert messages +# +declare -a alert_email_arr=() + +declare -a potential_critical_msg_file=() +declare -a tmp_potential_critical_msg_file=() + +tmp_spool_msg_folder_exists=false + + +# ------------- +# - Some functions +# ------------- + +clean_up() { + + # Perform program exit housekeeping + rm -rf "$LOCK_DIR" + blank_line + exit $1 +} + +echononl(){ + if $terminal ; then + echo X\\c > /tmp/shprompt$$ + if [ `wc -c /tmp/shprompt$$ | awk '{print $1}'` -eq 1 ]; then + echo -e -n " $*\\c" 1>&2 + else + echo -e -n " $*" 1>&2 + fi + rm /tmp/shprompt$$ + fi +} + +fatal(){ + echo "" + if $terminal ; then + echo -e " [ \033[31m\033[1mFatal\033[m ]: $*" + echo "" + echo -e " \033[31m\033[1mScript was interupted\033[m!" + else + echo " [ Fatal ]: $*" + echo "" + echo " Script was terminated...." + fi + echo "" + clean_up 1 +} + +error (){ + echo "" + if $terminal ; then + echo -e " [ \033[31m\033[1mError\033[m ]: $*" + else + echo "[ Error ]: $*" + fi + echo "" +} + +warn (){ + if $terminal ; then + echo "" + echo -e " [ \033[33m\033[1mWarning\033[m ]: $*" + echo "" + fi +} + +info (){ + if $terminal ; then + echo "" + echo -e " [ \033[32m\033[1mInfo\033[m ] $*" + echo "" + fi +} + +ok (){ + if $terminal ; then + echo "" + echo -e " [ \033[32m\033[1mOk\033[m ] $*" + echo "" + fi +} + +echo_done() { + if $terminal ; then + echo -e "\033[95G[ \033[32mdone\033[m ]" + fi +} +echo_ok() { + if $terminal ; then + echo -e "\033[95G[ \033[32mok\033[m ]" + fi +} +echo_warn() { + if $terminal ; then + echo -e "\033[95G[ \033[33mwarn\033[m ]" + fi +} +echo_failed(){ + if $terminal ; then + echo -e "\033[95G[ \033[1;31mfailed\033[m ]" + fi +} +echo_skipped() { + if $terminal ; then + echo -e "\033[95G[ \033[90m\033[1mskipped\033[m ]" + fi +} +echo_wait(){ + if $terminal ; then + echo -en "\033[95G[ \033[5m\033[1m...\033[m ]" + fi +} + +trim() { + local var="$*" + var="${var#"${var%%[![:space:]]*}"}" # remove leading whitespace characters + var="${var%"${var##*[![:space:]]}"}" # remove trailing whitespace characters + echo -n "$var" +} + +# Check if a given array (parameter 2) contains a given string (parameter 1) +# +containsElement () { + local e + for e in "${@:2}"; do [[ "$e" == "$1" ]] && return 0; done + return 1 +} + +# Check if directory is empty +# +is_empty_directory () { + + # Set the variable for bash behavior + shopt -s nullglob + shopt -s dotglob + + # Die if no dir name was provided on command line + if [[ $# -eq 0 ]]; then + error "Wrong call of function 'is_empty_directory ()'. + + Usage: is_empty_directory " + + echo "" + return 1 + fi + + chk_empty_dir=(${1}/*) + + # Unset the variable for bash behavior + shopt -u nullglob + shopt -u dotglob + + if (( ${#chk_empty_dir[*]} )) ; then + + # Files found in $1 directory (send false) + return 1 + else + + # Directory $1 is empty. (send true) + return 0 + fi + +} + +blank_line() { + if $terminal ; then + echo "" + fi +} + + +# ---------- +# - Some checks .. +# ---------- + +# - Running in a terminal? +# - +if [[ -t 1 ]] ; then + terminal=true +else + terminal=false +fi + + +# ---------- +# Read Configurations from $conf_file +# ---------- + + +# - Give your default values here +# - +if [[ -d "/usr/local/sympa/spool/msg" ]] ; then + DEFAULT_SYMPA_SPOOL_MSG_DIR="/usr/local/sympa/spool/msg" +else + DEFAULT_SYMPA_SPOOL_MSG_DIR="" +fi +DEFAULT_TMP_SPOOL_MSG_DIR="/tmp/usr_local_sympa_spool_msg" + +DEFAULT_CONFLICTING_SCRIPTS="" + +DEFAULT_COMPANY="O.OPEN" +DEFAULT_CONTENT_TYPE='Content-Type: text/plain;\n charset="utf-8"' +DEFAULT_SENDER_ADDRESS="${script_name%%.*}@$(hostname -f)" +DEFAULT_ALERT_EMAIL_ADDRESSES="ckubu@oopen.de" + +if [[ -f "$conf_file" ]]; then + source "$conf_file" +else + warn "No configuration file '$conf_file' present.\n + Loading default values.." +fi + + +[[ -n "$TMP_SPOOL_MSG_DIR" ]] || TMP_SPOOL_MSG_DIR="${DEFAULT_TMP_SPOOL_MSG_DIR}" +[[ -n "$SYMPA_SPOOL_MSG_DIR" ]] || SYMPA_SPOOL_MSG_DIR="${DEFAULT_SYMPA_SPOOL_MSG_DIR}" +if [[ ! -d "${SYMPA_SPOOL_MSG_DIR}" ]]; then + fatal "Given Sympa's spool message dir \033[1m${SYMPA_SPOOL_MSG_DIR}\033[m does not exist." +fi + +[[ -n "$CONFLICTING_SCRIPTS" ]] || CONFLICTING_SCRIPTS="${DEFAULT_CONFLICTING_SCRIPTS}" + +[[ -n "$(trim $alert_email_addresses)" ]] || alert_email_addresses=("${DEFAULT_ALERT_EMAIL_ADDRESSES[@]}") + +if [[ ${#alert_email_addresses} -gt 0 ]] ; then + for _email in $alert_email_addresses ; do + alert_email_arr+=("$_email") + done +fi + +[[ -n "$sender_address" ]] || sender_address="${DEFAULT_SENDER_ADDRESS}" +[[ -n "$content_type" ]] || content_type="${DEFAULT_CONTENT_TYPE}" +[[ -n "$company" ]] || company="${DEFAULT_COMPANY}" + + +# ------------- +# - Job is already running? +# ------------- + +# - If job already runs, stop execution.. +# - +if mkdir "$LOCK_DIR" 2> /dev/null ; then + + ## - Remove lockdir when the script finishes, or when it receives a signal + trap "clean_up 1" SIGHUP SIGINT SIGTERM + +else + + datum="$(date +"%d.%m.%Y %H:%M")" + + msg="[ Error ]: A previos instance of \"`basename $0`\" seems already be running.\n\n Exiting now.." + + echo "" + echo "[ Error ]: A previos instance of that script \"`basename $0`\" seems already be running." + echo "" + echo -e " Exiting now.." + echo "" + + for _email in ${alert_email_arr[@]} ; do + echo -e "To:${_email}\n${content_type}\nSubject:Error cronjob `basename $0` -- $datum\n${msg}\n" \ + | sendmail -F "Error `hostname -f`" -f $sender_address $_email + done + + exit 1 + +fi + + +# - Stop here, if these give scripts are running +# - +if [[ ${#CONFLICTING_SCRIPTS} -gt 0 ]] ; then + + # - Try using a random start delay to prevent (or at least have a small chance) that + # - conflicting scripts will both/all abort if they start at the same time. + # - + # - !! Notice !! + # - This only makes sense if a fixed LOCK directory is used, otherwise the process list + # - (and NOT the LOCK-directory) is used to look for scripts running in parallel. + # - + # - Skip delay if running in an terminal (from copnsole) + # - + if ! $terminal ; then + if [[ "$LOCK_DIR" = "/tmp/${script_name%%.*}.LOCK" ]]; then + _shift="$(( $RANDOM % 10 + 1 ))" + sleep $(( $RANDOM % 25 + $_shift )) + fi + fi + + _stop_running=false + for _val in $CONFLICTING_SCRIPTS ; do + + IFS=':' read -a _val_arr <<< "${_val}" + + _script_name="$(basename ${_val_arr[0]})" + + if [[ -n "${_val_arr[1]}" ]] ; then + + if [[ "${_val_arr[1]}" = "CHECK_PROCESS_LIST" ]] ; then + + check_string_ps="${_val_arr[0]}" + if ps -e f | grep -E "\s+${check_string_ps}" | grep -v grep | grep -v -E "\s+vim\s+" > /dev/null ; then + _stop_running=true + fi + + elif [[ -d "${_val_arr[1]}" ]] ; then + _stop_running=true + fi + + elif [[ -d "/tmp/${_script_name%%.*}.LOCK" ]]; then + _stop_running=true + fi + + if $_stop_running ; then + + echo "" + echo "[ Error ]: The \"${_script_name}\" script is currently running, but it conflicts with this script." + echo "" + echo " Exiting now.." + echo "" + + clean_up 1 + + fi # if $_stop_running ; then + + done # for _val in $CONFLICTING_SCRIPTS ; do + +fi # if [[ ${#CONFLICTING_SCRIPTS} -gt 0 ]] ; then + +# ---------- +# - Some pre-script tasks .. +# ---------- + +if $terminal ; then + echo "" + echo "" + echo -e " \033[1mDoing some pre-script tasks ..\033[m" + echo "" +fi + +echononl "Gather all files 'sympa@*' from folder \033[1m${SYMPA_SPOOL_MSG_DIR}\033[m.." + +CUR_IFS="$IFS" +while IFS=" " read -r -d '' _file ; do + potential_critical_msg_file+=("$(basename ${_file})") +done < <(find "${SYMPA_SPOOL_MSG_DIR}" -mindepth 1 -maxdepth 1 -type f -name "sympa@*" -print0) +echo_ok + +if [[ ${#potential_critical_msg_file[@]} -lt 1 ]] ; then + blank_line + info "No critical message(s) in folder \033[1m${SYMPA_SPOOL_MSG_DIR}\033[m found. + + \033[1mAll is fine.\033[m - Script ends here." + + rm -rf "${TMP_SPOOL_MSG_DIR}" + clean_up 0 +else + blank_line + if $terminal ; then + error "Found some critical file(s) in \033[1m${SYMPA_SPOOL_MSG_DIR}\033[m!" + else + error "Found some critical file(s) in ${SYMPA_SPOOL_MSG_DIR}!" + fi + blank_line +fi +IFS="$CUR_IFS" + +#blank_line +#for _file in ${potential_critical_msg_file[@]} ; do +# echo $_file +#done +#blank_line + +echononl "Create Folder \033[1m${TMP_SPOOL_MSG_DIR}\033[m if not exists.." +if [[ ! -d ${TMP_SPOOL_MSG_DIR} ]] ; then + mkdir -p "${TMP_SPOOL_MSG_DIR}" + if [[ $? -lt 1 ]] ; then + echo_done + else + echo_failed + fi +else + echo_skipped + + tmp_spool_msg_folder_exists=true + + echononl "Gather all files 'sympa@*' from folder \033[1m${TMP_SPOOL_MSG_DIR}\033[m.." + while IFS=" " read -r -d '' _file ; do + tmp_potential_critical_msg_file+=("$(basename ${_file})") + done < <(find "${TMP_SPOOL_MSG_DIR}" -mindepth 1 -maxdepth 1 -type f -name "sympa@*" -print0) + echo_ok + + #blank_line + #for _file in ${tmp_potential_critical_msg_file[@]} ; do + # echo $_file + #done + #blank_line + +fi + + + +# ---------- +# - Main part of script +# ---------- + +if $terminal ; then + echo "" + echo "" + echo -e " \033[1mMain part of script \033[32m${script_name}\033[m\033[1m ..\033[m" + echo "" +fi + +if ! $tmp_spool_msg_folder_exists ; then + for _file in ${potential_critical_msg_file[@]} ; do + echononl "Copy file \033[1m${_file}\033[m into ${TMP_SPOOL_MSG_DIR}.." + cp -a "${SYMPA_SPOOL_MSG_DIR}/${_file}" "${TMP_SPOOL_MSG_DIR}/" > $log_file 2>&1 + if [[ $? -lt 1 ]] ; then + echo_done + else + echo_failed + + error "$(cat $log_file)" + fi + done + + clean_up 0 +fi + +_found_file_second_time=false +for _file in ${potential_critical_msg_file[@]} ; do + + if containsElement "$_file" "${tmp_potential_critical_msg_file[@]}" ; then + + _found_file_second_time=true + + blank_line + echononl "Remove \033[1m${_file}\033[m from directory \033[1m${SYMPA_SPOOL_MSG_DIR}\033[m.." + rm "${SYMPA_SPOOL_MSG_DIR}/${_file}" > $log_file 2>&1 + if [[ $? -lt 1 ]] ; then + echo_done + else + echo_failed + + error "$(cat $log_file)" + fi + + echononl "Remove \033[1m${_file}\033[m from directory \033[1m${TMP_SPOOL_MSG_DIR}\033[m.." + rm "${TMP_SPOOL_MSG_DIR}/${_file}" > $log_file 2>&1 + if [[ $? -lt 1 ]] ; then + echo_done + else + echo_failed + + error "$(cat $log_file)" + fi + + else + + blank_line + echononl "Copy file \033[1m${_file}\033[m into ${TMP_SPOOL_MSG_DIR}.." + cp -a "${SYMPA_SPOOL_MSG_DIR}/${_file}" "${TMP_SPOOL_MSG_DIR}/" > $log_file 2>&1 + if [[ $? -lt 1 ]] ; then + echo_done + else + echo_failed + + error "$(cat $log_file)" + fi + + fi + +done + + +# ---------- +# - Some post-script tasks .. +# ---------- + +if $terminal ; then + echo "" + echo "" + echo -e " \033[1mDoing some post-script tasks ..\033[m" + echo "" +fi + + +# If directory ${TMP_SPOOL_MSG_DIR} is empty remove it. +# +echononl "Remove directory \033[1m${TMP_SPOOL_MSG_DIR}\033[m.." +if $(is_empty_directory "${TMP_SPOOL_MSG_DIR}") ; then + + rmdir "${TMP_SPOOL_MSG_DIR}" > $log_file 2>&1 + if [[ $? -lt 1 ]] ; then + echo_done + else + echo_failed + + error "$(cat $log_file)" + fi +else + echo_skipped + warn "Directory \033[1m${TMP_SPOOL_MSG_DIR}\033[m is not empty!" +fi + +if $_found_file_second_time ; then + echononl "Try to (ee)start sympa service.." + systemctl restart sympa > $log_file 2>&1 + if [[ $? -lt 1 ]] ; then + echo_done + else + echo_failed + + error "$(cat $log_file)" + fi +fi + + +clean_up 0 diff --git a/conf/check_sympa_spool_msg_dir.conf.sample b/conf/check_sympa_spool_msg_dir.conf.sample new file mode 100644 index 0000000..eafec26 --- /dev/null +++ b/conf/check_sympa_spool_msg_dir.conf.sample @@ -0,0 +1,81 @@ +#----------------------------- +# Settings for script check_sympa_spool_msg_dir.sh +#----------------------------- + +# SYMPA_SPOOL_MSG_DIR +# +# Sympa's message spool dir +# +# Defaults to: SYMPA_SPOOL_MSG_DIR="/usr/local/sympa/spool/msg" if exists +# +#SYMPA_SPOOL_MSG_DIR="/usr/local/sympa/spool/msg" + +# TMP_SPOOL_MSG_DIR +# +# Folder used by this script to compare content with original messagwe +# spool directory +# +# DEFAULTS to= TMP_SPOOL_MSG_DIR="/tmp/usr_local_sympa_spool_msg" +# +#TMP_SPOOL_MSG_DIR="/tmp/usr_local_sympa_spool_msg" + + +# CONFLICTING_SCRIPTS +# +# The scripts listed here conflict with this script. If one of these scripts +# is currently running, this script will be stopped. +# +# In addition to the script, a LOCK directory can also be specified which is +# connected to it. +# +# If no fixed LOCK directory is connected to the script, set +# this value to the constant 'CHECK_PROCESS_LIST'. +# +# If no value for the LOCK directory is given, the LOCK directory +# '/tmp/.LOCK' is assumed. +# +# +# Example: +# CONFLICTING_SCRIPTS=" +# /root/bin/monitoring/check_webservice_load.sh:CHECK_PROCESS_LIST +# /root/bin/monitoring/check_remote_websites.sh +# " +# +# No defaults +# +#CONFLICTING_SCRIPTS="" + + +# --- +# - E-Mail settings for sending script messages +# --- + +# company +# +# Example: company="Warenform" +# +# Defaults to: company="O.OPEN" +# +#company="" + +# sender_address +# +# Defaults to: sender_address="${script_name%%.*}@$(hostname -f)" +# +#sender_address="check_mm_service@$(hostname -f)" + +# content_type +# +# Defaults to: content_type='Content-Type: text/plain;\n charset="utf-8"' +# +#content_type='Content-Type: text/plain;\n charset="utf-8"' + +# alert_email_addresses +# +# blank separated list of e-mail addresses +# +# Example: alert_email_addresses="ckubu@oopen.de axel@warenform.net" +# +# Defaults to alert_email_addresses="ckubu@oopen.de" +# +#alert_email_addresses="ckubu@oopen.de"