#!/bin/bash

# Userlogrotate rotates logs in custom paths.
# The difference with logrotate is that it sets
# the owner:group according to the location of each log.

CONF_PATH="/etc/evolinux/userlogrotate.conf"  # optional file

# Default conf
DELETE_AFTER_RETENTION_DAYS="false" # values: true | false
RETENTION_DAYS=365                  # only applies if $RETENTION_DAYS == "true"
SYSTEM_LOGS_SEARCH_PATHS=(          # will chown root:$user
    /home/*/log
)
APPLICATIVE_LOGS_SEARCH_PATHS=(     # will chown $user:$user
    /home/*/www/{,current/}log
)
SYSTEM_LOG_NAMES=(access.log access-*.log error.log php.log)
APPLICATIVE_LOG_NAMES=(production.log delayed_job.log development.log test.log)
DRY_RUN=false                       # do echo instead of executing, values: true | false

############################################################

DATE="$(/bin/date +"%Y-%m-%d")"

if [ -f "${CONF_PATH}" ]; then
    source "${CONF_PATH}"
fi

rotate () {
    if [ ${DRY_RUN} == "false" ]; then
        mv $1 $1.${DATE}
        touch $1
        chown $2 $1
        chmod g+r $1
    else
        echo "Move $1 to $1.${DATE}"
        echo "Change $1 owner to $2"
    fi
}

user_for() {
  stat -L -c '%U' $1
}

group_for() {
  stat -L -c '%G' $1
}


delete_old() {
    if [ ${DELETE_AFTER_RETENTION_DAYS} == "true" ]; then
        if [ ${DRY_RUN} == "false" ]; then
            find $1/ -ctime +${RETENTION_DAYS} -delete  # slash is needed!
        else
            echo "Delete files:"
            find $1/ -ctime +${RETENTION_DAYS}
        fi
    fi
}

compress() {
    if [ ${DRY_RUN} == "false" ]; then
        gzip "$1"
    else
        echo "Gzipping $1"
    fi
}

for path in ${SYSTEM_LOGS_SEARCH_PATHS[@]}; do
    for log_name in ${SYSTEM_LOG_NAMES[@]}; do
        log_paths=$(ls -1 -d ${path}/${log_name} 2>/dev/null | grep -v \.bak\.)
        for file in ${log_paths}; do
            user="$(user_for "${file}")"
            group="$(group_for "${file}")"
            rotate "${file}" "${group}":"${user}"
            delete_old "$(dirname "${file}")"
        done
    done
done

for path in ${APPLICATIVE_LOGS_SEARCH_PATHS[@]}; do
    for log_name in ${APPLICATIVE_LOG_NAMES[@]}; do
        log_paths=$(ls -1 -d ${path}/${log_name} 2>/dev/null | grep -v \.bak\.)
        for file in ${log_paths}; do
            user="$(user_for "${file}")"
            group="$(group_for "${file}")"
            rotate "${file}" "${group}":"${user}"
            delete_old "$(dirname "${file}")"
        done
    done
done

if [ -x /usr/sbin/apache2ctl ] && /etc/init.d/apache2 status > /dev/null ; then
    if [ ${DRY_RUN} == "false" ]; then
        /etc/init.d/apache2 reload > /dev/null
    else
        echo "Reloading Apache"
    fi
fi

if [ -x /usr/sbin/nginx ]; then
    if [ ${DRY_RUN} == "false" ]; then
        invoke-rc.d nginx rotate >/dev/null 2>&1
    else
        echo "Reloading Nginx"
    fi
fi

# Zipping is done after web server reload, so that the file descriptor is released.
# Else, an error is raised (gzip file size changed while zipping)
# and logs written during the zipping process might be lost.

for path in ${SYSTEM_LOGS_SEARCH_PATHS[@]}; do
    for log_name in ${SYSTEM_LOG_NAMES[@]}; do
        to_compress_paths=$(ls -1 -d ${path}/${log_name}*[!\.gz] 2>/dev/null | grep -v \.bak\.)
        for file in ${to_compress_paths}; do
            compress "${file}"
        done
    done
done

for path in ${APPLICATIVE_LOGS_SEARCH_PATHS[@]}; do
    for log_name in ${APPLICATIVE_LOG_NAMES[@]}; do
        compressed_paths=$(ls -1 -d ${path}/${log_name}*[!\.gz] 2>/dev/null | grep -v \.bak\.)
        for file in ${compressed_paths}; do
            compress "${file}"
        done
    done
done

exit 0
