bmotd.sh 15KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. #!/bin/bash
  2. # cpu? mem?
  3. # dns server, volumes/space gw
  4. # mac addr?
  5. # Config
  6. MOTD="/etc/motd"
  7. INSTPATH="/etc/bmotd.sh"
  8. CACHEPATH="/var/cache/bmotd"
  9. # The different colours as variables
  10. C1="\033[01;35m" # Purple
  11. C2="\033[00;92m" # Green
  12. C3="\033[01;97m" # White
  13. X="\033[00;0m" # Reset
  14. main () {
  15. # print help
  16. if [ $# -lt 1 ]; then
  17. printHelp
  18. fi
  19. # check if root
  20. if ! isRoot; then
  21. echo 'Script needs root privileges to run. Re-run with sudo.'
  22. exit 1
  23. fi
  24. # check arguments
  25. case "$1" in
  26. enable)
  27. echo -e "\nEnabling bmotd.sh"
  28. # copy to INSTPATH
  29. cp "$(readlink -f $0)" "$INSTPATH"
  30. # check if crontab present
  31. if ! command -v crontab >/dev/null 2>&1; then
  32. echo "Error: couldn't find crontab. Exiting..."
  33. exit 1
  34. fi
  35. # Check if motd writable
  36. if ! test -w $MOTD; then
  37. echo "Unable to write $MOTD . To enable update permissions. Exiting..."
  38. exit 1
  39. fi
  40. # Check if script is already in crontab, if not add itself
  41. CRON_ENTRY="* * * * * $INSTPATH update"
  42. crontab -l 2>/dev/null | grep -q "$CRON_ENTRY" || ( crontab -l 2>/dev/null; echo "$CRON_ENTRY" ) | crontab -
  43. echo -e "Success! Check it yourself with crontab -l"
  44. echo "Exiting."
  45. exit 0
  46. ;;
  47. disable)
  48. echo -e "\nDisabling BetterMOTD"
  49. ( crontab -l 2>/dev/null | egrep -v "$INSTPATH update$"; ) | crontab -
  50. rm $INSTPATH
  51. exit 0
  52. ;;
  53. update)
  54. update
  55. exit 0
  56. ;;
  57. test)
  58. MOTD="/dev/stdout"
  59. update
  60. exit 0
  61. ;;
  62. *)
  63. printHelp
  64. esac
  65. }
  66. update() {
  67. # Gather information
  68. HOSTNAME=$(hostname -s)
  69. FQDN=$(hostname -f)
  70. OSID=$(cat /etc/*-release 2>/dev/null | awk -F'=' '/^ID=/ { print $2; count++ } END { if (!count) print "Unknown" }')
  71. KERNEL=$(uname -r)
  72. # check if crontab present
  73. if command -v dig >/dev/null 2>&1; then
  74. EXTERNAL=$(dig TXT +time=3 +tries=2 +short o-o.myaddr.l.google.com @ns1.google.com | tr -d '"')
  75. fi
  76. # Check if pkg number cache exists
  77. test -f "$CACHEPATH/pkg_count" || PKG_REFRESH=1
  78. # Check if pkg number cache is outdate
  79. LASTMODIFICATION=$(date +%s -r "$CACHEPATH/pkg_count")
  80. CURRENTTIME=$(date +%s)
  81. UPDATEDAGO=$((CURRENTTIME - LASTMODIFICATION))
  82. [ "$UPDATEDAGO" -gt "86400" ] && PKG_REFRESH=1
  83. # If cache old or non existent, get number of updates awaiting
  84. if [ $PKG_REFRESH ]; then
  85. case "$OSID" in
  86. debian|osmc|linuxmint)
  87. PKG_NU=$(apt-get --just-print upgrade | awk '/^[0-9]/ { print $1; exit }')
  88. ;;
  89. arch|archarm)
  90. PKG_NU=$(pacman -Qu | wc -l)
  91. ;;
  92. *)
  93. PKG_NU="-1"
  94. esac
  95. mkdir -p "$CACHEPATH"
  96. echo $PKG_NU > "$CACHEPATH/pkg_count"
  97. fi
  98. PKG_NU=$(cat $CACHEPATH/pkg_count)
  99. # run motd generator if so
  100. motdGen
  101. }
  102. function printHelp {
  103. echo -e "Use: $0 [ test | update | enable | disable ]\n"
  104. printf " %-6s %s\n" "test" "- Print generated motd to standard output. Use for preview."
  105. printf " %-6s %s\n" "update" "- Update /etc/motd file"
  106. printf " %-6s %s\n" "enable" "- Places $0 in /etc and adds cron entry for script to run every minute"
  107. printf " %-6s %s\n\n" "disable" "- Removes cron entry and disables refreshes of /etc/motd"
  108. exit 0;
  109. }
  110. function prettyPrint {
  111. declare -A a
  112. height=5
  113. a["32,0"]='$';a["32,1"]='$';a["32,2"]='$';a["32,3"]='$';a["32,4"]='$';
  114. a["33,0"]=' _ ';a["33,1"]='| |';a["33,2"]='|_|';a["33,3"]='(_)';a["33,4"]=' ';
  115. a["34,0"]=' _ _ ';a["34,1"]='( | )';a["34,2"]=' V V ';a["34,3"]=' $ ';a["34,4"]=' ';
  116. a["35,0"]=' _ _ ';a["35,1"]=' _| | |_ ';a["35,2"]='|_ . _|';a["35,3"]='|_ _|';a["35,4"]=' |_|_| ';
  117. a["36,0"]=' ';a["36,1"]=' ||_';a["36,2"]='(_-<';a["36,3"]='/ _/';a["36,4"]=' || ';
  118. a["37,0"]=' _ __ ';a["37,1"]='(_)/ / ';a["37,2"]=' / /_ ';a["37,3"]=' /_/(_)';a["37,4"]=' ';
  119. a["38,0"]=' __ ';a["38,1"]='/ _|___ ';a["38,2"]='> _|_ _|';a["38,3"]='\_____| ';a["38,4"]=' ';
  120. a["39,0"]=' _ ';a["39,1"]='( )';a["39,2"]='|/ ';a["39,3"]=' $ ';a["39,4"]=' ';
  121. a["40,0"]=' __';a["40,1"]=' / /';a["40,2"]='| | ';a["40,3"]='| | ';a["40,4"]=' \_\';
  122. a["41,0"]='__ ';a["41,1"]='\ \ ';a["41,2"]=' | |';a["41,3"]=' | |';a["41,4"]='/_/ ';
  123. a["42,0"]=' ';a["42,1"]='_/\_';a["42,2"]='> <';a["42,3"]=' \/ ';a["42,4"]=' ';
  124. a["43,0"]=' _ ';a["43,1"]=' _| |_ ';a["43,2"]='|_ _|';a["43,3"]=' |_| ';a["43,4"]=' ';
  125. a["44,0"]=' ';a["44,1"]=' ';a["44,2"]=' _ ';a["44,3"]='( )';a["44,4"]='|/ ';
  126. a["45,0"]=' ';a["45,1"]=' ___ ';a["45,2"]='|___|';a["45,3"]=' $ ';a["45,4"]=' ';
  127. a["46,0"]=' ';a["46,1"]=' ';a["46,2"]=' _ ';a["46,3"]='(_)';a["46,4"]=' ';
  128. a["47,0"]=' __';a["47,1"]=' / /';a["47,2"]=' / / ';a["47,3"]='/_/ ';a["47,4"]=' ';
  129. a["48,0"]=' __ ';a["48,1"]=' / \ ';a["48,2"]='| () |';a["48,3"]=' \__/ ';a["48,4"]=' ';
  130. a["49,0"]=' _ ';a["49,1"]='/ |';a["49,2"]='| |';a["49,3"]='|_|';a["49,4"]=' ';
  131. a["50,0"]=' ___ ';a["50,1"]='|_ )';a["50,2"]=' / / ';a["50,3"]='/___|';a["50,4"]=' ';
  132. a["51,0"]=' ____';a["51,1"]='|__ /';a["51,2"]=' |_ \';a["51,3"]='|___/';a["51,4"]=' ';
  133. a["52,0"]=' _ _ ';a["52,1"]='| | | ';a["52,2"]='|_ _|';a["52,3"]=' |_| ';a["52,4"]=' ';
  134. a["53,0"]=' ___ ';a["53,1"]='| __|';a["53,2"]='|__ \';a["53,3"]='|___/';a["53,4"]=' ';
  135. a["54,0"]=' __ ';a["54,1"]=' / / ';a["54,2"]='/ _ \';a["54,3"]='\___/';a["54,4"]=' ';
  136. a["55,0"]=' ____ ';a["55,1"]='|__ |';a["55,2"]=' / / ';a["55,3"]=' /_/ ';a["55,4"]=' ';
  137. a["56,0"]=' ___ ';a["56,1"]='( _ )';a["56,2"]='/ _ \';a["56,3"]='\___/';a["56,4"]=' ';
  138. a["57,0"]=' ___ ';a["57,1"]='/ _ \';a["57,2"]='\_, /';a["57,3"]=' /_/ ';a["57,4"]=' ';
  139. a["58,0"]=' _ ';a["58,1"]='(_)';a["58,2"]=' _ ';a["58,3"]='(_)';a["58,4"]=' ';
  140. a["59,0"]=' _ ';a["59,1"]='(_)';a["59,2"]=' _ ';a["59,3"]='( )';a["59,4"]='|/ ';
  141. a["60,0"]=' __';a["60,1"]=' / /';a["60,2"]='< < ';a["60,3"]=' \_\';a["60,4"]=' ';
  142. a["61,0"]=' ';a["61,1"]=' ___ ';a["61,2"]='|___|';a["61,3"]='|___|';a["61,4"]=' ';
  143. a["62,0"]='__ ';a["62,1"]='\ \ ';a["62,2"]=' > >';a["62,3"]='/_/ ';a["62,4"]=' ';
  144. a["63,0"]=' ___ ';a["63,1"]='|__ \';a["63,2"]=' /_/';a["63,3"]=' (_) ';a["63,4"]=' ';
  145. a["64,0"]=' ____ ';a["64,1"]=' / __ \ ';a["64,2"]='/ / _` |';a["64,3"]='\ \__,_|';a["64,4"]=' \____/ ';
  146. a["65,0"]=' _ ';a["65,1"]=' /_\ ';a["65,2"]=' / _ \ ';a["65,3"]='/_/ \_\';a["65,4"]=' ';
  147. a["66,0"]=' ___ ';a["66,1"]='| _ )';a["66,2"]='| _ \';a["66,3"]='|___/';a["66,4"]=' ';
  148. a["67,0"]=' ___ ';a["67,1"]=' / __|';a["67,2"]='| (__ ';a["67,3"]=' \___|';a["67,4"]=' ';
  149. a["68,0"]=' ___ ';a["68,1"]='| \ ';a["68,2"]='| |) |';a["68,3"]='|___/ ';a["68,4"]=' ';
  150. a["69,0"]=' ___ ';a["69,1"]='| __|';a["69,2"]='| _| ';a["69,3"]='|___|';a["69,4"]=' ';
  151. a["70,0"]=' ___ ';a["70,1"]='| __|';a["70,2"]='| _| ';a["70,3"]='|_| ';a["70,4"]=' ';
  152. a["71,0"]=' ___ ';a["71,1"]=' / __|';a["71,2"]='| (_ |';a["71,3"]=' \___|';a["71,4"]=' ';
  153. a["72,0"]=' _ _ ';a["72,1"]='| || |';a["72,2"]='| __ |';a["72,3"]='|_||_|';a["72,4"]=' ';
  154. a["73,0"]=' ___ ';a["73,1"]='|_ _|';a["73,2"]=' | | ';a["73,3"]='|___|';a["73,4"]=' ';
  155. a["74,0"]=' _ ';a["74,1"]=' _ | |';a["74,2"]='| || |';a["74,3"]=' \__/ ';a["74,4"]=' ';
  156. a["75,0"]=' _ __';a["75,1"]='| |/ /';a["75,2"]='| '"'"' < ';a["75,3"]='|_|\_\';a["75,4"]=' ';
  157. a["76,0"]=' _ ';a["76,1"]='| | ';a["76,2"]='| |__ ';a["76,3"]='|____|';a["76,4"]=' ';
  158. a["77,0"]=' __ __ ';a["77,1"]='| \/ |';a["77,2"]='| |\/| |';a["77,3"]='|_| |_|';a["77,4"]=' ';
  159. a["78,0"]=' _ _ ';a["78,1"]='| \| |';a["78,2"]='| .` |';a["78,3"]='|_|\_|';a["78,4"]=' ';
  160. a["79,0"]=' ___ ';a["79,1"]=' / _ \ ';a["79,2"]='| (_) |';a["79,3"]=' \___/ ';a["79,4"]=' ';
  161. a["80,0"]=' ___ ';a["80,1"]='| _ \';a["80,2"]='| _/';a["80,3"]='|_| ';a["80,4"]=' ';
  162. a["81,0"]=' ___ ';a["81,1"]=' / _ \ ';a["81,2"]='| (_) |';a["81,3"]=' \__\_\';a["81,4"]=' ';
  163. a["82,0"]=' ___ ';a["82,1"]='| _ \';a["82,2"]='| /';a["82,3"]='|_|_\';a["82,4"]=' ';
  164. a["83,0"]=' ___ ';a["83,1"]='/ __|';a["83,2"]='\__ \';a["83,3"]='|___/';a["83,4"]=' ';
  165. a["84,0"]=' _____ ';a["84,1"]='|_ _|';a["84,2"]=' | | ';a["84,3"]=' |_| ';a["84,4"]=' ';
  166. a["85,0"]=' _ _ ';a["85,1"]='| | | |';a["85,2"]='| |_| |';a["85,3"]=' \___/ ';a["85,4"]=' ';
  167. a["86,0"]='__ __';a["86,1"]='\ \ / /';a["86,2"]=' \ V / ';a["86,3"]=' \_/ ';a["86,4"]=' ';
  168. a["87,0"]='__ __';a["87,1"]='\ \ / /';a["87,2"]=' \ \/\/ / ';a["87,3"]=' \_/\_/ ';a["87,4"]=' ';
  169. a["88,0"]='__ __';a["88,1"]='\ \/ /';a["88,2"]=' > < ';a["88,3"]='/_/\_\';a["88,4"]=' ';
  170. a["89,0"]='__ __';a["89,1"]='\ \ / /';a["89,2"]=' \ V / ';a["89,3"]=' |_| ';a["89,4"]=' ';
  171. a["90,0"]=' ____';a["90,1"]='|_ /';a["90,2"]=' / / ';a["90,3"]='/___|';a["90,4"]=' ';
  172. a["91,0"]=' __ ';a["91,1"]='| _|';a["91,2"]='| | ';a["91,3"]='| | ';a["91,4"]='|__|';
  173. a["92,0"]='__ ';a["92,1"]='\ \ ';a["92,2"]=' \ \ ';a["92,3"]=' \_\';a["92,4"]=' ';
  174. a["93,0"]=' __ ';a["93,1"]='|_ |';a["93,2"]=' | |';a["93,3"]=' | |';a["93,4"]='|__|';
  175. a["94,0"]=' /\ ';a["94,1"]='|/\|';a["94,2"]=' $ ';a["94,3"]=' $ ';a["94,4"]=' ';
  176. a["95,0"]=' ';a["95,1"]=' ';a["95,2"]=' ';a["95,3"]=' ___ ';a["95,4"]='|___|';
  177. a["96,0"]=' _ ';a["96,1"]='( )';a["96,2"]=' \|';a["96,3"]=' $ ';a["96,4"]=' ';
  178. a["97,0"]=' ';a["97,1"]=' __ _ ';a["97,2"]='/ _` |';a["97,3"]='\__,_|';a["97,4"]=' ';
  179. a["98,0"]=' _ ';a["98,1"]='| |__ ';a["98,2"]='| '"'"'_ \';a["98,3"]='|_.__/';a["98,4"]=' ';
  180. a["99,0"]=' ';a["99,1"]=' __ ';a["99,2"]='/ _|';a["99,3"]='\__|';a["99,4"]=' ';
  181. a["100,0"]=' _ ';a["100,1"]=' __| |';a["100,2"]='/ _` |';a["100,3"]='\__,_|';a["100,4"]=' ';
  182. a["101,0"]=' ';a["101,1"]=' ___ ';a["101,2"]='/ -_)';a["101,3"]='\___|';a["101,4"]=' ';
  183. a["102,0"]=' __ ';a["102,1"]=' / _|';a["102,2"]='| _|';a["102,3"]='|_| ';a["102,4"]=' ';
  184. a["103,0"]=' ';a["103,1"]=' __ _ ';a["103,2"]='/ _` |';a["103,3"]='\__, |';a["103,4"]='|___/ ';
  185. a["104,0"]=' _ ';a["104,1"]='| |_ ';a["104,2"]='| '"'"' \ ';a["104,3"]='|_||_|';a["104,4"]=' ';
  186. a["105,0"]=' _ ';a["105,1"]='(_)';a["105,2"]='| |';a["105,3"]='|_|';a["105,4"]=' ';
  187. a["106,0"]=' _ ';a["106,1"]=' (_)';a["106,2"]=' | |';a["106,3"]=' _/ |';a["106,4"]='|__/ ';
  188. a["107,0"]=' _ ';a["107,1"]='| |__';a["107,2"]='| / /';a["107,3"]='|_\_\';a["107,4"]=' ';
  189. a["108,0"]=' _ ';a["108,1"]='| |';a["108,2"]='| |';a["108,3"]='|_|';a["108,4"]=' ';
  190. a["109,0"]=' ';a["109,1"]=' _ __ ';a["109,2"]='| '"'"' \ ';a["109,3"]='|_|_|_|';a["109,4"]=' ';
  191. a["110,0"]=' ';a["110,1"]=' _ _ ';a["110,2"]='| '"'"' \ ';a["110,3"]='|_||_|';a["110,4"]=' ';
  192. a["111,0"]=' ';a["111,1"]=' ___ ';a["111,2"]='/ _ \';a["111,3"]='\___/';a["111,4"]=' ';
  193. a["112,0"]=' ';a["112,1"]=' _ __ ';a["112,2"]='| '"'"'_ \';a["112,3"]='| .__/';a["112,4"]='|_| ';
  194. a["113,0"]=' ';a["113,1"]=' __ _ ';a["113,2"]='/ _` |';a["113,3"]='\__, |';a["113,4"]=' |_|';
  195. a["114,0"]=' ';a["114,1"]=' _ _ ';a["114,2"]='| '"'"'_|';a["114,3"]='|_| ';a["114,4"]=' ';
  196. a["115,0"]=' ';a["115,1"]=' ___';a["115,2"]='(_-<';a["115,3"]='/__/';a["115,4"]=' ';
  197. a["116,0"]=' _ ';a["116,1"]='| |_ ';a["116,2"]='| _|';a["116,3"]=' \__|';a["116,4"]=' ';
  198. a["117,0"]=' ';a["117,1"]=' _ _ ';a["117,2"]='| || |';a["117,3"]=' \_,_|';a["117,4"]=' ';
  199. a["118,0"]=' ';a["118,1"]='__ __';a["118,2"]='\ V /';a["118,3"]=' \_/ ';a["118,4"]=' ';
  200. a["119,0"]=' ';a["119,1"]='__ __ __';a["119,2"]='\ V V /';a["119,3"]=' \_/\_/ ';a["119,4"]=' ';
  201. a["120,0"]=' ';a["120,1"]='__ __';a["120,2"]='\ \ /';a["120,3"]='/_\_\';a["120,4"]=' ';
  202. a["121,0"]=' ';a["121,1"]=' _ _ ';a["121,2"]='| || |';a["121,3"]=' \_, |';a["121,4"]=' |__/ ';
  203. a["122,0"]=' ';a["122,1"]=' ___';a["122,2"]='|_ /';a["122,3"]='/__|';a["122,4"]=' ';
  204. str=$1
  205. strarr=()
  206. for (( i=0; i<${#str}; i++ )); do
  207. strarr+=($(printf '%d\n' "'${str:$i:1}"))
  208. done
  209. for ((i=0;i<height;i++)) do
  210. echo -n ' '
  211. for j in "${strarr[@]}"; do
  212. printf "%s" "${a["$j,$i"]}"
  213. done
  214. printf "\n"
  215. done
  216. }
  217. function parse_ip() {
  218. i=0;
  219. for dev in $(ip a | egrep "^[0-9]" | grep -v "lo" | awk '{ print $2 }'); do
  220. if [ $(ip a s dev "$dev" | grep -c "inet ") -gt 0 ]; then
  221. arr[i]=$dev' '
  222. for inet in $(ip a s dev "$dev" | grep "inet " | awk '{ print $2 }'); do
  223. arr[i]=${arr[i]}$inet' '
  224. done;
  225. arr[i]=${arr[i]}' ';
  226. i=$i+1
  227. fi;
  228. done;
  229. }
  230. function parse_ifconfig() {
  231. i=0
  232. for dev in $(sudo ifconfig | egrep "^[a-z0-9]" | grep -v "lo" | awk '{ print $1 }'); do
  233. if [ $(sudo ifconfig ${dev%?} | grep -c "inet ") -gt 0 ]; then
  234. arr[i]=$dev' '
  235. for inet in $(sudo ifconfig ${dev%?} | grep "inet " | awk '{ print $2 }'); do
  236. arr[i]=${arr[i]}$inet' '
  237. done;
  238. arr[i]=${arr[i]}' ';
  239. i=$i+1
  240. fi;
  241. done;
  242. }
  243. function isRoot() {
  244. ! (( ${EUID:-0} || $(id -u) ))
  245. }
  246. motdGen() {
  247. # Collect useful information about your system
  248. LASTUSER=$(last | head -n 1 | cut -d' ' -f1)
  249. LASTLOGIN="$LASTUSER$C3 on$C1 $(date --date "$(lastlog -u $LASTUSER | tail -n 1 | tr -s ' ' | cut -d" " -f4-)" "+%a %e %b %Y, %H:%M:%S")$C3 from$C1 $(lastlog -u $LASTUSER | tail -n 1 | tr -s ' ' | cut -d" " -f3)"
  250. UPTIME_EXT=`uptime | sed -n 's/^.*\(up.*\),[0-9 ]*user.*\(load average.*\)/\1, \2/p'`
  251. LBT='╔══════════════════════════════════════════════════════════╾╌╌╌╌╌╌╌┈┈┄┄┄┄┄┄┄┄┄'
  252. LBB='╚══════════════════════════════════════╾╌╌╌╌╌╌╌┈┈┄┄┄┄┄┄┄┄┄'
  253. command -v ip >/dev/null 2>&1 && parse_ip
  254. command -v ip >/dev/null 2>&1 || parse_ifconfig
  255. clear > $MOTD # to clear the screen when showing up
  256. echo -e "$C2" >> $MOTD
  257. prettyPrint $HOSTNAME >> $MOTD
  258. echo -e " $C3$LBT" >> $MOTD
  259. echo -e " $C3║$C2 • FQDN...............$C3: $C1 $FQDN" >> $MOTD
  260. echo -e " $C3║$C2 • Last Login.........$C3: $C1 $LASTLOGIN" >> $MOTD
  261. echo -e " $C3║$C2 • Pkg to update......$C3: $C1 $PKG_NU" >> $MOTD
  262. echo -e " $C3║$C2 • Uptime,Load........$C3: $C1 $UPTIME_EXT" >> $MOTD
  263. echo -e " $C3║$C2 • Kernel.............$C3: $C1 $KERNEL" >> $MOTD
  264. if ! test -z $EXTERNAL; then
  265. echo -e " $C3║$C2 • External IP........$C3: $C1 $EXTERNAL" >> $MOTD
  266. fi
  267. for (( i=0; i<${#arr[@]}; i++ )); do
  268. if [ $i -eq 0 ]; then
  269. echo -e "$C3 ║$C2 • Network Interfaces.$C3: $C1 ${arr[$i]}" >> $MOTD
  270. else
  271. echo -e "$C3 ║$C2 $C1 ${arr[$i]}" >> $MOTD
  272. fi
  273. done
  274. echo -e " $C3$LBB" >> $MOTD
  275. echo -e "$X" >> $MOTD
  276. }
  277. main "$@"