first commit
This commit is contained in:
		
						commit
						d102b513e2
					
				
							
								
								
									
										121
									
								
								00-motdfetch
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										121
									
								
								00-motdfetch
									
									
									
									
									
										Executable file
									
								
							|  | @ -0,0 +1,121 @@ | |||
| #!/usr/bin/env bash | ||||
| # | ||||
| # MOTDfetch is a modular and dynamic MOTD replacement | ||||
| # and a very nice command line information tool for Debian/Ubuntu systems. | ||||
| # | ||||
| # repository:   https://git.tkapias.net/tkapias/MOTDfetch | ||||
| # author:       Tomasz Kapias | ||||
| # email:        tomasz@tkapias.net | ||||
| # | ||||
| # modules path: ./motdfetch.d/ | ||||
| # config paths: $HOME/.config/motdfetch/motdfetch.conf | ||||
| #               /etc/motdfetch/motdfetch.conf | ||||
| # | ||||
| # requirements (modules apart): sudo apt install coreutils bc | ||||
| 
 | ||||
| # locale env | ||||
| unset LC_ALL | ||||
| export LC_MESSAGES=C | ||||
| 
 | ||||
| # GLOBAL COLORS ###################################################### | ||||
| 
 | ||||
| c_txt="39" | ||||
| c_txt_emphase="35" | ||||
| c_txt_deco="97" | ||||
| c_txt_invert="30" | ||||
| c_bg="47" | ||||
| c_danger="31" | ||||
| c_warning="33" | ||||
| c_success="32" | ||||
| c_title="${c_bg};1;${c_txt_invert}m" | ||||
| 
 | ||||
| # RUN OPTIONS ####################################################### | ||||
| 
 | ||||
| # MODTfetch directory path | ||||
| SCRIPT_DIR=$(dirname "$(realpath "$0")") | ||||
| 
 | ||||
| Help() | ||||
| { | ||||
|     echo -e "\e[1;${c_txt_emphase}mMOTDfetch\e[1;${c_txt}m is a modular and dynamic MOTD replacement and a very" | ||||
|     echo -e "nice command line information tool for Debian/Ubuntu systems.\e[0m" | ||||
|     echo | ||||
|     echo "Syntax:   bash $SCRIPT_DIR/00-motdfetch [-h] [-f] [-t ARG] [-l]" | ||||
|     echo | ||||
|     echo "options:  -h  Print this Help" | ||||
|     echo "          -f  force execution under heavy load" | ||||
|     echo "          -t  execute a standalone module with internal sample conf" | ||||
|     echo "          -l  list available modules files names"     | ||||
| } | ||||
| 
 | ||||
| unset option_force_load | ||||
| 
 | ||||
| # command options and arguments | ||||
| while getopts "hft:l" option; do | ||||
|     case $option in | ||||
|         h) Help | ||||
|              exit ;; | ||||
|         f) option_force_load=1;; | ||||
|         t) # standalone module option | ||||
|              if [[ -f "$SCRIPT_DIR/motdfetch.d/$OPTARG" ]]; then | ||||
|                  (. "$SCRIPT_DIR/motdfetch.d/$OPTARG") | ||||
|                  exit 0 | ||||
|              else | ||||
|                  echo -e "\e[1;${c_danger}mError\e[0m: Invalid module filename, check the -l option.\n" | ||||
|                  Help | ||||
|                  exit 1 | ||||
|              fi;; | ||||
|         l) # List modules option | ||||
|              for file in $SCRIPT_DIR/motdfetch.d/* | ||||
|              do | ||||
|                  echo -e "$(basename $file) $(head -3 $file|tail -1)" | ||||
|              done | column -t -s '#' | ||||
|              exit 0;; | ||||
|         \?) # Invalid option | ||||
|              echo -e "\e[1;${c_danger}mError\e[0m: Invalid option" | ||||
|              Help | ||||
|              exit 1;; | ||||
|     esac | ||||
| done | ||||
| 
 | ||||
| # CONFIG LOADING ################################################### | ||||
| 
 | ||||
| userconf="$HOME/.config/motdfetch/motdfetch.conf" | ||||
| sysconf="/etc/motdfetch/motdfetch.conf" | ||||
| 
 | ||||
| if [[ -f "$userconf" ]];then | ||||
|     . "$userconf" | ||||
| elif [[ -f "$sysconf" ]];then | ||||
|     . "$sysconf" | ||||
| else | ||||
|     echo -e "\e[1;${c_danger}mError\e[0m: no configuration available.\n" | ||||
|     Help | ||||
|     exit 1 | ||||
| fi | ||||
| 
 | ||||
| # EXECUTION ######################################################### | ||||
| 
 | ||||
| ## load check | ||||
| cores=$(/usr/bin/grep -ioPc 'processor\t:' /proc/cpuinfo 2>/dev/null) | ||||
| if [[ "$cores" -eq "0" ]]; then | ||||
|     cores=1 | ||||
| fi | ||||
| threshold="${cores:-1}.5" | ||||
| 
 | ||||
| echo -e "\n\e[${c_title} MOTDFETCH  \e[0m\n" | ||||
| if [[ $(echo "`cut -f1 -d ' ' /proc/loadavg` < $threshold" | /usr/bin/bc) -eq 1 || $option_force_load -eq 1 ]]; then | ||||
|     ### output modules | ||||
|     for file in $SCRIPT_DIR/motdfetch.d/* | ||||
|     do | ||||
|         (. "$file") | ||||
|     done | ||||
|     echo | ||||
| else | ||||
|     ### too much load for modules, run only 00 & 99 + msg | ||||
|     module_header_disable=0 | ||||
|     (. $SCRIPT_DIR/motdfetch.d/00-*) | ||||
|     module_userslog_disable=0 | ||||
|     (. $SCRIPT_DIR/motdfetch.d/99-*) | ||||
|     echo -e "\n\e[${c_title} WE SKIPPED SOME MODULES  \e[0m\n" | ||||
|     echo -e "  MOTDfetch skipped some modules because of\n  this \e[1;${c_danger}msystem load\e[0m being higher than \e[1;${c_danger}m$threshold\e[0;${c_warning}m.\e[0m\n" | ||||
|     echo -e "  \e[1;${c_txt}mBAD ADVICE\e[0m: you can force execution with the option [-f]:\n  # bash $SCRIPT_DIR/00-motdfetch -f\n" | ||||
| fi | ||||
							
								
								
									
										
											BIN
										
									
								
								docs/img/preview.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								docs/img/preview.jpg
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 116 KiB | 
							
								
								
									
										157
									
								
								install.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										157
									
								
								install.sh
									
									
									
									
									
										Executable file
									
								
							|  | @ -0,0 +1,157 @@ | |||
| #!/usr/bin/env bash | ||||
| # | ||||
| # installation script for MOTDfetch | ||||
| # repository: https://git.tkapias.net/tkapias/MOTDfetch | ||||
| # author:     Tomasz Kapias | ||||
| # email:      tomasz@tkapias.net | ||||
| # | ||||
| # run with sudo or as root user, or directly from the repository: | ||||
| #     sudo wget -q https://git.tkapias.net/tkapias/MOTDfetch/raw/master/install.sh -O - | sudo bash | ||||
| 
 | ||||
| 
 | ||||
| # locale | ||||
| export LC_ALL="C.UTF-8" | ||||
| export GREP_COLORS="ms=01;32:mc=01;32:sl=:cx=:fn=35:ln=31:bn=31:se=36" | ||||
| 
 | ||||
| N="\e[0m" | ||||
| T="\e[1;35m" | ||||
| S="\e[0;32m" | ||||
| W="\e[0;33m" | ||||
| E="\e[0;31m" | ||||
| 
 | ||||
| # check if executed by root or sudo | ||||
| if (( ! `id -u` == 0 )); then | ||||
|     echo -e "${E}Please do run as root or with sudo${N}" | ||||
|     exit | ||||
| fi | ||||
| 
 | ||||
| # check if the user uses Bash | ||||
| if [[ ! $BASH_VERSION ]]; then | ||||
|     echo -e "\n\e[1;33mThis tool is written for Bash, its compatibility is not tested with other shells.\e[0m" | ||||
|     echo -e "You are currently using \e[1;31m $SHELL\e[0m, do you want to continue? [\e[1;32mY\e[0m/\e[1;31mn\e[0m]\n" | ||||
|     read -n 1 -r | ||||
|     if [[ ! $REPLY =~ ^[Yy]$ ]]; then | ||||
|         exit 1 | ||||
|     fi     | ||||
| fi | ||||
| 
 | ||||
| ERRORCOUNT=0 | ||||
| 
 | ||||
| if [[ -f "/etc/ssh/sshd_config" ]]; then | ||||
|   echo -e "${T}# setup ssh server (/etc/ssh/sshd_config) to not print MOTD or LASTLOGIN${N}" | ||||
|   sed -ri 's/^(\#?)(PrintMotd|PrintLastLog)([[:space:]]+)(yes|no)/\2\3no/' /etc/ssh/sshd_config | ||||
|   resultsshno=$(/usr/bin/grep -E "PrintMotd\s+(no)?|\PrintLastLog\s+(no)?" /etc/ssh/sshd_config 2>/dev/null) | ||||
|   if [[ $resultsshno == "" ]]; then | ||||
|     echo -e "${E}FAIL - check manually \"PrintMotd no\" & \"PrintLastLog no\"${N}\n" | ||||
|     ((ERRORCOUNT++)) | ||||
|   else | ||||
|     echo -e "$resultsshno" | /usr/bin/grep --color=auto "no" | ||||
|     echo -e "${S}DONE${N}\n" | ||||
|   fi | ||||
|   echo -e "${T}# setup ssh server (/etc/ssh/sshd_config) to accept custom SSH_MOTD env variable${N}" | ||||
|   sed -ri '/SSH_MOTD/! s/^(\#?)(AcceptEnv)(.+)/\2\3 SSH_MOTD/' /etc/ssh/sshd_config | ||||
|   resultsshmotd=$(/usr/bin/grep -E "^AcceptEnv.+SSH_MOTD" /etc/ssh/sshd_config 2>/dev/null) | ||||
|   if [[ $resultsshmotd == "" ]]; then | ||||
|     echo -e "${E}FAIL - check manually \"AcceptEnv SSH_MOTD\"${N}\n" | ||||
|     ((ERRORCOUNT++)) | ||||
|   else | ||||
|     echo -e "$resultsshmotd" | /usr/bin/grep --color=auto "SSH_MOTD" | ||||
|     echo -e "${S}DONE${N}\n" | ||||
|   fi | ||||
| else | ||||
|   echo -e "${E}/etc/ssh/sshd_config DOES NOT EXIST${N}\n" | ||||
|   ((ERRORCOUNT++)) | ||||
| fi | ||||
| 
 | ||||
| echo -e "${T}# setup PAM's sshd (/etc/pam.d/sshd) to not print MOTD and MAIL${N}" | ||||
| if [[ -f "/etc/pam.d/sshd" ]]; then | ||||
|   sed -ri 's/^(\#?)(session[[:space:]]+optional[[:space:]]+)(pam_motd.so|pam_mail.so)(.+)/#\2\3\4/' /etc/pam.d/sshd | ||||
|   resultpamcom=$(/usr/bin/grep -E "^\#.+pam_motd.so|^\#.+pam_mail.so" /etc/pam.d/sshd 2>/dev/null) | ||||
|   if [[ $resultpamcom == "" ]]; then | ||||
|     echo -e "${E}FAIL - comment manually lines with \"pam_motd.so\" & \"pam_mail.so\"${N}\n" | ||||
|     ((ERRORCOUNT++)) | ||||
|   else | ||||
|     echo -e "$resultpamcom" | /usr/bin/grep --color=auto -E "^\#" | ||||
|     echo -e "${S}DONE${N}\n" | ||||
|   fi | ||||
| else | ||||
|   echo -e "${E}FAIL - /etc/pam.d/sshd DOES NOT EXIST${N}\n" | ||||
|   ((ERRORCOUNT++)) | ||||
| fi | ||||
| 
 | ||||
| echo -e "${T}# restart ssh server if it's active${N}" | ||||
| if [[ $(systemctl is-active ssh 2>/dev/null) == "active" ]]; then | ||||
|   systemctl restart ssh.service | ||||
|   echo -e "${S}DONE${N}\n" | ||||
| else | ||||
|   echo -e "${E}SSHD NOT ACTIVE${N}\n" | ||||
| fi | ||||
| 
 | ||||
| echo -e "${T}# install minimal dependencies${N}" | ||||
| apt install -f figlet coreutils bc wget nano dnsutils openssl s-nail | ||||
| echo | ||||
| 
 | ||||
| echo -e "${T}# install ANSI_Shadow figlet font${N}" | ||||
| downloadfigletfont=$(wget -nv -O "/usr/share/figlet/ANSI Shadow.flf" https://raw.githubusercontent.com/xero/figlet-fonts/master/ANSI%20Shadow.flf) | ||||
| if $downloadfigletfont ; then | ||||
|     echo -e "${S}DONE${N}\n" | ||||
| else | ||||
|     echo -e "${E}FAIL${N}\n" | ||||
|     ((ERRORCOUNT++)) | ||||
| fi | ||||
| 
 | ||||
| echo -e "${T}# check directories & backup old & obsolete files${N}" | ||||
| if [[ ! -d "/etc/update-motd.d/backup" ]]; then | ||||
|   mkdir -vp /etc/update-motd.d/backup | ||||
| fi | ||||
| if [[ ! -d "/etc/motdfetch" ]]; then | ||||
|   mkdir -vp /etc/motdfetch | ||||
| fi | ||||
| chmod -v 755 /etc/update-motd.d/ /etc/update-motd.d/backup/ 2>/dev/null | ||||
| echo -e "${S}CHMOD DONE${N}\n" | ||||
| if [[ -d "/etc/update-motd.d/motdfetch.d" ]]; then | ||||
|   cp -p -Rv /etc/update-motd.d/*motdfetch* /etc/update-motd.d/backup/ 2>/dev/null | ||||
|   echo -e "${S}MOTDfetch BACKUP DONE${N}" | ||||
| fi | ||||
| if [[ -d "/etc/motd" ]]; then | ||||
|   mkdir -vp /etc/update-motd.d/backup/etc | ||||
|   mv -vf /etc/motd /etc/update-motd.d/backup/etc/motd 2>/dev/null | ||||
|   echo -e "${S}Static MOTD BACKUP DONE${N}" | ||||
| fi | ||||
| if [[ -d "/etc/update-motd.d/10-uname" ]]; then | ||||
|   mv -vf /etc/update-motd.d/10-uname /etc/update-motd.d/backup/10-uname 2>/dev/null | ||||
|   echo -e "${S}Debian uname MOTD BACKUP DONE${N}" | ||||
| fi | ||||
| echo | ||||
| 
 | ||||
| echo -e "${T}# install/update MOTDfetch${N}" | ||||
| downloadmotd=$(wget -c -nv https://git.tkapias.net/tkapias/MOTDfetch/archive/master.tar.gz -O - \ | ||||
|   | tar -xz --strip-components=1 -C /etc/update-motd.d/ MOTDfetch-master/motdfetch.d/ MOTDfetch-master/00-motdfetch MOTDfetch-master/motdfetch.sample.conf 2>/dev/null) | ||||
| if $downloadmotd ; then | ||||
|     mv -vf /etc/update-motd.d/motdfetch.sample.conf /etc/motdfetch/motdfetch.sample.conf | ||||
|     if [[ -f "/etc/motdfetch/motdfetch.conf" ]]; then | ||||
|         echo -e "${S}SUCCESSFUL UPDATE${N}\n" | ||||
|     else | ||||
|         cp -p -Rv /etc/motdfetch/motdfetch.sample.conf /etc/motdfetch/motdfetch.conf | ||||
|         echo -e "${S}SUCCESSFUL INSTALLATION${N}\n" | ||||
|     fi | ||||
|         if (( $ERRORCOUNT == 1 )); then | ||||
|             echo -e "${W}But CAUTION, $ERRORCOUNT configuration steps have failed.${N} Please check if you need to adjust manually.\n" | ||||
|         elif (( $ERRORCOUNT > 1 )); then | ||||
|             echo -e "${W}But CAUTION, $ERRORCOUNT configuration step has failed.${N} Please check if you need to adjust manually.\n" | ||||
|         fi | ||||
|         echo -e "  - ${S}edit the config file${N}: | ||||
|     # sudo nano /etc/motdfetch/motdfetch.conf | ||||
|     ${S}or create a new user config${N}: | ||||
|     # userdir=~/.config/motdfetch \\ | ||||
|         && mkdir \$userdir \\ | ||||
|         && cp /etc/motdfetch/motdfetch.sample.conf \$userdir/motdfetch.conf \\ | ||||
|         && nano \$userdir/motdfetch.conf\n" | ||||
|         echo -e "  - ${S}add an alias \"motd\" command to your .bashrc${N}:\n      alias motd='/etc/update-motd.d/00-motdfetch'\n" | ||||
|         echo -e "  - ${S}how to use MOTDfetch as an alternative MOTD for SSH sessions${N}: | ||||
|     + ${S}on the ssh server, add the new \"motd\" alias at the end of the ssh user .bashrc${N}: | ||||
|       if [[ -n \$SSH_CONNECTION ]]; then\n        motd\n      fi | ||||
|     + ${S}on the ssh client, add an alias \"sshmotd\" to your .bashrc${N}:\n      alias sshmotd='ssh -o SetEnv=SSH_MOTD=1'\n" | ||||
| else | ||||
|     echo -e "${E}INSTALLATION FAILED - please retry${N}\n" | ||||
| fi | ||||
							
								
								
									
										81
									
								
								motdfetch.d/00-header
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								motdfetch.d/00-header
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,81 @@ | |||
| #!/usr/bin/env bash | ||||
| # | ||||
| # display a custom decorative text (default to username) | ||||
| # + welcome the username + date, time and timezone | ||||
| # + inform of mail presence for user (if s-nail is installed) | ||||
| # | ||||
| # requirements: sudo apt install figlet | ||||
| #               sudo wget --no-check-certificate -O "/usr/share/figlet/ansi-shadow.flf" https://raw.githubusercontent.com/xero/figlet-fonts/master/ANSI%20Shadow.flf | ||||
| # optionnal:    sudo apt install s-nail | ||||
| 
 | ||||
| # GENERAL ########################################################### | ||||
| 
 | ||||
| # locale env | ||||
| unset LC_ALL | ||||
| export LC_MESSAGES=C | ||||
| 
 | ||||
| # check if module was disabled | ||||
| module_disable=${module_header_disable:=0} | ||||
| if (($module_disable == 1)); then | ||||
|     exit 1 | ||||
| fi | ||||
| 
 | ||||
| # colors | ||||
| c_txt=${c_txt:="39"} | ||||
| c_txt_emphase=${c_txt_emphase:="35"} | ||||
| c_txt_deco=${c_txt_deco:="97"} | ||||
| c_txt_invert=${c_txt_invert:="30"} | ||||
| c_bg=${c_bg_sec:="47"} | ||||
| c_danger=${c_danger:="31"} | ||||
| c_warning=${c_warning:="33"} | ||||
| c_success=${c_success:="32"} | ||||
| c_title=${c_title:="${c_bg};1;${c_txt_invert}m"} | ||||
| 
 | ||||
| # OPTIONS ########################################################### | ||||
| 
 | ||||
| # banner custom text or username | ||||
| username=$(/usr/bin/id -un) | ||||
| header_text=${module_header_text:="$username"} | ||||
| 
 | ||||
| # PREPARATIONS ###################################################### | ||||
| 
 | ||||
| # check if s-nail is available and if you have mail | ||||
| if command -v s-nail 1>/dev/null; then | ||||
|     # check mail for user | ||||
|     if /usr/bin/s-nail -e; then | ||||
|         hasmail=$(echo -e "  You have \e[1;${c_success}mmessages\e[0m.") | ||||
|          | ||||
|     else | ||||
|         hasmail=$(echo -e "  You have no messages.") | ||||
|     fi | ||||
| else | ||||
|     hasmail="" | ||||
| fi | ||||
| 
 | ||||
| # trim banner text | ||||
| header_text_width=${#header_text} | ||||
| figlet_width=$(/usr/bin/env figlet -f "ANSI Shadow" "$header_text" | wc -L) | ||||
| while [[ $figlet_width -ge 73 ]]; do | ||||
|     let "header_text_width-=1" | ||||
|     header_text=$(echo -e "${header_text:0:$header_text_width}...") | ||||
|     figlet_width=$(/usr/bin/env figlet -f "ANSI Shadow" "$header_text" | wc -L) | ||||
| done | ||||
| 
 | ||||
| # OUTPUT ############################################################ | ||||
| 
 | ||||
| if [[ $module_header_text != "$username" ]]; then | ||||
|     /usr/bin/env figlet -f "ANSI Shadow" "$header_text" \ | ||||
|         | sed "$d" \ | ||||
|         | sed "s/^/  /" \ | ||||
|         | echo -e "$(sed "1 s/^/\\\e[${c_txt_emphase}m/")" \ | ||||
|         | echo -e "$(sed "$ s/$/\\\e[0m/")" | ||||
|     echo -e "  \e[1;${c_txt}mWelcome \e[${c_txt_emphase}m${username}\e[${c_txt}m, it is \e[${c_txt_emphase}m$(date +"%Y-%m-%d %H:%M:%S %z")\e[${c_txt}m.\e[0m\n${hasmail}" | ||||
| else | ||||
|     echo -e "  Welcome" | ||||
|     /usr/bin/env figlet -f "ANSI Shadow" "$header_text" \ | ||||
|         | sed "$d" \ | ||||
|         | sed "s/^/  /" \ | ||||
|         | echo -e "$(sed "1 s/^/\\\e[${c_txt_emphase}m/")" \ | ||||
|         | echo -e "$(sed "$ s/$/\\\e[0m/")" | ||||
|     echo -e "  \e[1;${c_txt}mIt is \e[${c_txt_emphase}m$(date +"%Y-%m-%d %H:%M:%S %z")\e[${c_txt}m.\e[0m\n${hasmail}" | ||||
| fi | ||||
							
								
								
									
										149
									
								
								motdfetch.d/01-sysinfo
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										149
									
								
								motdfetch.d/01-sysinfo
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,149 @@ | |||
| #!/usr/bin/env bash | ||||
| # | ||||
| # display a list of system informations | ||||
| # + dig and curl have shorts timeouts to not hang the script | ||||
| # | ||||
| # requirements: sudo apt install dnsutils | ||||
| 
 | ||||
| # GENERAL ########################################################### | ||||
| 
 | ||||
| # locale env | ||||
| unset LC_ALL | ||||
| export LC_MESSAGES=C | ||||
| 
 | ||||
| # check if module was disabled | ||||
| module_disable=${module_sysinfo_disable:=0} | ||||
| if (($module_disable == 1)); then | ||||
|     exit 1 | ||||
| fi | ||||
| 
 | ||||
| # colors | ||||
| c_txt=${c_txt:="39"} | ||||
| c_txt_emphase=${c_txt_emphase:="35"} | ||||
| c_txt_deco=${c_txt_deco:="97"} | ||||
| c_txt_invert=${c_txt_invert:="30"} | ||||
| c_bg=${c_bg_sec:="47"} | ||||
| c_danger=${c_danger:="31"} | ||||
| c_warning=${c_warning:="33"} | ||||
| c_success=${c_success:="32"} | ||||
| c_title=${c_title:="${c_bg};1;${c_txt_invert}m"} | ||||
| 
 | ||||
| # api website name for plain public IP4/6 check | ||||
| publicip_api=${global_publicip_api:="icanhazip.com"} | ||||
| 
 | ||||
| # PREPARATIONS ###################################################### | ||||
| 
 | ||||
| # output header | ||||
| echo -e "\nWaiting for DNS and IP checks\e[5m...\e[0m" | ||||
| 
 | ||||
| # get hostname | ||||
| HOSTNAME=`hostname -f` | ||||
| # get distribution name | ||||
| DISTRO=`/usr/bin/cat /etc/*release | /usr/bin/grep "PRETTY_NAME" | cut -d "=" -f 2- | sed 's/"//g'` | ||||
| # get name of main interface with a route for internet | ||||
| INTERNETIFACE="$(ip -o route get 8/32 2>/dev/null)" | ||||
| if [[ "$INTERNETIFACE" ]]; then | ||||
|     INTERNETIFACE=`echo -e "$INTERNETIFACE" | sed -e 's/.*dev //' -e 's/ .*//'` | ||||
| else | ||||
|     INTERNETIFACE="\e[1;${c_warning}mno interface with a route to 8/32\e[0;${c_txt}m" | ||||
| fi | ||||
| # get DNS servers ips from resolv.conf | ||||
| DNSSERVERS=`/usr/bin/grep '^nameserver' /etc/resolv.conf | cut -d' ' -f2 | paste -sd ','` | ||||
| if [[ ! $DNSSERVERS ]];then | ||||
|     DNSSERVERS="\e[1;${c_warning}mno ns in resolv.conf\e[0;${c_txt}m" | ||||
| fi | ||||
| # get current output public IPs and their revers DNS record | ||||
| PUBLICIP4=`timeout 6 curl -s -4 $publicip_api 2>/dev/null` | ||||
| if [[ $PUBLICIP4 ]];then | ||||
|     IP4PTR=`timeout 4 dig +short -x $PUBLICIP4 @1.1.1.1 2>/dev/null` | ||||
|     if [[ ! $IP4PTR ]];then | ||||
|         IP4PTR="\e[0;${c_txt}mno data" | ||||
|     fi | ||||
|         else | ||||
|     IP4PTR="\e[0;${c_txt}mno data" | ||||
|     PUBLICIP4="\e[1;5;${c_warning}mno IPv4 internet\e[0;${c_txt}m" | ||||
|     INTERNET_IP4=0 | ||||
| fi | ||||
| PUBLICIP6=`timeout 6 curl -s -6 $publicip_api 2>/dev/null` | ||||
| if [[ $PUBLICIP6 ]];then | ||||
|     IP6PTR=`timeout 4 dig +short -x $PUBLICIP6 @1.1.1.1 2>/dev/null` | ||||
|     if [[ ! $IP6PTR ]];then | ||||
|         IP6PTR="\e[0;${c_txt}mno data" | ||||
|     fi | ||||
| else | ||||
|     IP6PTR="\e[0;${c_txt}mno data" | ||||
|     PUBLICIP6="\e[1;${c_warning}mno ipv6 internet\e[0;${c_txt}m" | ||||
|     INTERNET_IP6=0 | ||||
| fi | ||||
| INTERNET_OUT=0 | ||||
| if [[ $INTERNET_IP4 && $INTERNET_IP6 ]]; then | ||||
|     INTERNET_OUT=1 | ||||
| fi | ||||
| # get DNS records of the FQDN | ||||
| HOSTNAMEIP4=`timeout 4 dig +short A $HOSTNAME @1.1.1.1 2>/dev/null` | ||||
| if [[ ! $HOSTNAMEIP4 ]];then | ||||
|     HOSTNAMEIP4="\e[0;${c_txt}mno data" | ||||
| fi | ||||
| HOSTNAMEIP6=`timeout 4 dig +short AAAA $HOSTNAME @1.1.1.1 2>/dev/null` | ||||
| if [[ ! $HOSTNAMEIP6 ]];then | ||||
|     HOSTNAMEIP6="\e[0;${c_txt}mno data" | ||||
| fi | ||||
| # get processes | ||||
| PROCESS=`/usr/bin/ps -eo user= | sort | uniq -c | awk '{ print $2 " " $1 }'` | ||||
| PROCESS_ALL=`echo "$PROCESS" | awk {'print $2'} | awk '{ SUM += $1} END { print SUM }'` | ||||
| PROCESS_ROOT=`echo "$PROCESS" | /usr/bin/grep root | awk {'print $2'}` | ||||
| PROCESS_USER=`echo "$PROCESS" | /usr/bin/grep -v root | awk {'print $2'} | awk '{ SUM += $1} END { print SUM }'` | ||||
| # get processors | ||||
| PROCESSOR_NAME=`/usr/bin/grep "model name" /proc/cpuinfo | cut -d ' ' -f3- | awk {'print $0'} | head -1 | sed -e 's/([^()]*)/ /g' -e 's/\s\+/ /g'` | ||||
| PROCESSOR_COUNT=`/usr/bin/grep -ioPc 'processor\t:' /proc/cpuinfo 2>/dev/null` | ||||
| # get load averages | ||||
| IFS=" " read LOAD1 LOAD5 LOAD15 <<<$(cat /proc/loadavg | awk '{ print $1,$2,$3 }') | ||||
| if [[ $(echo "$LOAD1 > $(echo "$PROCESSOR_COUNT + ($PROCESSOR_COUNT / 3)" | bc -l )" | bc) == 1 ]]; then | ||||
|     LOAD1="\e[1;5;${c_danger}m$LOAD1\e[0;${c_txt}m" | ||||
| elif [[ $(echo "$LOAD1 > $(echo "$PROCESSOR_COUNT - ($PROCESSOR_COUNT / 3)" | bc -l )" | bc) == 1 ]]; then | ||||
|     LOAD1="\e[1;5;${c_warning}m$LOAD1\e[0;${c_txt}m" | ||||
| fi | ||||
| if [[ $(echo "$LOAD5 > $(echo "$PROCESSOR_COUNT * 2" | bc -l )" | bc) == 1 ]]; then | ||||
|     LOAD2="\e[1;5;${c_warning}m$LOAD5\e[0;${c_txt}m" | ||||
| fi | ||||
| if [[ $(echo "$LOAD15 > $(echo "$PROCESSOR_COUNT * 2" | bc -l )" | bc) == 1 ]]; then | ||||
|     LOAD3="\e[1;5;${c_warning}m$LOAD15\e[0;${c_txt}m" | ||||
| fi | ||||
| # get free memory | ||||
| IFS=" " read USED AVAIL TOTAL <<<$(free -htm | /usr/bin/grep "Mem" | awk {'print $3,$7,$2'}) | ||||
| # get free swap | ||||
| IFS=" " read SUSED SAVAIL STOTAL <<<$(free -htm | /usr/bin/grep "Swap" | awk {'print $3,$4,$2'}) | ||||
| 
 | ||||
| # OUTPUT ############################################################ | ||||
| 
 | ||||
| W="\e[0;${c_txt}m" | ||||
| X="\e[1;${c_txt}m" | ||||
| G="\e[1;${c_txt_emphase}m" | ||||
| N="\e[0m" | ||||
| echo -e "\e[1A\e[${c_title} System information  $N                     | ||||
| 
 | ||||
| $X  Distro$W..........: $DISTRO | ||||
| $X  Kernel$W..........: `uname -sr` | ||||
| $X  Uptime$W..........: $G`uptime -p`$W | ||||
| 
 | ||||
| $X  CPU$W.............: $PROCESSOR_NAME | ||||
| $X  CPU cores$W.......: $G$PROCESSOR_COUNT$W | ||||
| $X  Load$W............: $G$LOAD1$W (1m), $G$LOAD5$W (5m), $G$LOAD15$W (15m) | ||||
| $X  Processes$W.......: $G$PROCESS_ROOT$W (root), $G$PROCESS_USER$W (user), $G$PROCESS_ALL$W (total) | ||||
| $X  Memory$W..........: $G$USED$W used, $G$AVAIL$W avail, $G$TOTAL$W total$N" | ||||
| if [[ ${SUSED} ]]; then | ||||
|     echo -e "$X  Swap$W............: $G$SUSED$W used, $G$SAVAIL$W avail, $G$STOTAL$W total$W" | ||||
| else | ||||
|     echo -e "$X  Swap$W............: \e[1;${c_warning}mno Swap$W" | ||||
| fi | ||||
| echo -e " | ||||
| $X  Hostname/FQDN$W...: $G$(hostname)$W / $G$(hostname -f)$W | ||||
| $X  Internet Iface$W..: $G$INTERNETIFACE$W | ||||
| $X  DNS servers$W.....: $G$(echo -e "${DNSSERVERS}" | sed "s/,/\\\e[0m, \\\e[1;${c_txt_emphase}m/g")$N" | ||||
| if [[ ${INTERNET_OUT} == 0 ]]; then | ||||
|     echo -e "$X  Public IP4/IP6$W..: $G$PUBLICIP4$W / $G$PUBLICIP6$N" | ||||
| else | ||||
|     echo -e "$X  Public IP4/IP6$W..: \e[1;${c_warning}mno internet or "${publicip_api}" timeout$N" | ||||
| fi | ||||
| echo -e "$X  PTR IP4/IP6$W.....: $G$IP4PTR$W / $G$IP6PTR$W | ||||
| $X  FQDN A/AAAA$W.....: $G$HOSTNAMEIP4$W / $G$HOSTNAMEIP6$N" | ||||
							
								
								
									
										143
									
								
								motdfetch.d/02-services
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										143
									
								
								motdfetch.d/02-services
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,143 @@ | |||
| #!/usr/bin/env bash | ||||
| # | ||||
| # check status of a list of systemd service units | ||||
| # + accept service name with or without extension (.service) | ||||
| # + default to system wide services but accept --user services with the :uid | ||||
| # + alarm by bullet coloration and blinking | ||||
| # | ||||
| # requirements: systemd | ||||
| 
 | ||||
| # GENERAL ########################################################### | ||||
| 
 | ||||
| # locale env | ||||
| unset LC_ALL | ||||
| export LC_MESSAGES=C | ||||
| 
 | ||||
| # check if module was disabled | ||||
| module_disable=${module_services_disable:=0} | ||||
| if (($module_disable == 1)); then | ||||
|     exit 1 | ||||
| fi | ||||
| 
 | ||||
| # colors | ||||
| c_txt=${c_txt:="39"} | ||||
| c_txt_emphase=${c_txt_emphase:="35"} | ||||
| c_txt_deco=${c_txt_deco:="97"} | ||||
| c_txt_invert=${c_txt_invert:="30"} | ||||
| c_bg=${c_bg_sec:="47"} | ||||
| c_danger=${c_danger:="31"} | ||||
| c_warning=${c_warning:="33"} | ||||
| c_success=${c_success:="32"} | ||||
| c_title=${c_title:="${c_bg};1;${c_txt_invert}m"} | ||||
| 
 | ||||
| # OPTIONS ########################################################### | ||||
| 
 | ||||
| # array of services | ||||
| if [[ $module_services ]]; then | ||||
|     services=(${module_services[@]}) | ||||
| else | ||||
|     services=("cron.service" "dbus.service:1000" "user2service:1002") | ||||
| fi | ||||
| IFS=$'\n' services=($(sort <<<"${services[*]}")) | ||||
| unset IFS | ||||
| 
 | ||||
| # column max-width | ||||
| width=${module_services_width:="80"} | ||||
| 
 | ||||
| # PREPARATIONS ###################################################### | ||||
| 
 | ||||
| # get status | ||||
| # + dim status if the service does not exist or if the user is not root and the service has another uid | ||||
| serviceStatus=() | ||||
| for service in "${services[@]}"; do | ||||
|     uid=${service/*:/} | ||||
|     # script executed as root and the service to check is from a user | ||||
|     if [[ $service = *:* ]] && [[ "$(id -u)" == "0" ]]; then | ||||
|         service=${service/.service/} | ||||
|         service=${service/:[0-9]*/} | ||||
|         serviceexist=$(machinectl -q shell --uid="$uid" .host /usr/bin/systemctl list-units --user -q --plain --no-pager --full --all -t service 2>/dev/null \ | ||||
|             | awk '$1 ~ /\.service$/ { sub("\\.service$", "", $1); print $1 }' \ | ||||
|             | /usr/bin/grep "$service") | ||||
|         if [[ "$serviceexist" ]] ;then | ||||
|             status=$(machinectl -q shell --uid="$uid" .host /usr/bin/systemctl is-active --user "$service") | ||||
|             if [[ $status = inactive* ]]; then | ||||
|                 serviceStatus+=("inactive") | ||||
|             elif [[ $status = active* ]]; then | ||||
|                 serviceStatus+=("active") | ||||
|             else | ||||
|                 serviceStatus+=("hidden") | ||||
|             fi | ||||
|         else | ||||
|             serviceStatus+=("hidden") | ||||
|         fi | ||||
|     # script executed by the same user as the service user | ||||
|     elif [[ $service = *:* ]] && [[ "$(id -u)" == "$uid" ]]; then | ||||
|         service=${service/.service/} | ||||
|         service=${service/:[0-9]*/} | ||||
|         serviceexist=$(/usr/bin/systemctl list-units --user -q --plain --no-pager --full --all -t service 2>/dev/null \ | ||||
|             | awk '$1 ~ /\.service$/ { sub("\\.service$", "", $1); print $1 }' \ | ||||
|             | /usr/bin/grep "$service") | ||||
|         if [[ "$serviceexist" ]] ;then | ||||
|             serviceStatus+=($(/usr/bin/systemctl --user is-active "$service")) | ||||
|         else | ||||
|             serviceStatus+=("hidden") | ||||
|         fi | ||||
|     # script executed by another user than root and than the service user | ||||
|     elif [[ $service = *:* ]]; then | ||||
|         serviceStatus+=("hidden") | ||||
|     # system service | ||||
|     else | ||||
|         service=${service/.service/} | ||||
|         service=${service/:[0-9]*/} | ||||
|         serviceexist=$(/usr/bin/systemctl list-units -q --plain --no-pager --full --all -t service 2>/dev/null \ | ||||
|             | awk '$1 ~ /\.service$/ { sub("\\.service$", "", $1); print $1 }' \ | ||||
|             | /usr/bin/grep "$service") | ||||
|         if [[ "$serviceexist" ]] ;then | ||||
|             serviceStatus+=($(/usr/bin/systemctl is-active "$service")) | ||||
|         else | ||||
|             serviceStatus+=("hidden") | ||||
|         fi | ||||
|     fi | ||||
| done | ||||
| 
 | ||||
| # OUTPUT ############################################################ | ||||
| 
 | ||||
| # output header | ||||
| echo -e "\n\e[${c_title} Services checks  \e[0m\n" | ||||
| 
 | ||||
| # output checklist | ||||
| line=" " | ||||
| lineLen=1 | ||||
| for i in "${!serviceStatus[@]}" | ||||
| do | ||||
|     service=${services[$i]/.service/} | ||||
|     service=${service^} | ||||
| 
 | ||||
|     # Next line and next line length | ||||
|     next="   $service " | ||||
|     nextLen=$((1+${#next})) | ||||
| 
 | ||||
|     # If the current line will exceed the max column with then echo and start a new line | ||||
|     if [[ $((lineLen+nextLen)) -gt $width ]]; then | ||||
|         echo -e "$line" | ||||
|         lineLen=1 | ||||
|         line=" " | ||||
|     fi | ||||
| 
 | ||||
|     lineLen=$((lineLen+nextLen)) | ||||
| 
 | ||||
|     # Color the next line green if it's active, red if inactive, else orange | ||||
|     if [[ "${serviceStatus[$i]}" == "active" ]] | ||||
|     then | ||||
|         line+=" \e[${c_success}m●\e[0m \e[${c_txt}m$service\e[0m " | ||||
|     elif [[ "${serviceStatus[$i]}" == "inactive" ]] | ||||
|     then | ||||
|         line+=" \e[1;5;${c_danger}m▲\e[0m \e[1;${c_txt}m$service\e[0m " | ||||
|     else | ||||
|         line+=" \e[1;2;${c_warning}m▲\e[0m \e[1;2;${c_txt}m$service\e[0m " | ||||
|     fi | ||||
| done | ||||
| 
 | ||||
| # echo what is left | ||||
| echo -e "$line" | ||||
| 
 | ||||
							
								
								
									
										227
									
								
								motdfetch.d/03-filesystem
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										227
									
								
								motdfetch.d/03-filesystem
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,227 @@ | |||
| #!/usr/bin/env bash | ||||
| # | ||||
| # status of mounted filesystems in 2 steps | ||||
| #     1. use "df" for general fs except zfs, squashfs, tmpfs, devtmpfs and overlay | ||||
| #     2. use "zpool" for ZFS pools | ||||
| # + displays name, filesystem type, used blocks and inodes or pool health when relevant | ||||
| # + custom warn threshold for blocks | ||||
| # + warn threshold for inodes (80%), flashing danger threshold for health, blocks (95%) and inodes (90%) | ||||
| # | ||||
| # requirements: sudo apt install coreutils | ||||
| # optionnal:    sudo apt install zfsutils-linux | ||||
| 
 | ||||
| # GENERAL ########################################################### | ||||
| 
 | ||||
| # locale env | ||||
| unset LC_ALL | ||||
| export LC_MESSAGES=C | ||||
| 
 | ||||
| # check if module was disabled | ||||
| module_disable=${module_filesystem_disable:=0} | ||||
| if (($module_disable == 1)); then | ||||
|     exit 1 | ||||
| fi | ||||
| 
 | ||||
| # colors | ||||
| c_txt=${c_txt:="39"} | ||||
| c_txt_emphase=${c_txt_emphase:="35"} | ||||
| c_txt_deco=${c_txt_deco:="97"} | ||||
| c_txt_invert=${c_txt_invert:="30"} | ||||
| c_bg=${c_bg_sec:="47"} | ||||
| c_danger=${c_danger:="31"} | ||||
| c_warning=${c_warning:="33"} | ||||
| c_success=${c_success:="32"} | ||||
| c_title=${c_title:="${c_bg};1;${c_txt_invert}m"} | ||||
| 
 | ||||
| # OPTIONS ########################################################### | ||||
| 
 | ||||
| # max usage warning threshold | ||||
| max_usage=${module_filesystem_max_usage:="85"} | ||||
| 
 | ||||
| # disable ZFS section | ||||
| zfs_disable=${module_filesystem_zfs_disable:=0} | ||||
| 
 | ||||
| # PREPARATIONS ###################################################### | ||||
| 
 | ||||
| # disk usage: ignore zfs, squashfs & tmpfs, standard error output because of a bug with /run/user/1000/doc | ||||
| dfcmd=$(/usr/bin/df -H -x zfs -x squashfs -x tmpfs -x devtmpfs -x overlay --output 2>/dev/null) | ||||
| mapfile -t dfoutput < <(echo "$dfcmd" | tail -n+2) | ||||
| 
 | ||||
| # determine best width for the bar | ||||
| largesttarget=$(echo "$dfcmd" | awk '{if (length ($12)>max) max=length($12)} END {print max}') | ||||
| if [[ $((largesttarget+30)) -gt 50 ]]; then | ||||
|     bar_width=$((largesttarget+30)) | ||||
| else | ||||
|     bar_width="50" | ||||
| fi | ||||
| 
 | ||||
| # OUTPUT ############################################################ | ||||
| 
 | ||||
| # general filesystems | ||||
| linecounter=0 | ||||
| if [[ "${dfoutput[@]}" ]]; then | ||||
|     # output header | ||||
|     echo -e "\n\e[${c_title} Filesystem usage  \e[0m\n" | ||||
|     # output filesystem status except ZFS | ||||
|     for line in "${dfoutput[@]}"; do | ||||
|         # parse df output | ||||
|         diskid=$(echo "$line" | awk '{print $12}') | ||||
|         diskused=$(echo "$line" | awk '{print $10}'| sed 's/%//') | ||||
|         disktotal=$(echo "$line" | awk '{print $7}') | ||||
|         fsformat=$(echo "$line" | awk '{print $2}') | ||||
|         inodesused=$(echo "$line" | awk '{print $6}'| sed 's/%//') | ||||
|         inodestotal=$(echo "$line" | awk '{print $3}') | ||||
|          | ||||
|         # bar & blocks coloration, danger red above 95% | ||||
|         if [[ "${diskused}" -ge "95" ]]; then | ||||
|             barcolor="\e[1;${c_danger}m" | ||||
|             blockscolor="\e[1;${c_danger}m" | ||||
|             flashing="\e[5m" | ||||
|         elif [ "${diskused}" -ge "${max_usage}" ]; then | ||||
|             barcolor="\e[1;${c_warning}m" | ||||
|             blockscolor="\e[1;${c_warning}m" | ||||
|             flashing="" | ||||
|         else | ||||
|             barcolor="\e[1;${c_success}m" | ||||
|             blockscolor="\e[${c_txt}m" | ||||
|             flashing="" | ||||
|         fi | ||||
|         # print colored bar until used_width | ||||
|         used_width=$(((diskused*$bar_width)/100)) | ||||
|         bar="[${barcolor}" | ||||
|         for ((i=0; i<$used_width; i++)); do | ||||
|             bar+="=" | ||||
|         done | ||||
|         # print dimmmed bar until end | ||||
|         bar+="\e[${c_txt}m\e[0m" | ||||
|         for ((i=$used_width; i<$bar_width; i++)); do | ||||
|             bar+="=" | ||||
|         done | ||||
|         bar+="\e[0m]" | ||||
|          | ||||
|         # print blocks usage line & bar | ||||
|         padding=$((bar_width-28)) | ||||
|         if [[ $linecounter -ge 1 ]] | ||||
|         then | ||||
|             echo -e "\n" | ||||
|         fi | ||||
|         echo "${line}" | printf "\e[1;${c_txt_emphase}m%-${padding}s\e[0m${blockscolor}%+3s%% used ${flashing}blocks\e[0m out of %+4s\n" $diskid $diskused $disktotal | sed 's/^/   /' | ||||
|         echo -e "${bar}" | sed 's/^/  /' | ||||
|          | ||||
|         # print filesystem type & inodes usage line | ||||
|         if [[ ! "$inodesused" == "-" ]] | ||||
|         then | ||||
|             padding=$((bar_width-34)) | ||||
|             # inodes coloration, danger red above 90% | ||||
|             if [[ "${inodesused}" -ge "90" ]]; then | ||||
|                 inodescolor="\e[1;${c_danger}m" | ||||
|                 flashing="\e[5m" | ||||
|             elif [[ "${inodesused}" -ge "80" ]]; then | ||||
|                 inodescolor="\e[1;${c_warning}m" | ||||
|                 flashing="" | ||||
|             else | ||||
|                 inodescolor="\e[${c_txt}m" | ||||
|                 flashing="" | ||||
|             fi | ||||
|             echo "${line}" | printf "Type: %-${padding}s${inodescolor}%+3s%% used ${flashing}inodes\e[0m out of %+4s\n" $fsformat $inodesused $inodestotal | sed 's/^/   /' | ||||
|         else | ||||
|             echo "${line}" | printf "Type: %-10s\n" $fsformat | sed 's/^/   /' | ||||
|         fi | ||||
|         linecounter=$((linecounter+1)) | ||||
|     done | ||||
| else | ||||
|     echo "  no general filesystem available, ZFS expected in next section" | ||||
| fi | ||||
| 
 | ||||
| # check if ZFS section was disabled | ||||
| if [[ $zfs_disable == 1 ]]; then | ||||
|     exit 1 | ||||
| fi | ||||
| 
 | ||||
| # output ZFS header | ||||
| echo -e "\n\e[${c_title} Zpool usage  \e[0m\n" | ||||
| 
 | ||||
| # check if zpool is available | ||||
| if ! command -v zpool 1> /dev/null; then | ||||
|     echo "  no ZFS tools available" | ||||
|     exit 1 | ||||
| fi | ||||
| 
 | ||||
| # ZFS zpool usage & health status | ||||
| zlistcmd=$(zpool list -o name,cap,size,health 2> /dev/null) | ||||
| if [[ $zlistcmd == "no pools available" ]]; then | ||||
|     echo "  no ZFS pool available" | ||||
| else | ||||
|     mapfile -t zpools < <(echo "$zlistcmd" | tail -n+2) | ||||
|      | ||||
|     # determine best width for the bar | ||||
|     largesttarget=$(echo "zlistcmd" | awk '{if (length ($1)>max) max=length($1)} END {print max}') | ||||
|     if [[ $((largesttarget+30)) -gt 50 ]]; then | ||||
|         bar_width=$((largesttarget+30)) | ||||
|     else | ||||
|         bar_width="50" | ||||
|     fi | ||||
|      | ||||
|     linecounter=0 | ||||
|     for line in "${zpools[@]}"; do | ||||
|         # parse zpool list output | ||||
|         poolid=$(echo "$line" | awk '{print $1}') | ||||
|         poolused=$(echo "$line" | awk '{print $2}'| sed 's/%//') | ||||
|         pooltotal=$(echo "$line" | awk '{print $3}') | ||||
|         poolhealth=$(echo "$line" | awk '{print $4}') | ||||
|                      | ||||
|         # bar & pools coloration, danger red above 95% | ||||
|         if [[ "${poolused}" -ge "95" ]]; then | ||||
|             barcolor="\e[1;${c_danger}m" | ||||
|             poolscolor="\e[1;${c_danger}m" | ||||
|             flashing="\e[5m" | ||||
|         elif [[ "${poolused}" -ge "${max_usage}" ]]; then | ||||
|             barcolor="\e[1;${c_warning}m" | ||||
|             poolscolor="\e[1;${c_warning}m" | ||||
|             flashing="" | ||||
|         else | ||||
|             barcolor="\e[1;${c_success}m" | ||||
|             poolscolor="\e[${c_txt}m" | ||||
|             flashing="" | ||||
|         fi | ||||
|         # print colored bar until used_width | ||||
|         used_width=$(((poolused*$bar_width)/100)) | ||||
|         bar="[${barcolor}" | ||||
|         for ((i=0; i<$used_width; i++)); do | ||||
|             bar+="=" | ||||
|         done | ||||
|         # print dimmmed bar until end | ||||
|         bar+="\e[${c_txt}m\e[0m" | ||||
|         for ((i=$used_width; i<$bar_width; i++)); do | ||||
|             bar+="=" | ||||
|         done | ||||
|         bar+="\e[0m]" | ||||
|          | ||||
|         # print pool usage line & bar | ||||
|         padding=$((bar_width-29)) | ||||
|         if [[ $linecounter -ge 1 ]] | ||||
|         then | ||||
|             echo -e "\n" | ||||
|         fi | ||||
|         echo "${line}" | printf "\e[1;${c_txt_emphase}m%-${padding}s\e[0m${poolscolor}%+3s%% used ${flashing}blocks\e[0m out of %+5s\n" $poolid $poolused $pooltotal | sed 's/^/   /' | ||||
|         echo -e "${bar}" | sed 's/^/  /' | ||||
|          | ||||
|         # print pool health line | ||||
|         padding=$((bar_width-34)) | ||||
|         # health coloration, danger red for FAULTED | ||||
|         if [[ "${poolhealth}" == "FAULTED" ]]; then | ||||
|                healthcolor="\e[1;${c_danger}m" | ||||
|                flashing="\e[5m" | ||||
|         elif [[ "${poolhealth}" == "OFFLINE" ]] || [[ "${poolhealth}" == "UNAVAIL" ]] || [[ "${poolhealth}" == "REMOVED" ]] || [[ "${poolhealth}" == "DEGRADED" ]]; then | ||||
|                healthcolor="\e[1;${c_warning}m" | ||||
|                flashing="" | ||||
|         else | ||||
|                healthcolor="\e[${c_txt}m" | ||||
|                flashing="" | ||||
|         fi | ||||
|         padding=$((bar_width-17)) | ||||
|         text="health" | ||||
|         echo "${line}" | printf "%+${padding}s status: ${healthcolor}${flashing}%+8s\e[0m\n" $text ${poolhealth,,} | sed 's/^/   /' | ||||
|         linecounter=$((linecounter+1)) | ||||
|     done | ||||
| fi | ||||
							
								
								
									
										119
									
								
								motdfetch.d/04-tls
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										119
									
								
								motdfetch.d/04-tls
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,119 @@ | |||
| #!/usr/bin/env bash | ||||
| # | ||||
| # check X.509 cert for a domain:port with openssl, for correspondance and expiration | ||||
| # + by default the port is 443 | ||||
| # + there is a timeout of 6 sec and is there is no connectivity the check is skipped | ||||
| # | ||||
| # requirements: sudo apt install openssl | ||||
| 
 | ||||
| # GENERAL ########################################################### | ||||
| 
 | ||||
| # locale env | ||||
| unset LC_ALL | ||||
| export LC_MESSAGES=C | ||||
| 
 | ||||
| # check if module was disabled | ||||
| module_disable=${module_tls_disable:=0} | ||||
| if (($module_disable == 1)); then | ||||
|     exit 1 | ||||
| fi | ||||
| 
 | ||||
| # colors | ||||
| c_txt=${c_txt:="39"} | ||||
| c_txt_emphase=${c_txt_emphase:="35"} | ||||
| c_txt_deco=${c_txt_deco:="97"} | ||||
| c_txt_invert=${c_txt_invert:="30"} | ||||
| c_bg=${c_bg_sec:="47"} | ||||
| c_danger=${c_danger:="31"} | ||||
| c_warning=${c_warning:="33"} | ||||
| c_success=${c_success:="32"} | ||||
| c_title=${c_title:="${c_bg};1;${c_txt_invert}m"} | ||||
| 
 | ||||
| # api website name for plain public IP4/6 check | ||||
| publicip_api=${global_publicip_api:="icanhazip.com"} | ||||
| 
 | ||||
| # OPTIONS ########################################################### | ||||
| 
 | ||||
| # domains:ports input | ||||
| if [[ $module_tls_domains ]] | ||||
| then | ||||
|     tls_domains=(${module_tls_domains[@]}) | ||||
| else | ||||
|     tls_domains=("www.google.com" "smtp.gmail.com:465") | ||||
| fi | ||||
| IFS=$'\n' tls_domains=($(sort <<<"${tls_domains[*]}")) | ||||
| unset IFS | ||||
| 
 | ||||
| # PREPARATIONS ###################################################### | ||||
| 
 | ||||
| # print loading message | ||||
| echo -e "\nWaiting for TLS checks\e[5m...\e[0m" | ||||
| 
 | ||||
| # parse output | ||||
| output="    \e[1;4;${c_txt}mDomain\e[24m|\e[4mPort\e[24m|\e[4mValid until\e[0m" | ||||
| currentTime=$(date +%s) | ||||
| 
 | ||||
| # check if there is internet connectivity | ||||
| INTERNET_OUT=0 | ||||
| PUBLICIP="$(timeout 6 curl -s $publicip_api 2>/dev/null)" | ||||
| if [[ ! $PUBLICIP ]]; then | ||||
|     INTERNET_OUT=1 | ||||
| fi | ||||
| 
 | ||||
| # OUTPUT ############################################################ | ||||
| 
 | ||||
| for domain in "${tls_domains[@]}" | ||||
| do | ||||
|     if [[ $domain == *:* ]] | ||||
|     then | ||||
|         port=${domain/*:/} | ||||
|         domain=${domain/:*/} | ||||
|     else | ||||
|         port="443" | ||||
|     fi | ||||
|     if [[ $INTERNET_OUT == 0 ]]; then | ||||
|         # fetch cert | ||||
|         cert="" | ||||
|         cert=$(timeout 6 openssl s_client -servername ${domain} -connect ${domain}:${port} < /dev/null 2>/dev/null) | ||||
|         # fetch subject name with a 3 sec timeout | ||||
|         certSubj=$(echo -e "$cert" | openssl x509 -noout -subject 2>/dev/null) | ||||
|         # fetch expiration time | ||||
|         certTime=$(echo -e "$cert" | openssl x509 -noout -enddate 2>/dev/null | cut -d= -f2) | ||||
|         certLineTime=$(date -d "${certTime}" +"%F") | ||||
|         certTimestamp=$(date -d "${certTime}" +%s) | ||||
|         port="\e[${c_txt}m${port}\e[0m" | ||||
|         # check subject name with a 3 sec timeout | ||||
|         if [[ $certSubj == *${domain} ]] | ||||
|         then | ||||
|             domain="\e[${c_txt}m${domain}\e[0m" | ||||
|             # check expiration time - 3 days | ||||
|             if [[ "$((${certTimestamp} - 259200 ))" -ge "${currentTime}" ]] | ||||
|             then | ||||
|                 sign="\e[${c_success}m●\e[0m" | ||||
|                 result="\e[1;${c_success}m$certLineTime\e[0m" | ||||
|             # check expiration time today | ||||
|             elif [[ "${certTimestamp}" -ge "${currentTime}" ]] | ||||
|             then | ||||
|                 sign="\e[1;${c_warning}m▲\e[0m" | ||||
|                 result="\e[1;${c_warning}m${certLineTime}\e[0m" | ||||
|             else | ||||
|                 sign="\e[1;5;${c_danger}m▲\e[0m" | ||||
|                 result="\e[1;${c_danger}m$certLineTime\e[0m" | ||||
|             fi | ||||
|         else | ||||
|             domain="\e[${c_txt}m${domain}\e[0m" | ||||
|             sign="\e[1;2;${c_warning}m\U25B2\e[0m" | ||||
|             result="\e[1;2;${c_warning}mtimeout or misnamed\e[0m" | ||||
|         fi | ||||
|     elif [[ $INTERNET_OUT == 1 ]]; then | ||||
|         domain="\e[${c_txt}m${domain}\e[0m" | ||||
|         sign="\e[1;2;${c_txt}m▲\e[0m" | ||||
|         result="\e[1;2;${c_txt}mno internet, skipped\e[0m" | ||||
|     fi | ||||
|     output+="\n  ${sign} ${domain}|${port}|$result" | ||||
| done | ||||
| 
 | ||||
| # output header and table content | ||||
| echo -e "\e[1A\e[${c_title} TLS checks  \e[0m                    " | ||||
| echo -e  | ||||
| echo -e "$output" | column -t -s '|' | ||||
							
								
								
									
										74
									
								
								motdfetch.d/05-postqueue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								motdfetch.d/05-postqueue
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,74 @@ | |||
| #!/usr/bin/env bash | ||||
| # | ||||
| # check if there is some mails in the deferred queue of postfix | ||||
| # + danger color if >= 100 messages | ||||
| # + warning color if >= 1 messages | ||||
| # | ||||
| # requirements: sudo apt install postfix | ||||
| 
 | ||||
| # GENERAL ########################################################### | ||||
| 
 | ||||
| # locale env | ||||
| unset LC_ALL | ||||
| export LC_MESSAGES=C | ||||
| 
 | ||||
| # check if module was disabled | ||||
| module_disable=${module_postqueue_disable:=0} | ||||
| if (($module_disable == 1)); then | ||||
|     exit 1 | ||||
| fi | ||||
| 
 | ||||
| # colors | ||||
| c_txt=${c_txt:="39"} | ||||
| c_txt_emphase=${c_txt_emphase:="35"} | ||||
| c_txt_deco=${c_txt_deco:="97"} | ||||
| c_txt_invert=${c_txt_invert:="30"} | ||||
| c_bg=${c_bg_sec:="47"} | ||||
| c_danger=${c_danger:="31"} | ||||
| c_warning=${c_warning:="33"} | ||||
| c_success=${c_success:="32"} | ||||
| c_title=${c_title:="${c_bg};1;${c_txt_invert}m"} | ||||
| 
 | ||||
| # PREPARATIONS ###################################################### | ||||
| 
 | ||||
| # print loading message | ||||
| echo -e "\nWaiting for Postqueue checks\e[5m...\e[0m" | ||||
| 
 | ||||
| # check if postfix is available, with qshape | ||||
| if ! command -v qshape 1>/dev/null; then | ||||
|     # output module header | ||||
|     echo -e "\e[1A\e[${c_title} Postfix deferred queue status  \e[0m\n" | ||||
|     echo -e "  no Postfix server available" | ||||
|     exit 1 | ||||
| fi | ||||
| 
 | ||||
| # parse deferred messages qty with qshape | ||||
| deferredcmd=$(timeout 5 qshape -b 6 deferred 2>/dev/null) | ||||
| 
 | ||||
| # OUTPUT ############################################################ | ||||
| 
 | ||||
| # if qshape timeout 5sec | ||||
| if [[ "$deferredcmd" == "" ]]; then | ||||
|     # output module header | ||||
|     echo -e "\e[1A\e[${c_title} Postfix deferred  \e[0m\n" | ||||
|     echo -e "  \e[1;${c_warning}mqshape needs more than 5 sec to parse the deferred Mails list,\n  you should investigate!\e[0m" | ||||
|     exit 1 | ||||
| fi | ||||
| 
 | ||||
| # if total deferred is 0 | ||||
| deferredtotal=$(echo -e "$deferredcmd" | grep TOTAL | awk '{print $2}') | ||||
| if [[ "$deferredtotal" == "0" ]]; then | ||||
|     # output module header | ||||
|     echo -e "\e[1A\e[${c_title} Postfix deferred queue status  \e[0m\n" | ||||
|     echo -e "  There is \e[1;${c_success}m${deferredtotal}\e[0m deferred Mails." | ||||
|     exit 1 | ||||
| fi | ||||
| 
 | ||||
| # else print qshape output | ||||
| # output module header | ||||
| echo -e "\e[1A\e[${c_title} Postfix deferred queue status  \e[0m\n" | ||||
| if [[ "$deferredtotal" -gt 100 ]]; then | ||||
|     echo -e "  There is \e[1;${c_danger}m${deferredtotal}\e[0m deferred Mails in queue." | ||||
| else | ||||
|     echo -e "  There is \e[1;${c_warning}m${deferredtotal}\e[0m deferred Mails in queue." | ||||
| fi | ||||
							
								
								
									
										77
									
								
								motdfetch.d/06-fail2ban
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								motdfetch.d/06-fail2ban
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,77 @@ | |||
| #!/usr/bin/env bash | ||||
| # | ||||
| # parse Fail2ban jail status, display failed and banned counts | ||||
| # + Warning if currently more than 0 | ||||
| # + Danger  if currently more than 20 | ||||
| #  | ||||
| # /!\ need root to display status, display warning for other user | ||||
| # | ||||
| # requirements: sudo apt install fail2ban | ||||
| 
 | ||||
| # GENERAL ########################################################### | ||||
| 
 | ||||
| # locale env | ||||
| unset LC_ALL | ||||
| export LC_MESSAGES=C | ||||
| 
 | ||||
| # check if module was disabled | ||||
| module_disable=${module_fail2ban_disable:=0} | ||||
| if (($module_disable == 1)); then | ||||
|     exit 1 | ||||
| fi | ||||
| 
 | ||||
| # colors | ||||
| c_txt=${c_txt:="39"} | ||||
| c_txt_emphase=${c_txt_emphase:="35"} | ||||
| c_txt_deco=${c_txt_deco:="97"} | ||||
| c_txt_invert=${c_txt_invert:="30"} | ||||
| c_bg=${c_bg_sec:="47"} | ||||
| c_danger=${c_danger:="31"} | ||||
| c_warning=${c_warning:="33"} | ||||
| c_success=${c_success:="32"} | ||||
| c_title=${c_title:="${c_bg};1;${c_txt_invert}m"} | ||||
| 
 | ||||
| # PREPARATIONS ###################################################### | ||||
| 
 | ||||
| # check if fail2ban is available | ||||
| if ! command -v fail2ban-client 1>/dev/null; then | ||||
|     # output module header | ||||
|     echo -e "\n\e[${c_title} Fail2Ban status  \e[0m\n" | ||||
|     echo -e "  no Fail2Ban server available" | ||||
|     exit 1 | ||||
| elif [[ ! `id -un` == "root" ]]; then | ||||
|     echo -e "\n\e[${c_title} Fail2Ban status  \e[0m\n" | ||||
|     echo -e "  you must be root to get Fail2Ban status" | ||||
|     exit 1 | ||||
| fi | ||||
| 
 | ||||
| # OUTPUT ############################################################ | ||||
| 
 | ||||
| echo -e "\n\e[${c_title} Fail2Ban status  \e[0m\n" | ||||
| 
 | ||||
| # fail2ban-client status to get all jails, takes about ~70ms | ||||
| jails=($(fail2ban-client status | grep "Jail list:" | sed "s/ //g" | awk '{split($2,a,",");for(i in a) print a[i]}')) | ||||
| 
 | ||||
| out="\e[1;4;${c_txt}mJail name\e[24m,\e[4mFailed\e[24m,\e[4mTotal\e[24m,\e[4mBanned\e[24m,\e[4mTotal\e[24m\n" | ||||
| 
 | ||||
| for jail in ${jails[@]}; do | ||||
|     # slow because fail2ban-client has to be called for every jail (~70ms per jail) | ||||
|     status=$(fail2ban-client status ${jail}) | ||||
|     failed=$(echo "$status" | grep -ioP '(?<=Currently failed:\t)[[:digit:]]+') | ||||
|     if [[ $failed -ge 20 ]]; then | ||||
|         failed="\e[1;5;${c_danger}m${failed}\e[0m" | ||||
|     elif [[ $failed -ge 1 ]]; then | ||||
|         failed="\e[1;${c_warning}m${failed}\e[0m" | ||||
|     fi | ||||
|     totalfailed=$(echo "$status" | grep -ioP '(?<=Total failed:\t)[[:digit:]]+') | ||||
|     banned=$(echo "$status" | grep -ioP '(?<=Currently banned:\t)[[:digit:]]+') | ||||
|     if [[ $banned -ge 20 ]]; then | ||||
|         banned="\e[1;5;${c_danger}m${banned}\e[0m" | ||||
|     elif [[ $banned -ge 1 ]]; then | ||||
|         banned="\e[1;${c_warning}m${banned}\e[0m" | ||||
|     fi | ||||
|     totalbanned=$(echo "$status" | grep -ioP '(?<=Total banned:\t)[[:digit:]]+') | ||||
|     out+="\e[1;${c_txt_emphase}m${jail}\e[0m,$failed,$totalfailed,$banned,$totalbanned\n" | ||||
| done | ||||
| 
 | ||||
| echo -e "$out" | column -ts $',' | sed 's/^/  /' | ||||
							
								
								
									
										77
									
								
								motdfetch.d/99-userslog
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								motdfetch.d/99-userslog
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,77 @@ | |||
| #!/usr/bin/env bash | ||||
| # | ||||
| # check last user logged in (with host ip and period) and currently logged in users | ||||
| # + if the last logged in is not the current user, add a section about the last login of the curent user | ||||
| 
 | ||||
| # GENERAL ########################################################### | ||||
| 
 | ||||
| # locale env | ||||
| unset LC_ALL | ||||
| export LC_MESSAGES=C | ||||
| 
 | ||||
| # check if module was disabled | ||||
| module_disable=${module_userslog_disable:=0} | ||||
| if (($module_disable == 1)); then | ||||
|     exit 1 | ||||
| fi | ||||
| 
 | ||||
| # colors | ||||
| c_txt=${c_txt:="39"} | ||||
| c_txt_emphase=${c_txt_emphase:="35"} | ||||
| c_txt_deco=${c_txt_deco:="97"} | ||||
| c_txt_invert=${c_txt_invert:="30"} | ||||
| c_bg=${c_bg_sec:="47"} | ||||
| c_danger=${c_danger:="31"} | ||||
| c_warning=${c_warning:="33"} | ||||
| c_success=${c_success:="32"} | ||||
| c_title=${c_title:="${c_bg};1;${c_txt_invert}m"} | ||||
| 
 | ||||
| # PREPARATIONS ###################################################### | ||||
| 
 | ||||
| lastuserlog=$(last -i -F -n 2 | head -2 | tail -1) | ||||
| lastusername=$(echo -e "$lastuserlog" | awk '{print $1}') | ||||
| lastuserhost=$(echo -e "$lastuserlog" | awk '{print $3}') | ||||
| if [[ "$lastuserhost" == "0.0.0.0" ]]; then | ||||
|     lastuserhost="localhost" | ||||
| fi | ||||
| lastusertime=$(echo -e "$lastuserlog" | awk '{$1=$2=$3=""; print $0}' | sed 's/^   //') | ||||
| 
 | ||||
| lastcurrentuserlog=$(last $(id -un) -i -F -n 2 | head -2 | tail -1) | ||||
| lastcurrentusername=$(echo -e "$lastcurrentuserlog" | awk '{print $1}') | ||||
| lastcurrentuserhost=$(echo -e "$lastcurrentuserlog" | awk '{print $3}') | ||||
| if [[ "$lastcurrentuserhost" == "0.0.0.0" ]]; then | ||||
|     lastcurrentuserhost="localhost" | ||||
| fi | ||||
| lastcurrentusertime=$(echo -e "$lastcurrentuserlog" | awk '{$1=$2=$3=""; print $0}' | sed 's/^   //') | ||||
| 
 | ||||
| loggedusers=$(last -i -F -p now | /usr/bin/grep "logged in" | awk '{print $1}') | ||||
| loggedusersnames=$(echo -e "$loggedusers" | uniq -c | sed 's/^\s\+/|/' | tr ' ' '|') | ||||
| loggeduserscount=$(echo -e "$loggedusers" | wc -l) | ||||
| 
 | ||||
| # OUTPUT ############################################################ | ||||
| 
 | ||||
| # header | ||||
| echo -e "\n\e[${c_title} Users log  \e[0m\n" | ||||
| 
 | ||||
| W="\e[0;${c_txt}m" | ||||
| X="\e[1;${c_txt}m" | ||||
| F="\e[0;${c_txt_emphase}m" | ||||
| G="\e[1;${c_txt_emphase}m" | ||||
| S="\e[1;4;${c_txt}m" | ||||
| N="\e[0m" | ||||
| 
 | ||||
| # last logins | ||||
| if [[ "$lastusername" == "$lastcurrentusername" ]]; then | ||||
|     echo -e "$X  Last user logged in$W: $G$lastcurrentusername$W, from $F$lastcurrentuserhost$W | ||||
| $X  | Login - out$W (duration): $F$lastcurrentusertime$N" | ||||
| else | ||||
|     echo -e "$X  Last user logged in$W: $G$lastusername$W, from $F$lastuserhost$W | ||||
| $X  | Login - out$W (duration): $F$lastusertime$W | ||||
| 
 | ||||
| $X  Last time$W $G$lastcurrentusername$W$X logged in$W, was from $F$lastcurrentuserhost$W | ||||
| $X  | Login - out$W (duration): $F$lastcurrentusertime$N" | ||||
| fi | ||||
| 
 | ||||
| # logged users | ||||
| echo | ||||
| echo -e "$G"$loggeduserscount"$W ${X}session$W(s)$X are logged in$W:|${S}Session(s)${W}|${S}User$W${G}\n`echo -e "$loggedusersnames"`$N" | column -t -s '|' | sed 's/^/  /' | ||||
							
								
								
									
										70
									
								
								motdfetch.sample.conf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								motdfetch.sample.conf
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,70 @@ | |||
| #!/usr/bin/env bash | ||||
| # | ||||
| # user configuration file for MOTDfetch | ||||
| 
 | ||||
| # GLOBAL COLORS ###################################################### | ||||
| 
 | ||||
| c_txt="39" | ||||
| c_txt_emphase="35" | ||||
| c_txt_deco="97" | ||||
| c_txt_invert="30" | ||||
| c_bg="47" | ||||
| c_danger="31" | ||||
| c_warning="33" | ||||
| c_success="32" | ||||
| c_title="${c_bg};1;${c_txt_invert}m" | ||||
| 
 | ||||
| # GLOBAL OPTIONS #################################################### | ||||
|   | ||||
| ## api website name for plain public IP4/6 check | ||||
| global_publicip_api="icanhazip.com" | ||||
|   | ||||
| # MODULES OPTIONS #################################################### | ||||
|   | ||||
| ## HEADER module | ||||
| module_header_disable=0 | ||||
| ### custom text (comment to use username, trim > 80 char) | ||||
| module_header_text="BANNER" | ||||
|   | ||||
| ## SYSINFO module | ||||
| module_sysinfo_disable=0 | ||||
|   | ||||
| ## SERVICES module | ||||
| module_services_disable=0 | ||||
| ### services to check | ||||
| ###     + lookup system & current user services running with these 2 commands: | ||||
| ###         systemctl --type=service --no-pager -q --state running | ||||
| ###         systemctl --type=service --user --no-pager -q --state running | ||||
| ###     + to add user services you need to provide the uid of the user ("service:uid"), find the uid with: | ||||
| ###         id -u | ||||
| module_services=( | ||||
|     "cron" | ||||
|     "unattended-upgrades.service" | ||||
|     "dbus:1000" | ||||
| ) | ||||
| ### column max-width | ||||
| module_services_width="80" | ||||
|   | ||||
| ## FILESYSTEM module | ||||
| module_filesystem_disable=0 | ||||
| ### disable the ZFS section of the module | ||||
| module_filesystem_zfs_disable=0 | ||||
| ### max blocks usage percentage warning threshold | ||||
| module_filesystem_max_usage="85" | ||||
|   | ||||
| ## TLS module | ||||
| module_tls_disable=0 | ||||
| ### Domains and ports (default:433) for TLS certification check | ||||
| module_tls_domains=( | ||||
|     "www.google.com" | ||||
|     "w.fakedomain.com" | ||||
| ) | ||||
|   | ||||
| ## POSTQUEUE module | ||||
| module_postqueue_disable=0 | ||||
|   | ||||
| ## FAIL2BAN module | ||||
| module_fail2ban_disable=0 | ||||
|   | ||||
| ## USERLOG module | ||||
| module_userslog_disable=0 | ||||
							
								
								
									
										112
									
								
								readme.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								readme.md
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,112 @@ | |||
| # [MOTDfetch][motdfetch_repo] | ||||
| 
 | ||||
|  | ||||
|  | ||||
|  | ||||
| 
 | ||||
| **MOTDfetch** is a modular & dynamic **MOTD replacement** written in Bash and a nice **command line information tool** for Debian/Ubuntu systems. | ||||
| 
 | ||||
| >*MOTD - "message of the day"   | ||||
| >Feature used on Unix-like CLI systems to send a common message to all users after a successful login, and just before it executes the login shell.   | ||||
| >Newer Unix-like systems may generate the message dynamically when the host boots or a user logs in.* | ||||
| 
 | ||||
| **Drawbacks** with the current implementation of **MOTD with PAM on Debian and Ubuntu** are at least 3: | ||||
|   1. The **SSH client does not decide** whether to activate the MOTD.   | ||||
| As it is loaded before the shell login is opened:   | ||||
|   2. User has to **wait blindly** for the end of the execution if there is a dynamic script.   | ||||
|   3. Scripts **can not check the user sessions** status. | ||||
| 
 | ||||
| MOTDfetch **avoids** and partially **disable the original MOTD implementation**, but **remains compatible** with it for PAM login. | ||||
| 
 | ||||
| --- | ||||
| 
 | ||||
| >###### Table of contents   | ||||
| >**[FEATURES](#features)**   | ||||
| >**[INSTALLATION](#installation)**   | ||||
| >**[USAGE](#usage)**   | ||||
| 
 | ||||
| [![Preview of MOTDfetch][preview_image]][preview_image_url] | ||||
| 
 | ||||
| --- | ||||
| 
 | ||||
| ## Features | ||||
| 
 | ||||
| - Usable as a **command**, a **login MOTD** or **SSH MOTD**. | ||||
| - **[8 Core modules](#8_core_modules)**. | ||||
| - Uniform and **easily customizable**. | ||||
| - **Emphasis** of important elements and status by **colors, symbols or flashing**. | ||||
| - **Notice message** upon missing dependencies | ||||
| - **Reduced operation mode fot high load** (enforceable). | ||||
| - Separate **system and users configuration** files. | ||||
| - **Scripted installation** and updates. | ||||
| - **Modules or sections can be disabled**. | ||||
| - Standalone **executable modules**. | ||||
| 
 | ||||
| ### 8 Core modules | ||||
| 
 | ||||
| #### **HEADER module** | ||||
| 
 | ||||
| - decorative banner (custom text or username) | ||||
| - welcome message with username, date and time | ||||
| - user mail inbox status | ||||
| 
 | ||||
| #### **SYSYINFO module** | ||||
| 
 | ||||
| - distribution name, kernel version, uptime | ||||
| - CPU, cores, load, processes, memory, swap | ||||
| - hostname, network interface, DNS servers, public IPs/DNS/rDNS records | ||||
| - custom external API for public IP check | ||||
| - skip connectivity related tests if the API check fail | ||||
| - short timeout on dig & curl commands to keep the script snappy | ||||
| 
 | ||||
| #### **SERVICES module** | ||||
| 
 | ||||
| - check systemd services status | ||||
| - by service name and user UID if not system | ||||
| - :warning: user cannot check other user's services | ||||
| 
 | ||||
| #### **FILESYSTEM module** | ||||
| 
 | ||||
| - 2 sections: general filesystems, ZFS filesystems | ||||
| - name, fs type, usage and size of disk or ZFS pool | ||||
| - inodes usage and size when relevant | ||||
| - health status for ZFS | ||||
| - custom usage threshold for warning hints | ||||
| 
 | ||||
| #### **TLS module** | ||||
| 
 | ||||
| - check X.509 certificates status with openssl | ||||
| - accept domain and optional port (443 by default) | ||||
| - validate name correspondence and expiration date | ||||
| - skip the test if there is no internet connectivity | ||||
| - short timeout on openssl command to keep the script snappy | ||||
| 
 | ||||
| #### **POSTQUEUE module** | ||||
| 
 | ||||
| - postfix deferred queue status | ||||
| - short timeout on the parsing to keep the script snappy if there is thousands of mails | ||||
| 
 | ||||
| #### **FAIL2BAN module** | ||||
| 
 | ||||
| - display fail2ban jails status | ||||
| - :warning: need to be executed with root or sudo | ||||
| 
 | ||||
| #### **USERSLOG module** | ||||
| 
 | ||||
|   - display last user logged in | ||||
|   - name, IP and connection range | ||||
|   - if the current user is different, display his last log too | ||||
|   - display currently logged sessions with usernames | ||||
| 
 | ||||
| ## Installation | ||||
| 
 | ||||
| ### Requirements | ||||
| 
 | ||||
| ## Usage | ||||
| 
 | ||||
| --- | ||||
| 
 | ||||
| [//]: # (LINKS) | ||||
| [motdfetch_repo]: https://git.tkapias.net/tkapias/MOTDfetch | ||||
| [preview_image]: docs/img/preview.jpg "Preview of MOTDfetch" | ||||
| [preview_image_url]: https://git.tkapias.net/tkapias/MOTDfetch/raw/master/docs/img/preview.jpg | ||||
		Loading…
	
		Reference in a new issue