#! /usr/bin/env sh ############################################################################# # # Usage: # * Run it as user: ./usr/local/bin/dynmotd # * Run it at user login: # # /usr/local/bin/dynmotd # # * Or set a cron job with a privileged user (access log files, ...) # # */30 * * * * root rm -f /etc/motd && /usr/local/bin/dynmotd > /etc/motd # ############################################################################# #### Colors definition BLACK='\033[30;40m' RED='\033[0;31m' REDB='\033[1;31m' GREEN='\033[1;32m' YELLOW='\033[1;33m' BLUE='\033[34;40m' MAGENTA='\033[0;35m' CYAN='\033[36;40m' WHITE='\033[0;37m' WHITEB='\033[1;37m' RESET='\033[0m' ## Return the state of processes passed in parameters # process_info $PROCESS_LIST_TO_MONITOR $MESSAGE process_info() { local PROCESS_LIST="${1}" local MSG="${2}" for PROCESS in ${PROCESS_LIST}; do MSG="${MSG}${MAGENTA}+ " if (ps ax | grep -v grep | grep ${PROCESS} > /dev/null); then MSG="${MSG}${WHITEB}${PROCESS}${RESET} [ ${GREEN}RUNNING${RESET} ] " else MSG="${MSG}${WHITEB}${PROCESS}${RESET} [ ${REDB}NOT RUNNING${RESET} ] " fi done printf '%b' "${MSG}" } ## Return the listening socket # service_info $PORT_LIST_TO_MONITOR $MESSAGE service_info() { local PORT_LIST="${1}" local MSG="${2}" for PORT in ${PORT_LIST}; do MSG="${MSG}${MAGENTA}+ " # If a port listen if (netstat -lnt|grep -m1 ${PORT} > /dev/null); then # Example: "tcp/127.0.0.1:25" MSG="${MSG}${GREEN}$(netstat -lnt|grep -m1 ${PORT}|awk '{print $1"/"$4}')${RESET} " else # Example: "22: NOT LISTENING" MSG="${MSG}${REDB}${PORT}: NOT LISTENING${RESET} " fi done printf '%b' "${MSG}" } ## Return the number of occurrence a pattern is present in a file # and a color (red:>0, green:=0) get_pattern_count() { local GREP_PAT="${1}" local FILE="${2}" local EXP_VAL="${3}" # Count the pattern in the file NUM=$(grep -E "${GREP_PAT}" "${FILE}" | wc -l) # If $EXP_VAL exist ++ the $NUM and $EXP_VAL are equal if [ "${EXP_VAL}" ] && [ "${NUM}" = "${EXP_VAL}" ]; then MSG="${GREEN}${NUM}" else MSG="${REDB}${NUM}" fi printf '%b' "${MSG}" } #+++++++++++++++++++: System Data :+++++++++++++++++++ HOSTNAME=$(hostname) NET_ADDR=$(hostname -I) KERNEL_VER=$(uname -r) UPTIME=$(uptime | sed 's/.*up ([^,]*), .*/1/') CORE_NUMBER=$(grep "model name" /proc/cpuinfo | wc -l) CPU_MODEL=$(grep -m1 "model name" /proc/cpuinfo | awk -F: '{print $2}') MEM_FREE=$(grep MemFree /proc/meminfo | awk '{print $2}') MEM_TOTAL=$(grep MemTotal /proc/meminfo | awk '{print $2}') SWAP_FREE=$(grep SwapFree /proc/meminfo | awk '{print $2}') SWAP_TOTAL=$(grep SwapTotal /proc/meminfo | awk '{print $2}') #++++++++++++++++++++: User Data :++++++++++++++++++++++ USERNAME=$(whoami) USER_SESSION=$(who | grep $USER | wc -l) PROC_COUNT=$(ps -Afl | wc -l) PROC_COUNT=$(expr $PROC_COUNT - 5) # The "ulimit" from sh don't support the -u option PROC_LIMIT=$(ulimit) #++++++++++++: Authentication Information :+++++++++++++ # Get only one "auth.log" file path, the most recent # Simpliest way to get it? AUTH_LOG_FILE=$(find /var/log -iname 'auth.log' -type f -printf '%TY-%Tm-%Td_%TT %p\n' | sort -r | tail -n1 | cut -d' ' -f2) SSH_USER_LOGIN=$(grep 'session opened' "${AUTH_LOG_FILE}" | awk '/sshd/' | awk "/${USERNAME}/" | wc -l) MOTD_ORIG='/etc/motd.orig' # If an original Motd exist, print it if [ -f ${MOTD_ORIG} ]; then printf '%b' "${RESET}${MAGENTA}+++++++++++++++++++++++: ${WHITE}MoTD${MAGENTA} :++++++++++++++++++++++++${RESET}" while read -r line; do printf '\n%s' "${line}" done < ${MOTD_ORIG} fi printf '%b' "\n${RESET}${MAGENTA}+++++++++++++++++++: ${WHITE}System Data${MAGENTA} :+++++++++++++++++++++${RESET} ${MAGENTA}+ ${WHITE}Hostname\t${MAGENTA}= ${GREEN}${HOSTNAME} ${MAGENTA}+ ${WHITE}Addresses\t${MAGENTA}= ${GREEN}${NET_ADDR} ${MAGENTA}+ ${WHITE}Kernel\t${MAGENTA}= ${GREEN}${KERNEL_VER} ${MAGENTA}+ ${WHITE}Uptime\t${MAGENTA}=${GREEN}${UPTIME} ${MAGENTA}+ ${WHITE}CPU\t\t${MAGENTA}= ${GREEN}${CORE_NUMBER}x${CPU_MODEL} ${MAGENTA}+ ${WHITE}Memory\t${MAGENTA}= ${GREEN}${MEM_FREE}(free)/${MEM_TOTAL}(total) kB ${MAGENTA}+ ${WHITE}Swap\t\t${MAGENTA}= ${GREEN}${SWAP_FREE}(free)/${SWAP_TOTAL}(total) kB" printf '%b' "\n${RESET}${MAGENTA}++++++++++++++++++++: ${WHITE}User Data${MAGENTA} :++++++++++++++++++++++${RESET} ${MAGENTA}+ ${WHITE}Username\t${MAGENTA}= ${GREEN}${USERNAME} ${MAGENTA}+ ${WHITE}Sessions\t${MAGENTA}= ${GREEN}${USER_SESSION} ${MAGENTA}+ ${WHITE}Processes\t${MAGENTA}= ${GREEN}$PROC_COUNT of ${PROC_LIMIT} MAX" printf '%b' "\n${MAGENTA}++++++++++++: ${WHITE}Authentication Information${MAGENTA} :+++++++++++++${RESET}" ## Count the number of session for all standard's user (with a home/) #for SSH_USER in `ls -1 /home/`; do #echo -e "${MAGENTA}+ ${WHITE}SSH login ${MAGENTA}= ${GREEN}`grep 'session opened' "${AUTH_LOG_FILE}" | awk '/sshd/' | awk "/${SSH_USER}/" | wc -l` times this week ("${SSH_USER}")" ##echo -e "${MAGENTA}+ ${WHITE}SSH login ${MAGENTA}= ${GREEN}`grep 'session opened' "${AUTH_LOG_FILE}".1 | awk '/login/' | awk "/${SSH_USER}/" | wc -l` times this week ("${SSH_USER}")" #done # Count the number of failed ssh authentication SSH_FAIL_LOGIN=$(get_pattern_count 'sshd.*Failed' "${AUTH_LOG_FILE}" '0') printf '%b' "\n${MAGENTA}+ ${WHITE}SSH fail\t${MAGENTA}= ${SSH_FAIL_LOGIN} fail(s) this week" # Count the number of failed sudo authentication SUDO_FAIL=$(get_pattern_count 'sudo.*authentication failure' "${AUTH_LOG_FILE}" '0') SUDO_3_FAIL=$(get_pattern_count 'sudo.*3 incorrect password' "${AUTH_LOG_FILE}" '0') printf '%b' "\n${MAGENTA}+ ${WHITE}Sudo fail\t${MAGENTA}= ${GREEN}${SUDO_FAIL} fail(s) this week ${MAGENTA}+ ${WHITE}Sudo 3 fails\t${MAGENTA}= ${GREEN}${SUDO_3_FAIL} fail(s) this week" printf '%b' "\n${MAGENTA}++++++++++++++++++++: ${WHITE}Disk Usage${MAGENTA} :+++++++++++++++++++++${RESET}" # Root partition # Replace by rootfs in few kernel version DISK_USAGE=$(df | grep -m1 "/$" | awk '{print $5}') printf '%b' "\n${MAGENTA}+ ${WHITEB}/${RESET}\t[ ${DISK_USAGE} ] " # Other partition for PART in /boot /home /opt /tmp /usr /var /var/lib/vz; do # "/...$" : $ to grep only the mount point and not sub-directories (/var: OK; /mnt/temp: nOK) if (df | grep "${PART}$" > /dev/null); then DISK_USAGE=$(df | grep "${PART}$" | awk '{print $5}') printf '%b' "\n${MAGENTA}+ ${WHITEB}${PART}${RESET}\t[ ${DISK_USAGE} ] " fi done printf '%b' "\n${MAGENTA}+++++++++++++++++++: ${WHITE}Service Info${MAGENTA} :++++++++++++++++++++${RESET}" ## IF POSTFIX MSG=$(process_info "postfix" '') MSG=$(service_info "25" "${MSG}") printf '%b' "\n${MSG}" ## FI POSTFIX ## Service need a warning if running YELLOW_SERVICE='tmux screen glances htop automysqlbackup vzdump puppet aptitude' for SERVICE in ${YELLOW_SERVICE}; do if (ps ax | grep -v grep | grep ${SERVICE} > /dev/null); then printf '%b' "\n${MAGENTA}+ ${WHITEB}${SERVICE}${RESET} [ ${YELLOW}RUNNING${RESET} ]" fi done #echo -e "${MAGENTA}+++++++++++++: ${RED}Maintenance Information${MAGENTA} :+++++++++++++++${RESET} #${MAGENTA}+${RED}"" #echo -e "${MAGENTA}+++++++++++++++++++++++++++++++++++++++++++++++++++++++${RESET}"