#!/bin/bash { #//////////////////////////////////// # DietPi Banner Script # #//////////////////////////////////// # Created by Daniel Knight / daniel.knight@dietpi.com / dietpi.com # #//////////////////////////////////// # # Info: # - Location: /boot/dietpi/func/dietpi-banner # - Checks /run/dietpi/.update_available, /run/dietpi/.live_patches, /run/dietpi/.apt_updates, /run/dietpi/.dietpi_motd and /boot/dietpi/.prep_info # USAGE=' - dietpi-banner = banner customisation menu - dietpi-banner 0 = top section + LAN IP - dietpi-banner 1 = clear terminal + top section + chosen entries + credits ' #//////////////////////////////////// # Grab input INPUT=$* # Import DietPi-Globals -------------------------------------------------------------- . /boot/dietpi/func/dietpi-globals # - Allow concurrent banner prints but a single menu call only if [[ ! $INPUT ]] then readonly G_PROGRAM_NAME='DietPi-Banner' G_CHECK_ROOT_USER "$@" # Required to store settings G_INIT else # Apply safe locale in non-menu mode (where G_INIT does it) export LC_ALL='C.UTF-8' LANG='C.UTF-8' fi # Import DietPi-Globals -------------------------------------------------------------- #///////////////////////////////////////////////////////////////////////////////////// # Globals #///////////////////////////////////////////////////////////////////////////////////// readonly FP_SAVEFILE='/boot/dietpi/.dietpi-banner' readonly FP_CUSTOM='/boot/dietpi/.dietpi-banner_custom' aDESCRIPTION=( 'Device model' 'Uptime' 'CPU temp' 'FQDN/hostname' 'NIS domainname' 'LAN IP' 'WAN IP' 'Disk usage (RootFS)' 'Disk usage (userdata)' 'Weather (wttr.in)' 'Custom banner entry' 'Display DietPi useful commands?' 'MOTD' 'VPN status' 'Large hostname' 'Print credits' 'Let'\''s Encrypt cert status' 'RAM usage' 'Load average' ) # Set defaults: Disable CPU temp by default in VMs if (( $G_HW_MODEL == 20 )) then aENABLED=(1 0 0 0 0 1 0 1 0 0 0 1 1 0 0 1 0 0 0) else aENABLED=(1 0 1 0 0 1 0 0 0 0 0 1 1 0 0 1 0 0 0) fi COLOUR_RESET='\e[0m' aCOLOUR=( '\e[38;5;154m' # DietPi green | Lines, bullets and separators '\e[1m' # Bold white | Main descriptions '\e[90m' # Grey | Credits '\e[91m' # Red | Update notifications ) # Load settings here, to have chosen ${aCOLOUR[0]} applied to below strings # shellcheck disable=SC1090 [[ -f $FP_SAVEFILE ]] && . "$FP_SAVEFILE" GREEN_LINE=" ${aCOLOUR[0]}─────────────────────────────────────────────────────$COLOUR_RESET" GREEN_BULLET=" ${aCOLOUR[0]}-$COLOUR_RESET" GREEN_SEPARATOR="${aCOLOUR[0]}:$COLOUR_RESET" DIETPI_VERSION="$G_DIETPI_VERSION_CORE.$G_DIETPI_VERSION_SUB.$G_DIETPI_VERSION_RC" [[ $G_GITBRANCH == 'master' ]] || DIETPI_VERSION+=" ($G_GITBRANCH)" # DietPi update available? AVAILABLE_UPDATE= # value = version string Check_DietPi_Update() { [[ -f '/run/dietpi/.update_available' ]] || return 1 read -r AVAILABLE_UPDATE < /run/dietpi/.update_available return 0 } # New DietPi live patches available? LIVE_PATCHES=0 Check_DietPi_Live_Patches() { [[ -f '/run/dietpi/.live_patches' ]] || return 1 LIVE_PATCHES=1 return 0 } # APT updates available? PACKAGE_COUNT=0 Check_APT_Updates() { [[ -f '/run/dietpi/.apt_updates' ]] || return 1 read -r PACKAGE_COUNT < /run/dietpi/.apt_updates return 0 } # Reboot required to finalise kernel upgrade? REBOOT_REQUIRED=0 Check_Reboot() { G_CHECK_KERNEL && return 1 REBOOT_REQUIRED=1 return 0 } Save() { # Custom entry description echo "aDESCRIPTION[10]='${aDESCRIPTION[10]}'" for i in "${!aDESCRIPTION[@]}" do echo "aENABLED[$i]=${aENABLED[$i]}" done for i in "${!aCOLOUR[@]}" do echo "aCOLOUR[$i]='${aCOLOUR[$i]}'" done } Print_Header() { # DietPi update available? if Check_DietPi_Update then local text_update_available_date="${aCOLOUR[3]}Update available" # New DietPi live patches available? elif Check_DietPi_Live_Patches then local text_update_available_date="${aCOLOUR[3]}New live patches available" # APT update available? elif Check_APT_Updates then local text_update_available_date="${aCOLOUR[3]}$PACKAGE_COUNT APT updates available" # Reboot required to finalise kernel upgrade? elif Check_Reboot then local text_update_available_date="${aCOLOUR[3]}Reboot required" else local locale=$(sed -n '/^[[:blank:]]*AUTO_SETUP_LOCALE=/{s/^[^=]*=//p;q}' /boot/dietpi.txt) local text_update_available_date=$(LC_ALL=${locale:-C.UTF-8} date '+%R - %a %x') fi echo -e "$GREEN_LINE ${aCOLOUR[1]}DietPi v$DIETPI_VERSION$COLOUR_RESET $GREEN_SEPARATOR $text_update_available_date$COLOUR_RESET $GREEN_LINE" } Print_Local_Ip() { (( ${aENABLED[5]} )) || return 0 local iface=$(G_GET_NET -q iface) local ip=$(G_GET_NET -q ip) echo -e "$GREEN_BULLET ${aCOLOUR[1]}${aDESCRIPTION[5]} $GREEN_SEPARATOR ${ip:-Use dietpi-config to setup a connection} (${iface:-NONE})" } Print_Cert_Status() { # Let's Encrypt cert status - MUST be run as root local i for i in /etc/letsencrypt/live/*/cert.pem do # shellcheck disable=SC2292 [ -f "$i" ] || continue openssl x509 -enddate -noout -in "$i" | mawk '/notAfter=/{print "Valid until "$4"-"substr($1,10)"-"$2" "$3}' return 0 done echo 'No certificate found' } Print_Credits() { echo -e " ${aCOLOUR[2]}DietPi Team : https://github.com/MichaIng/DietPi#the-dietpi-project-team" [[ -f '/boot/dietpi/.prep_info' ]] && mawk 'NR==1 {sub(/^0$/,"DietPi Core Team");a=$0} NR==2 {print " Image by : "a" (pre-image: "$0")"}' /boot/dietpi/.prep_info echo -e " Patreon Legends : Chris Gelatt, ADSB.im Website : https://dietpi.com/ | https://x.com/DietPi_ | Bsky: @dietpi.com Contribute : https://dietpi.com/contribute.html Web Hosting by : https://login-online.com/$COLOUR_RESET\n" } Print_Updates() { # DietPi update available? if [[ $AVAILABLE_UPDATE ]] then echo -e " ${aCOLOUR[1]}dietpi-update$COLOUR_RESET $GREEN_SEPARATOR ${aCOLOUR[3]}Run now to update DietPi from v$DIETPI_VERSION to v$AVAILABLE_UPDATE$COLOUR_RESET\n" # New DietPi live patches available? elif (( $LIVE_PATCHES )) then echo -e " ${aCOLOUR[1]}dietpi-update$COLOUR_RESET $GREEN_SEPARATOR ${aCOLOUR[3]}Run now to check out new available DietPi live patches$COLOUR_RESET\n" # APT updates available? elif (( $PACKAGE_COUNT )) then echo -e " ${aCOLOUR[1]}apt upgrade$COLOUR_RESET $GREEN_SEPARATOR ${aCOLOUR[3]}Run now to apply $PACKAGE_COUNT available APT package upgrades$COLOUR_RESET\n" # Reboot required to finalise kernel upgrade? elif (( $REBOOT_REQUIRED )) then echo -e " ${aCOLOUR[1]}reboot$COLOUR_RESET $GREEN_SEPARATOR ${aCOLOUR[3]}A reboot is required to finalise a recent kernel upgrade$COLOUR_RESET\n" fi } Print_Useful_Commands() { echo -e " ${aCOLOUR[1]}dietpi-launcher$COLOUR_RESET $GREEN_SEPARATOR All the DietPi programs in one place ${aCOLOUR[1]}dietpi-config$COLOUR_RESET $GREEN_SEPARATOR Feature rich configuration tool for your device ${aCOLOUR[1]}dietpi-software$COLOUR_RESET $GREEN_SEPARATOR Select optimised software for installation ${aCOLOUR[1]}htop$COLOUR_RESET $GREEN_SEPARATOR Resource monitor ${aCOLOUR[1]}cpu$COLOUR_RESET $GREEN_SEPARATOR Shows CPU information and stats\n" } Print_Banner() { G_TERM_CLEAR Print_Header # Large Format Hostname # shellcheck disable=SC1091 (( ${aENABLED[14]} )) && . /boot/dietpi/func/dietpi-print_large "$(&1)" # CPU temp (( ${aENABLED[2]} )) && echo -e "$GREEN_BULLET ${aCOLOUR[1]}${aDESCRIPTION[2]} $GREEN_SEPARATOR $(print_full_info=1 G_OBTAIN_CPU_TEMP 2>&1)" # RAM usage (( ${aENABLED[17]} )) && echo -e "$GREEN_BULLET ${aCOLOUR[1]}${aDESCRIPTION[17]} $GREEN_SEPARATOR $(free -b | mawk 'NR==2 {CONVFMT="%.0f"; print $3/1024^2" of "$2/1024^2" MiB ("$3/$2*100"%)"}')" # Load average (( ${aENABLED[18]} )) && echo -e "$GREEN_BULLET ${aCOLOUR[1]}${aDESCRIPTION[18]} $GREEN_SEPARATOR $(mawk '{print $1 ", " $2 ", " $3}' /proc/loadavg) ($(nproc) cores)" # Hostname (( ${aENABLED[3]} && ! ${aENABLED[14]} )) && echo -e "$GREEN_BULLET ${aCOLOUR[1]}${aDESCRIPTION[3]} $GREEN_SEPARATOR $(&1)" # LAN IP Print_Local_Ip # WAN IP + location info (( ${aENABLED[6]} )) && echo -e "$GREEN_BULLET ${aCOLOUR[1]}${aDESCRIPTION[6]} $GREEN_SEPARATOR $(G_GET_WAN_IP 2>&1)" # DietPi-VPN connection status (( ${aENABLED[13]} )) && echo -e "$GREEN_BULLET ${aCOLOUR[1]}${aDESCRIPTION[13]} $GREEN_SEPARATOR $(/boot/dietpi/dietpi-vpn status 2>&1)" # Disk usage (RootFS) (( ${aENABLED[7]} )) && echo -e "$GREEN_BULLET ${aCOLOUR[1]}${aDESCRIPTION[7]} $GREEN_SEPARATOR $(df -h --output=used,size,pcent / | mawk 'NR==2 {print $1" of "$2" ("$3")"}' 2>&1)" # Disk usage (DietPi userdata) (( ${aENABLED[8]} )) && echo -e "$GREEN_BULLET ${aCOLOUR[1]}${aDESCRIPTION[8]} $GREEN_SEPARATOR $(df -h --output=used,size,pcent /mnt/dietpi_userdata | mawk 'NR==2 {print $1" of "$2" ("$3")"}' 2>&1)" # Weather (( ${aENABLED[9]} )) && echo -e "$GREEN_BULLET ${aCOLOUR[1]}${aDESCRIPTION[9]} $GREEN_SEPARATOR $(curl -sSfLm 3 'https://wttr.in/?format=4' 2>&1)" # Let's Encrypt cert status if (( ${aENABLED[16]} )) then echo -en "$GREEN_BULLET ${aCOLOUR[1]}${aDESCRIPTION[16]} $GREEN_SEPARATOR " if [[ $EUID == 0 ]] then # Running as root Print_Cert_Status 2>&1 else # Running as non-root: Fail silently without NOPASSWD to avoid password prompt, but print info instead sudo -n dash -c "$(declare -f Print_Cert_Status); Print_Cert_Status 2>&1" 2> /dev/null || echo 'NOPASSWD sudo required to obtain cert status' fi fi # Custom (( ${aENABLED[10]} )) && echo -e "$GREEN_BULLET ${aCOLOUR[1]}${aDESCRIPTION[10]} $GREEN_SEPARATOR $(bash "$FP_CUSTOM" 2>&1)" # MOTD if (( ${aENABLED[12]} )) then local motd fp_motd='/run/dietpi/.dietpi_motd' [[ -f $fp_motd ]] || curl -sSfLm 3 'https://dietpi.com/motd' -o "$fp_motd" # shellcheck disable=SC1090 [[ -f $fp_motd ]] && . "$fp_motd" &> /dev/null && [[ $motd ]] && echo -e "$GREEN_BULLET ${aCOLOUR[1]}${aDESCRIPTION[12]} $GREEN_SEPARATOR $motd" fi echo -e "$GREEN_LINE\n" (( ${aENABLED[15]} )) && Print_Credits Print_Updates (( ${aENABLED[11]} )) && Print_Useful_Commands } Menu_Main() { G_WHIP_CHECKLIST_ARRAY=() for i in "${!aDESCRIPTION[@]}" do local state='off' (( ${aENABLED[$i]:=0} == 1 )) && state='on' G_WHIP_CHECKLIST_ARRAY+=("$i" "${aDESCRIPTION[$i]}" "$state") done G_WHIP_CHECKLIST "Please (de)select options via spacebar to be shown in the $G_PROGRAM_NAME:" || return 0 for i in "${!aDESCRIPTION[@]}" do aENABLED[$i]=0 done for i in $G_WHIP_RETURNED_VALUE do aENABLED[$i]=1 # Custom entry (( $i == 10 )) || continue [[ -f $FP_CUSTOM ]] && read -r G_WHIP_DEFAULT_ITEM < "$FP_CUSTOM" || G_WHIP_DEFAULT_ITEM='echo '\''Hello World!'\' G_WHIP_INPUTBOX 'You have chosen to show a custom entry in the banner. Please enter the desired command here.\n NB: It is executed as bash script, so it needs to be in bash compatible syntax. For multi-line or non-bash scripts, keep it separate and only add the script call here.' || continue echo "$G_WHIP_RETURNED_VALUE" > "$FP_CUSTOM" G_WHIP_DEFAULT_ITEM=${aDESCRIPTION[10]} G_WHIP_INPUTBOX 'Please enter a meaningful name to be shown in front of your custom command output:' && aDESCRIPTION[10]=$G_WHIP_RETURNED_VALUE done [[ -f $FP_CUSTOM ]] || aENABLED[10]=0 Save > "$FP_SAVEFILE" } #///////////////////////////////////////////////////////////////////////////////////// # Main Loop #///////////////////////////////////////////////////////////////////////////////////// case $INPUT in 0) Print_Header; Print_Local_Ip;; 1) Print_Banner;; '') Menu_Main; Print_Banner;; *) G_DIETPI-NOTIFY 1 "Invalid input \"$*\"\n\nUsage:$USAGE"; exit 1;; esac #----------------------------------------------------------------------------------- exit 0 #----------------------------------------------------------------------------------- }