#!/usr/bin/env bash export LC_ALL=en_US.utf8 script_name="$(basename $(realpath $0))" working_dir="$(dirname $(realpath $0))" conf_file="${working_dir}/conf/${script_name%%.*}.conf" LOCK_DIR="/tmp/dovecot_last_change.LOCK" error_log="${LOCK_DIR}/error.log" _CACHE_FILE="${LOCK_DIR}/tmp_last_change" # ------------- # --- Some defaut values # ------------- DEFAULT_MAILBOX_BASE_DIR="/var/vmail" DEFAULT_DST_DIR="/var/MAIL-STATS/LAST-CHANGE" DEFAULT_DOMAIN="*" DEFAULT_USER="*" # ------------- # --- Some functions # ------------- usage() { [[ -n "$1" ]] && error "$1" [[ $terminal ]] && echo -e " \033[1mUsage:\033[m $(basename $0) [-d ] \033[1mDescription\033[m Script determins the 'last change' time of maildirs using dovecots 'dovecot.index.log' for each mailbox of a domain. If no domain was given at the command line, statistics is written for all mailboxes of all available domains. \033[1mOptions\033[m -d The domain for which the 'last change' statistic is written. The default is to write statistics for all available mail domains. \033[1mFiles\033[m $conf_file: Configuration file \033[1mExample:\033[m Write statistics for domain mail36.net $(basename $0) .. " clean_up 1 } 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[1mError\033[m ]: $*" echo "" echo -e "\033[15G\033[31m\033[1mScript was interupted\033[m!" else echo " [ Fatal ]: $*" echo "" echo " Script was terminated...." fi echo "" clean_up 1 } warn (){ if $terminal ; then blank_line echo -e " [ \033[33m\033[1mWarn\033[m ] $*" blank_line fi } info (){ if $terminal ; then blank_line echo -e " [ \033[32m\033[1mInfo\033[m ] $*" blank_line fi } echo_done() { if $terminal ; then echo -e "\033[75G[ \033[32mdone\033[m ]" fi } echo_failed(){ if $terminal ; then echo -e "\033[75G[ \033[1;31mfailed\033[m ]" fi } echo_skipped() { if $terminal ; then echo -e "\033[75G[ \033[37m\033[1mskipped\033[m ]" fi } echo_wait(){ if $terminal ; then echo -en "\033[75G[ \033[5m\033[1m...\033[m ]" fi } blank_line() { if $terminal ; then echo "" fi } # 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 } # ------------- # - 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 SIGHUP SIGINT SIGTERM else datum="$(date +"%d.%m.%Y %H:%M")" msg="A previos instance of \"${script_name}\" seems already be running." blank_line if $terminal ; then echo -e " [ \033[31m\033[1mError\033[m ]: $msg" echo "" echo -e "\033[15G\033[31m\033[1mScript was interupted\033[m!" else echo " [ Fatal ]: $msg" echo "" echo " Script was terminated...." fi echo "" exit 1 fi # ------------- # --- Check some prerequisites # ------------- # - Running in a terminal? # - if [[ -t 1 ]] ; then terminal=true else terminal=false fi # ========== # - Begin Main Script # ========== # ---------- # - Headline # ---------- if $terminal ; then echo "" echo -e "\033[1m----------\033[m" echo -e "\033[32m\033[1mRunning script \033[m\033[1m$script_name\033[32m .. \033[m" echo -e "\033[1m----------\033[m" fi # ---------- # - Read Configurations from file '$conf_file' # ---------- if [[ -f "$conf_file" ]]; then source "$conf_file" else warn "No configuration file '$conf_file' present.\n Loading default values.." fi [[ -n "${MAILBOX_BASE_DIR}" ]] || MAILBOX_BASE_DIR="${DEFAULT_MAILBOX_BASE_DIR}" [[ -n "${DST_DIR}" ]] || DST_DIR="${DEFAULT_DST_DIR}" # ---------- # - Read commandline parameter # ---------- while getopts d:h opt ; do case $opt in d) DOMAIN="$OPTARG" ;; h) usage ;; \?) usage ;; esac done [[ -n "${DOMAIN}" ]] || DOMAIN="*" USER="*" echo -n '' > $_CACHE_FILE chmod 600 $_CACHE_FILE declare -a _domain_arr=() blank_line echononl "Create Directory '${DST_DIR}'.." if [[ ! -d "$DST_DIR" ]] ; then mkdir -p "$DST_DIR" > $error_log 2>&1 if [[ $? -eq 0 ]]; then echo_done else echo_failed error "$(cat "$error_log")" fi else echo_skipped fi echononl "Remove old statistic files .." if [[ "$DOMAIN" = "*" ]] ; then rm -f ${DST_DIR}/* > $error_log 2>&1 if [[ $? -eq 0 ]]; then echo_done else echo_failed error "$(cat "$error_log")" fi else rm -f "${DST_DIR}/${DOMAIN}/*" if [[ $? -eq 0 ]]; then echo_done else echo_failed error "$(cat "$error_log")" fi fi echononl "Determin last change time for mailboxes.." echo_wait for _index_log in $(ls ${MAILBOX_BASE_DIR}/${DOMAIN}/${USER}/Maildir/dovecot.index.log); do LAST_CHANGE="$(stat $_index_log | grep 'Change: ' | cut -d' ' -f2)" DOMAIN="$(echo $_index_log | cut -d/ -f4)" USER="$(echo $_index_log | cut -d/ -f5)" echo "$LAST_CHANGE ${USER}@${DOMAIN}" >> $_CACHE_FILE if ! containsElement "$DOMAIN" "${_domain_arr[@]}" ; then _domain_arr+=("$DOMAIN") fi done; echo_done echononl "Write down over all statistic file .." if [[ ${#_domain_arr[@]} -gt 1 ]]; then cat $_CACHE_FILE | sort -n > "${DST_DIR}/00-all-domains.stat" 2> "$error_log" if [[ $? -eq 0 ]]; then echo_done else echo_failed error "$(cat "$error_log")" fi else echo_skipped fi echononl "Write down statistic files per domain .." echo_wait _failed=false for _domain in "${_domain_arr[@]}" ; do if [[ ${#_domain_arr[@]} -eq 1 ]] ; then cat $_CACHE_FILE | sort -n > "${DST_DIR}/${_domain}.stat" 2> "$error_log" else cat "${DST_DIR}/00-all-domains.stat" | grep "@$_domain" > "${DST_DIR}/${_domain}.stat" 2> "$error_log" fi if [[ $? -ne 0 ]]; then _failed=true fi done if $_failed ; then echo_failed else echo_done fi info "Statistic file(s) stored at directory '${DST_DIR}/'" clean_up 0;