From 9bbbbaefd47636ce0e16a725c042de5f6e467bbe Mon Sep 17 00:00:00 2001 From: aristocratos Date: Sun, 10 May 2020 02:59:29 +0200 Subject: [PATCH 01/52] v0.8.28 Added: Option for higher resolution graphs, Fixed: Ctrl-C and Ctrl-Z --- CHANGELOG.md | 6 + README.md | 16 +- bashtop | 498 +++++++++++++++++++++++++++++++++++++++++++++------ 3 files changed, 459 insertions(+), 61 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d353288..ec45bcd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## v0.8.28 + +* Fixed: Ctrl-C and Ctrl-Z not registering after change to "dd" +* Added: Option to switch to high resolution graphs +* Added: Current peak value for download/upload graphs + ## v0.8.27 * Fixed: Use value for "Inactive"+"MemFree" if "MemAvailable" is missing in /proc/meminfo diff --git a/README.md b/README.md index 1626fa5..f80f7b9 100644 --- a/README.md +++ b/README.md @@ -109,7 +109,7 @@ Dropbear seems to not be able to set correct locale. So if accessing bashtop ove ## Dependencies -**[bash](https://www.gnu.org/software/bash/)** (v4.4 or later) Script functionality will most probably break with earlier versions. +**[bash](https://www.gnu.org/software/bash/)** (v4.4 or later) Script functionality will most probably break with earlier versions. Bash version 5 is highly recommended to make use of $EPOCHREALTIME variable instead of a lot of external date command calls. **[GNU Core Utilities](https://www.gnu.org/software/coreutils/)** @@ -130,13 +130,13 @@ Bash version 5 is highly recommended to make use of $EPOCHREALTIME variable inst ## Screenshots -Main UI showing details for a selected process. +Main UI showing details for a selected process. ![Screenshot 1](Imgs/main.png) -Main menu. +Main menu. ![Screenshot 2](Imgs/menu.png) -Options menu. +Options menu. ![Screenshot 3](Imgs/options.png) ## Installation @@ -233,7 +233,7 @@ Config files stored in "$HOME/.config/bashtop" folder #### bashtop.cfg: (auto generated if not found) ```bash -#? Config file for bashtop v. 0.8.22 +#? Config file for bashtop v. 0.8.28 #* Color theme, looks for a .theme file in "$HOME/.config/bashtop/themes", "Default" for builtin default theme color_theme="Default" @@ -271,6 +271,12 @@ proc_per_core="false" #* Optional filter for shown disks, should be names of mountpoints, "root" replaces "/", separate multiple values with space disks_filter="" + +#* Enable check for new version from github.com/aristocratos/bashtop at start +update_check="true" + +#* Enable graphs with double the horizontal resolution, increases cpu usage +hires_graphs="false" ``` #### Command line options: (not yet implemented) diff --git a/bashtop b/bashtop index abe949e..96f1fc9 100755 --- a/bashtop +++ b/bashtop @@ -64,7 +64,7 @@ banner=( "██╔══██╗██╔══██║╚════██║██╔══██║ ██║ ██║ ██║██╔═══╝ " "██████╔╝██║ ██║███████║██║ ██║ ██║ ╚██████╔╝██║ " "╚═════╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ") -declare version="0.8.27" +declare version="0.8.28" declare banner_width=${#banner[0]} banner_colors=("#E62525" "#CD2121" "#B31D1D" "#9A1919" "#801414") @@ -113,6 +113,9 @@ disks_filter="" #* Enable check for new version from github.com/aristocratos/bashtop at start update_check="true" +#* Enable graphs with double the horizontal resolution, increases cpu usage +hires_graphs="false" + aaz_config() { : ; } #! Do not remove this line! #? End default variables--------------------------------------------------------------------------------> @@ -149,7 +152,7 @@ declare -a cpu_usage cpu_graph_a cpu_graph_b color_meter color_temp_graph color_ declare -a mem_history swap_history net_history_download net_history_upload mem_graph swap_graph proc_array download_graph upload_graph trace_array declare resized=1 size_error clock tty_width tty_height hex="16#" cpu_p_box swap_on=1 draw_out esc_character boxes_out last_screen clock_out update_string declare -a options_array=("color_theme" "update_ms" "proc_sorting" "check_temp" "draw_clock" "background_update" "custom_cpu_name" "proc_per_core" - "proc_reversed" "proc_gradient" "disks_filter" "net_totals_reset" "update_check" "error_logging") + "proc_reversed" "proc_gradient" "disks_filter" "hires_graphs" "net_totals_reset" "update_check" "error_logging") declare -a save_array=(${options_array[*]/net_totals_reset/}) declare -a sorting=( "pid" "program" "arguments" "threads" "user" "memory" "cpu lazy" "cpu responsive" "tree" ) declare -a pid_history detail_graph detail_history detail_mem_history @@ -163,6 +166,8 @@ printf -v backspace "\u7F" #? Backspace set to DELETE printf -v backspace_real "\u08" #? Real backspace #printf -v enter_key "\uA" printf -v enter_key "\uD" +printf -v ctrl_c "\u03" +printf -v ctrl_z "\u1A" read tty_height tty_width < <(stty size) @@ -170,6 +175,21 @@ read tty_height tty_width < <(stty size) declare -a graph_symbol graph_symbol=(" " "⡀" "⣀" "⣄" "⣤" "⣦" "⣴" "⣶" "⣷" "⣾" "⣿") graph_symbol+=( " " "⣿" "⢿" "⡿" "⠿" "⠻" "⠟" "⠛" "⠙" "⠉" "⠈") +declare -A graph_symbol_up='( + [0_0]=⠀ [0_1]=⢀ [0_2]=⢠ [0_3]=⢰ [0_4]=⢸ + [1_0]=⡀ [1_1]=⣀ [1_2]=⣠ [1_3]=⣰ [1_4]=⣸ + [2_0]=⡄ [2_1]=⣄ [2_2]=⣤ [2_3]=⣴ [2_4]=⣼ + [3_0]=⡆ [3_1]=⣆ [3_2]=⣦ [3_3]=⣶ [3_4]=⣾ + [4_0]=⡇ [4_1]=⣇ [4_2]=⣧ [4_3]=⣷ [4_4]=⣿ +)' +declare -A graph_symbol_down='( + [0_0]=⠀ [0_1]=⠈ [0_2]=⠘ [0_3]=⠸ [0_4]=⢸ + [1_0]=⠁ [1_1]=⠉ [1_2]=⠙ [1_3]=⠹ [1_4]=⢹ + [2_0]=⠃ [2_1]=⠋ [2_2]=⠛ [2_3]=⠻ [2_4]=⢻ + [3_0]=⠇ [3_1]=⠏ [3_2]=⠟ [3_3]=⠿ [3_4]=⢿ + [4_0]=⡇ [4_1]=⡏ [4_2]=⡟ [4_3]=⡿ [4_4]=⣿ +)' +declare -A graph box[boxes]="cpu mem net processes" cpu[threads]=0 @@ -242,6 +262,7 @@ init_() { #? Collect needed information and set options before startig main loop tput smcup stty -echo tput civis + keys_stty="$(stty -g)" #* Check if "sensors" command is available, if not, disable temperature collection if [[ $check_temp != false ]] && command -v sensors >/dev/null 2>&1; then check_temp="true"; else check_temp="false"; fi @@ -258,6 +279,9 @@ init_() { #? Collect needed information and set options before startig main loop #* Get number of cores and cpu threads get_cpu_info + #* Set graph resolution + graph[hires]="${hires_graphs}" + #* Get processor BCLK local param_var if [[ -e /usr/include/asm-generic/param.h ]]; then @@ -468,7 +492,6 @@ color_init_() { #? Check for theme file and set colors quit_() { #? Clean exit #* Restore terminal options and screen tput rmcup - stty echo tput cnorm stty "${saved_stty}" @@ -482,7 +505,6 @@ quit_() { #? Clean exit sleep_() { #? Restore terminal options, stop and send to background if caught SIGTSTP (ctrl+z) tput rmcup - stty echo tput cnorm stty "${saved_stty}" @@ -1002,6 +1024,8 @@ create_graph() { #? Create a graph from an array of percentage values, usage; #? Add last value from an array to existing graph; create_graph [-i, -invert] [-max "max value"] -add-last "graph_array" "value-array" #? Options: < -d, -dimensions > [-i, -invert] [-n, -no-guide] [-c, -color "array-name"] [-o, -output-array "variable-name"] if [[ -z $1 ]]; then return; fi + if [[ ${graph[hires]} == true ]]; then create_graph_hires "$@"; return; fi + local val col s_col line s_line height s_height width s_width colors color i var ext_var out side_num side_nums=1 add add_array invert no_guide max local -a graph_array input_array @@ -1189,6 +1213,9 @@ create_mini_graph() { #? Create a one line high graph from an array of percenta #? Add last value from an array to existing graph; create_mini_graph [-i, -invert] [-nc, -no-color] [-c, -color "array-name"] -add-last "graph_variable" "value-array" #? Options: [-w, -width ] [-i, -invert] [-nc, -no-color] [-c, -color "array-name"] [-o, -output-variable "variable-name"] if [[ -z $1 ]]; then return; fi + + if [[ ${graph[hires]} == true ]]; then create_mini_graph_hires "$@"; return; fi + local val col s_col line s_line height s_height width s_width colors color i var ext_var out side_num side_nums=1 add invert no_guide graph_var no_color color_value #* Argument parsing @@ -1297,6 +1324,371 @@ create_mini_graph() { #? Create a one line high graph from an array of percenta else output_var="${graph_var}"; fi } +create_graph_hires() { #? Create a graph from an array of percentage values, usage; create_graph + #? Create a graph from an array of non percentage values: create_graph <-max "max value"> + #? Add a value to existing graph; create_graph [-i, -invert] [-max "max value"] -add-value "graph_array" + #? Add last value from an array to existing graph; create_graph [-i, -invert] [-max "max value"] -add-last "graph_array" "value-array" + #? Options: < -d, -dimensions > [-i, -invert] [-n, -no-guide] [-c, -color "array-name"] [-o, -output-array "variable-name"] + if [[ -z $1 ]]; then return; fi + local val col s_col line s_line height s_height width s_width colors color var ext_var out side_num side_nums=1 add add_array invert no_guide max graph_name offset=0 last_val + local -a input_array + local -i i + + #* Argument parsing + until (($#==0)); do + case $1 in + -d|-dimensions) if is_int "${@:2:4}"; then line=$2; col=$3; height=$4; width=$5; shift 4; fi;; #? Graph dimensions + -c|-color) local -n colors=$2; shift;; #? Name of an array containing colors from index 0-100 + -o|-output-array) local -n output_array=$2; graph_name=$2; ext_var=1; shift;; #? Output meter to an array + -add-value) if is_int "$3"; then local -n output_array=$2; graph_name=$2; add=$3; break; else return; fi;; #? Add a value to existing graph + -add-last) local -n output_array=$2; graph_name=$2; local -n add_array=$3; add=${add_array[-1]}; break;; #? Add last value from array to existing graph + -i|-invert) invert=1;; #? Invert graph, drawing from top to bottom + -n|-no-guide) no_guide=1;; #? Don't print side and bottom guide lines + -max) if is_int "$2"; then max=$2; shift; fi;; #? Needed max value for non percentage arrays + *) local -n tmp_in_array="$1"; input_array=("${tmp_in_array[@]}");; + esac + shift + done + + local -n last_val="graph[${graph_name}_last_val]" + local -n last_type="graph[${graph_name}_last_type]" + + + if [[ -z $add ]]; then + last_type="even" + last_val=0 + local -n graph_array="${graph_name}_odd" + local -n graph_even="${graph_name}_even" + graph_even=("") + graph_array=("") + elif [[ ${last_type} == "even" ]]; then + local -n graph_array="${graph_name}_odd" + last_type="odd" + elif [[ ${last_type} == "odd" ]]; then + local -n graph_array="${graph_name}_even" + last_type="even" + fi + + if [[ -z $no_guide ]]; then ((--height)) + elif [[ -n $invert ]]; then ((line--)) + fi + + if ((width<3)); then width=3; fi + if ((height<1)); then height=1; fi + + + #* If argument "add" was passed check for existing graph and make room for new value(s) + local add_start add_end + if [[ -n $add ]]; then + local cut_left search + if [[ -n ${input_array[*]} || -z ${graph_array[0]} ]]; then return; fi + + height=$((${#graph_array[@]}-1)) + input_array=("${add}") + + #* Remove last value in current graph + + for ((i=0;i=0;i--)); do + g_index+=($i) + done + + else + for((i=0;i<=height;i++)); do + g_index+=($i) + done + fi + + if [[ -n $no_guide ]]; then unset normal_vals + elif [[ -n $invert ]]; then g_char=(" ⡇" " ⡤" "⠤") + fi + + #* Set up graph array print side numbers and lines + print -v graph_array[0] -rs -m $((line+g_index[0])) ${col} ${normal_vals:+-jr 3 -fg ee -b -t "${side_num[0]}" -rs -fg ${theme[main_fg]} -t "${g_char[0]}"} -fg ${colors[100]} + for((i=1;i=max)); then + input_array[i]=100 + else + input_array[i]=$((input_array[i]*100/max)) + fi + done + if [[ -n $converted ]]; then + last_val=$((${last_val}*100/max)) + if ((${last_val}>100)); then last_val=100; fi + fi + fi + + if [[ -n $invert ]]; then local -n symbols=graph_symbol_down + else local -n symbols=graph_symbol_up + fi + + until ((y==done_val)); do + + next_line=$(( virt_height-((y+1)*4) )) + unset p_val + + #* Create graph by walking through all values for each line + for ((x=0;x<${#input_array[@]};x++)); do + c_val=${input_array[x]} + p_val=${p_val:-${last_val}} + cur_value="$((c_val*virt_height/100-next_line))" + prev_value=$((p_val*virt_height/100-next_line)) + + if ((cur_value<0)); then cur_value=0 + elif ((cur_value>4)); then cur_value=4; fi + if ((prev_value<0)); then prev_value=0 + elif ((prev_value>4)); then prev_value=4; fi + + if [[ -z $add ]] && ((x==0)); then + print -v graph_even[y] -t "${symbols[${prev_value}_${cur_value}]}" + print -v graph_array[y] -t "${symbols[0_${prev_value}]}" + elif [[ -z $add ]] && ! ((x%2)); then + print -v graph_even[y] -t "${symbols[${prev_value}_${cur_value}]}" + else + print -v graph_array[y] -t "${symbols[${prev_value}_${cur_value}]}" + fi + + if [[ -z $add ]]; then p_val=${input_array[x]}; else unset p_val; fi + + done + + if [[ -n $invert ]]; then + ((y--)) || true + else + ((++y)) + fi + + done + + if [[ -z $add && ${last_type} == "even" ]]; then + declare -n graph_array="${graph_name}_even" + fi + + last_val=$c_val + + output_array=("${graph_array[@]}") +} + + +create_mini_graph_hires() { #? Create a one line high graph from an array of percentage values, usage; create_mini_graph + #? Add a value to existing graph; create_mini_graph [-i, -invert] [-nc, -no-color] [-c, -color "array-name"] -add-value "graph_variable" + #? Add last value from an array to existing graph; create_mini_graph [-i, -invert] [-nc, -no-color] [-c, -color "array-name"] -add-last "graph_variable" "value-array" + #? Options: [-w, -width ] [-i, -invert] [-nc, -no-color] [-c, -color "array-name"] [-o, -output-variable "variable-name"] + if [[ -z $1 ]]; then return; fi + local val col s_col line s_line height s_height width s_width colors color var ext_var out side_num side_nums=1 add invert no_guide graph_var no_color color_value graph_name + local -a input_array + local -i i + + #* Argument parsing + until (($#==0)); do + case $1 in + -w|-width) if is_int "$2"; then width=$2; shift; fi;; #? Graph width + -c|-color) local -n colors=$2; shift;; #? Name of an array containing colors from index 0-100 + -nc|-no-color) no_color=1;; #? Set no color + -o|-output-variable) local -n output_var=$2; graph_name=$2; ext_var=1; shift;; #? Output graph to a variable + -add-value) if is_int "$3"; then local -n output_var=$2; graph_name=$2; add=$3; break; else return; fi;; #? Add a value to existing graph + -add-last) local -n output_var=$2; local -n add_array=$3; graph_name=$2; add="${add_array[-1]:-0}"; break;; #? Add last value from array to existing graph + -i|-invert) invert=1;; #? Invert graph, drawing from top to bottom + *) local -n tmp_in_arr=$1; input_array=("${tmp_in_arr[@]}");; + esac + shift + done + + local -n last_val="${graph_name}_last_val" + local -n last_type="${graph_name}_last_type" + + if [[ -z $add ]]; then + last_type="even" + last_val=0 + local -n graph_var="${graph_name}_odd" + local -n graph_other="${graph_name}_even" + graph_var=""; graph_other="" + elif [[ ${last_type} == "even" ]]; then + local -n graph_var="${graph_name}_odd" + last_type="odd" + elif [[ ${last_type} == "odd" ]]; then + local -n graph_var="${graph_name}_even" + last_type="even" + fi + + if ((width<1)); then width=1; fi + + #* If argument "add" was passed check for existing graph and make room for new value(s) + local add_start add_end + if [[ -n $add ]]; then + local cut_left search + input_array[0]=${add} + + #* Remove last value in current graph + if [[ -n ${graph_var} && -z $no_color ]]; then + if [[ ${graph_var::5} == '\e[1C' ]]; then + graph_var="${graph_var#'\e[1C'}" + else + cut_left="${graph_var%m*}" + search=$((${#cut_left}+1)) + graph_var="${graph_var::$search}${graph_var:$((search+1))}" + fi + elif [[ -n ${graph_var} && -n $no_color ]]; then + if [[ ${graph_var::5} == "\e[1C" ]]; then + #cut_left="${graph_var%%C*}" + #search=$((${#cut_left}+1)) + #graph_var="${graph_var:$((search))}" + graph_var="${graph_var#'\e[1C'}" + else + graph_var="${graph_var:1}" + fi + fi + fi + + + #* If no color array was given, create a simple greyscale array + if [[ -z $colors && -z $no_color ]]; then + for ((i=0,ic=50;i<=100;i++,ic=ic+2)); do + colors[i]="${ic} ${ic} ${ic}" + done + fi + + + #* Create the graph + local value_width x=0 y a cur_value prev_value p_val c_val acolor jump odd offset=0 + if [[ -n $add ]]; then + value_width=1 + elif ((${#input_array[@]}<=width*2)); then + value_width=$((${#input_array[@]}*2)) + else + value_width=$((width*2)) + input_array=("${input_array[@]:(-${value_width})}") + fi + + if [[ -z $add ]] && ! ((${#input_array[@]}%2)); then last_val=${input_array[0]}; input_array=("${input_array[@]:1}"); fi + + #* Print spaces to right-justify graph if number of values is less than graph width + if [[ -z $add ]] && ((${#input_array[@]}/2=85)); then cur_value=4 + elif ((c_val>=60)); then cur_value=3 + elif ((c_val>=30)); then cur_value=2 + elif ((c_val>=10)); then cur_value=1 + elif ((c_val<10)); then cur_value=0; fi + + if ((p_val>=85)); then prev_value=4 + elif ((p_val>=60)); then prev_value=3 + elif ((p_val>=30)); then prev_value=2 + elif ((p_val>=10)); then prev_value=1 + elif ((p_val<10)); then prev_value=0; fi + + if [[ -z $no_color ]]; then + if ((c_val>p_val)); then acolor=$((c_val-p_val)) + else acolor=$((p_val-c_val)); fi + if ((acolor>100)); then acolor=100; elif ((acolor<0)); then acolor=0; fi + color="-fg ${colors[${acolor:-0}]} " + else + unset color + fi + + if ((cur_value==0 & prev_value==0)); then jump="\e[1C"; else unset jump; fi + + if [[ -z $add ]] && ((i==0)); then + print -v graph_other ${color}-t "${jump:-${symbols[${prev_value}_${cur_value}]}}" + print -v graph_var ${color}-t "${jump:-${symbols[0_${prev_value}]}}" + elif [[ -z $add ]] && ((i%2)); then + print -v graph_other ${color}-t "${jump:-${symbols[${prev_value}_${cur_value}]}}" + else + print -v graph_var ${color}-t "${jump:-${symbols[${prev_value}_${cur_value}]}}" + fi + + if [[ -z $add ]]; then p_val=$c_val; else unset p_val; fi + done + + #if [[ -z $add ]]; then + # declare -n graph_var="${graph_name}_even" + # #echo "yup" >&2 + #fi + + last_val=$c_val + + output_var="${graph_var}" +} + print() { #? Print text, set true-color foreground/background color, add effects, center text, move cursor, save cursor position and restore cursor postion #? Effects: [-fg, -foreground | ] [-bg, -background | ] [-rs, -reset] [-/+b, -/+bold] [-/+da, -/+dark] #? [-/+ul, -/+underline] [-/+i, -/+italic] [-/+bl, -/+blink] [-f, -font "sans-serif|script|fraktur|monospace|double-struck"] @@ -1436,8 +1828,8 @@ collect_cpu() { #? Collects cpu stats from /proc/stat and compares with previous for((i=1;i<=threads;i++)); do local -n cpu_core_history="cpu_core_history_$i" - if ((${#cpu_core_history[@]}>20)); then - cpu_core_history=( "${cpu_core_history[@]:10}" "${cpu_usage[$i]}") + if ((${#cpu_core_history[@]}>40)); then + cpu_core_history=( "${cpu_core_history[@]:20}" "${cpu_usage[$i]}") else cpu_core_history+=("${cpu_usage[$i]}") fi @@ -1552,10 +1944,10 @@ collect_cpu_temps() { #? Collect cpu temperatures if [[ $check_temp == true ]]; then for((i=0;i<=threads;i++)); do local -n cpu_temp_history="cpu_temp_history_$i" - if ((${#cpu_temp_history[@]}>15)); then - cpu_temp_history=( "${cpu_temp_history[@]:10}" "$(( (${cpu[temp_${i}]}-15)*100/(cpu[temp_high]-15) ))") + if ((${#cpu_temp_history[@]}>20)); then + cpu_temp_history=( "${cpu_temp_history[@]:10}" "$(( (${cpu[temp_${i}]}-20)*100/(cpu[temp_high]-20) ))") else - cpu_temp_history+=("$(( (${cpu[temp_${i}]}-15)*100/(cpu[temp_high]-15) ))") + cpu_temp_history+=("$(( (${cpu[temp_${i}]}-20)*100/(cpu[temp_high]-20) ))") fi done fi @@ -1870,18 +2262,18 @@ collect_processes() { #? Collect process information and calculate accurate cpu if [[ ${cpu_int} -gt 0 ]]; then pid_count=5; fi if [[ -z ${!pid_graph} && ${cpu_int} -gt 0 ]]; then - tmp_value_array=("$((cpu_int+4))") + tmp_value_array=("$((cpu_int+4))") create_mini_graph -o "pid_${pid}_graph" -nc -w 5 "tmp_value_array" elif [[ ${pid_count} -gt 0 ]]; then if [[ ${cpu_int} -gt 9 ]]; then - create_mini_graph -nc -add-value "pid_${pid}_graph" "$((cpu_int+20))" + create_mini_graph -nc -add-value "pid_${pid}_graph" "$((cpu_int+15))" else - create_mini_graph -nc -add-value "pid_${pid}_graph" "$((cpu_int+4))" + create_mini_graph -nc -add-value "pid_${pid}_graph" "$((cpu_int+9))" fi pid_count=$((${pid_count}-1)) elif [[ ${pid_count} == "0" ]]; then - unset "pid_${pid}_graph" + unset "pid_${pid}_graph" "pid_${pid}_graph_even" "pid_${pid}_graph_odd" "pid_${pid}_graph_last_type" "pid_${pid}_graph_last_val" unset "pid_${pid}_count" fi else @@ -1930,7 +2322,7 @@ collect_processes() { #? Collect process information and calculate accurate cpu proc[general_counter]=0 for ((i=0;i<${#pid_history[@]};i++)); do if [[ -n ${pid_history[$i]} && ! -e /proc/${pid_history[$i]} ]]; then - unset "pid_${pid_history[$i]}_graph" + unset "pid_${pid_history[$i]}_graph" "pid_${pid_history[$i]}_graph_even" "pid_${pid_history[$i]}_graph_odd" "pid_${pid_history[$i]}_graph_last_type" "pid_${pid_history[$i]}_graph_last_val" unset "pid_${pid_history[$i]}_count" unset "proc[new_${pid_history[$i]}_ticks]" unset "proc[old_${pid_history[$i]}_ticks]" @@ -2023,6 +2415,8 @@ collect_net() { #? Collect information from "/proc/net/dev" fi fi + floating_humanizer -Byte -short -v net[${direction}_max_string] ${net[${direction}_graph_max]} + net[old_${direction}]=${net[new_${direction}]} done @@ -2189,13 +2583,15 @@ draw_cpu() { #? Draw cpu and core graphs and print percentages create_graph -o cpu_graph_a -d ${line} ${col} ${graph_a_size} $((width-p_width-2)) -c color_cpu_graph -n cpu_history create_graph -o cpu_graph_b -d $((line+graph_a_size)) ${col} ${graph_b_size} $((width-p_width-2)) -c color_cpu_graph -i -n cpu_history - for((i=1;i<=threads;i++)); do - create_mini_graph -o "cpu_core_graph_$i" -w 10 -c color_cpu_graph "cpu_core_history_$i" - done + if [[ -z ${cpu_core_1_graph} ]]; then + for((i=1;i<=threads;i++)); do + create_mini_graph -o "cpu_core_${i}_graph" -w 10 -nc "cpu_core_history_${i}" + done + fi - if [[ $check_temp == true ]]; then + if [[ $check_temp == true && -z ${cpu_temp_0_graph} ]]; then for((i=0;i<=threads;i++)); do - if [[ -n ${cpu[temp_${i}]} ]]; then create_mini_graph -o "cpu_temp_graph_$i" -w 5 -c color_temp_graph "cpu_temp_history_$i"; fi + if [[ -n ${cpu[temp_${i}]} ]]; then create_mini_graph -o "cpu_temp_${i}_graph" -w 5 -nc "cpu_temp_history_${i}"; fi done fi ((resized++)) @@ -2206,14 +2602,12 @@ draw_cpu() { #? Draw cpu and core graphs and print percentages create_graph -add-last cpu_graph_a cpu_history create_graph -i -add-last cpu_graph_b cpu_history for((i=1;i<=threads;i++)); do - declare -n core_hist="cpu_core_history_${i}[-1]" - create_mini_graph -w 10 -c color_cpu_graph -add-value "cpu_core_graph_$i" ${core_hist} + create_mini_graph -w 10 -nc -add-last "cpu_core_${i}_graph" "cpu_core_history_${i}" done if [[ $check_temp == true ]]; then for((i=0;i<=threads;i++)); do if [[ -n ${cpu[temp_${i}]} ]]; then - declare -n temp_hist="cpu_temp_history_${i}[-1]" - create_mini_graph -w 5 -c color_temp_graph -add-value "cpu_temp_graph_$i" ${temp_hist} + create_mini_graph -w 5 -nc -add-last "cpu_temp_${i}_graph" "cpu_temp_history_${i}" fi done fi @@ -2233,7 +2627,7 @@ draw_cpu() { #? Draw cpu and core graphs and print percentages #* Get color of temperature text depending on current temp vs factory high temp declare -n temp_hist="cpu_temp_history_${i}[-1]" temp_color="${color_temp_graph[${temp_hist}]}" - temp_name="cpu_temp_graph_$i" + temp_name="cpu_temp_${i}_graph" temp_width=13 fi @@ -2246,7 +2640,7 @@ draw_cpu() { #? Draw cpu and core graphs and print percentages if ((i==0)); then create_meter -v meter -w $meter_width -f -c color_cpu_graph ${cpu_usage[i]} else - core_name="cpu_core_graph_$i" + core_name="cpu_core_${i}_graph" meter="${!core_name}" fi @@ -2255,10 +2649,10 @@ draw_cpu() { #? Draw cpu and core graphs and print percentages elif ((p_width>24+temp_width & i>=p_height-2)); then pt_line=$((p_line+i-y*2)); pt_col=$((p_col+24+temp_width)) else y=$i; fi - print -v cpu_out_var -m $((pt_line+y)) $pt_col -rs -fg $p_normal_color -jl 7 -t "$name" -fg ${theme[inactive_fg]} "⡀⡀⡀⡀⡀⡀⡀⡀⡀⡀" -l 10 -t "$meter"\ - -fg $cpu_p_color -jr 4 -t "${cpu_usage[i]}" -fg $p_normal_color -t "%" + print -v cpu_out_var -m $((pt_line+y)) $pt_col -rs -fg $p_normal_color -jl 7 -t "$name" -fg ${theme[inactive_fg]} "⡀⡀⡀⡀⡀⡀⡀⡀⡀⡀" -l 10 -fg $cpu_p_color -t "$meter"\ + -jr 4 -fg $cpu_p_color -t "${cpu_usage[i]}" -fg $p_normal_color -t "%" if [[ $check_temp == true && -n ${cpu[temp_${i}]} ]]; then - print -v cpu_out_var -fg ${theme[inactive_fg]} " ⡀⡀⡀⡀⡀" -l 7 -t " ${!temp_name}" -fg $temp_color -jr 4 -t ${cpu[temp_${i}]} -fg $p_normal_color -t ${cpu[temp_unit]} + print -v cpu_out_var -fg ${theme[inactive_fg]} " ⡀⡀⡀⡀⡀" -l 7 -fg $temp_color -jl 7 -t " ${!temp_name}" -jr 4 -t ${cpu[temp_${i}]} -fg $p_normal_color -t ${cpu[temp_unit]} fi if (( i>(p_height-2)*( p_width/(24+temp_width) )-( p_width/(24+temp_width) )-1 )); then break; fi @@ -2698,6 +3092,9 @@ draw_net() { #? Draw net information and graphs to screen if ((height>7)); then print -v net_out -fg ${main_fg} -m $((ypos++)) $n_col -jl 10 -t "▲ Bit:" -jr 12 -t "${net[speed_upload_bitps]}"; fi if ((height>5)); then print -v net_out -fg ${main_fg} -m $((ypos++)) $n_col -jl 10 -t "▲ Total:" -jr 12 -t "${net[total_upload]}"; fi + print -v net_out -fg ${theme[inactive_fg]} -m $line $col -t "${net[download_max_string]}" + print -v net_out -fg ${theme[inactive_fg]} -m $((line+height-1)) $col -t "${net[upload_max_string]}" + #* Print graphs and text to output variable draw_out+="${download_graph[*]}${upload_graph[*]}${net_out}" @@ -2801,9 +3198,7 @@ menu_() { #? Shows the main menu overlay get_ms timestamp_end time_left=$((timestamp_start+update_ms-timestamp_end)) - # if ((time_left>1000)); then wait_string=1; time_left=$((time_left-1000)) - # elif ((time_left>1)); then printf -v wait_string ".%03d" "${time_left}"; time_left=0 - # else wait_string="0.001"; time_left=0; fi + if ((time_left>1000)); then wait_string=10; time_left=$((time_left-1000)) elif ((time_left>100)); then wait_string=$((time_left/100)); time_left=0 else wait_string="0"; time_left=0; fi @@ -2921,10 +3316,6 @@ help_() { #? Shows the help overlay get_ms timestamp_end time_left=$((timestamp_start+update_ms-timestamp_end)) - # if ((time_left>1000)); then wait_string=1; time_left=$((time_left-1000)) - # elif ((time_left>0)); then printf -v wait_string ".%03d" "${time_left}"; time_left=0 - # else wait_string="0.001"; time_left=0; fi - if ((time_left>1000)); then wait_string=10; time_left=$((time_left-1000)) elif ((time_left>100)); then wait_string=$((time_left/100)); time_left=0 else wait_string="0"; time_left=0; fi @@ -3054,6 +3445,13 @@ options_() { #? Shows the options overlay "github.com/aristocratos/bashtop at start." " " "True or False.") + desc_hires_graphs=("Enable high resolution graphs." + " " + "Doubles the horizontal resolution of all" + "graphs. At a cpu usage cost." + "Needs restart to take effect." + " " + "True or False.") if [[ -n $pause_screen ]]; then from_menu=1; fi @@ -3155,9 +3553,6 @@ options_() { #? Shows the options overlay get_ms timestamp_end if [[ -z $theme_check ]]; then time_left=$((timestamp_start+update_ms-timestamp_end)) else unset theme_check; time_left=0; fi - # if ((time_left>500)); then wait_string=0.5 - # elif ((time_left>0)); then printf -v wait_string ".%03d" "${time_left}" - # else wait_string="0.001"; time_left=0; fi if ((time_left>500)); then wait_string=5; time_left=$((time_left-500)) elif ((time_left>100)); then wait_string=$((time_left/100)); time_left=0 @@ -3231,7 +3626,7 @@ options_() { #? Shows the options overlay if ((net[reset]==1)); then net_totals_reset="Off"; net[reset]=0 else net_totals_reset="On"; net[reset]=1; fi ;; - "check_temp"*|"error_logging"*|"background_update"*|"proc_reversed"*|"proc_gradient"*|"proc_per_core"*|"update_check"*) + "check_temp"*|"error_logging"*|"background_update"*|"proc_reversed"*|"proc_gradient"*|"proc_per_core"*|"update_check"*|"hires_graphs"*) local -n selected_var=${selected} if [[ ${selected_var} == "true" ]]; then selected_var="false" @@ -3364,9 +3759,6 @@ killer_() { #? Kill process with selected signal get_ms timestamp_end time_left=$((timestamp_start+update_ms-timestamp_end)) - # if ((time_left>1000)); then wait_string=1; time_left=$((time_left-1000)) - # elif ((time_left>1)); then printf -v wait_string ".%03d" "${time_left}"; time_left=0 - # else wait_string="0.001"; time_left=0; fi if ((time_left>1000)); then wait_string=10; time_left=$((time_left-1000)) elif ((time_left>100)); then wait_string=$((time_left/100)); time_left=0 @@ -3390,8 +3782,6 @@ killer_() { #? Kill process with selected signal q|Q) quit_ ;; esac - - if ((confirmed<0)); then unpause_ break @@ -3435,21 +3825,23 @@ get_key() { #? Get one key from standard input and translate key code to readabl if [[ -z $save && -n ${saved_key[0]} ]]; then key="${saved_key[0]}"; unset 'saved_key[0]'; saved_key=("${saved_key[@]}") else unset key - #IFS= read -rsd '' -t ${wait_time:-0.001} -n 1 key 2>/dev/null ||true - key=$(stty -cooked min 0 time ${wait_time:-0}; dd bs=1 count=1 2>/dev/null) + key=$(stty -cooked min 0 time ${wait_time:-0}; dd bs=1 count=1 2>/dev/null) if [[ -z ${key:+s} ]]; then key_out="" + stty isig if [[ -z $save ]]; then return 0 else return 1; fi fi #* Read 3 more characters if a leading escape character is detected if [[ $key == "${enter_key}" ]]; then key="enter" + elif [[ $key == "${ctrl_c}" ]]; then quitting=1; time_left=0 + elif [[ $key == "${ctrl_z}" ]]; then sleepy=1; time_left=0 elif [[ $key == "${backspace}" || $key == "${backspace_real}" ]]; then key="backspace" elif [[ $key == "${tab}" ]]; then key="tab" elif [[ $key == "$esc_character" ]]; then - esc=1; key=$(stty -cooked min 0 time 0; dd bs=1 count=3 2>/dev/null); fi # read -rsn3 -t 0.001 key 2>/dev/null || true + esc=1; key=$(stty -cooked isig min 0 time 0; dd bs=1 count=3 2>/dev/null); fi if [[ -z $key && $esc -eq 1 ]]; then key="escape" elif [[ $esc -eq 1 ]]; then case "${key}" in @@ -3482,9 +3874,8 @@ get_key() { #? Get one key from standard input and translate key code to readabl fi - #read -rst 0.001 -n 1000 2>/dev/null ||true - stty -cooked min 0 time 0; dd bs=512 count=1 >/dev/null 2>&1 - + stty -cooked isig min 0 time 0; dd bs=512 count=1 >/dev/null 2>&1 + stty isig if [[ -n $save && -n $key ]]; then saved_key+=("${key}"); return 0; fi if [[ -n $ext_out ]]; then key_out="${key}" @@ -3716,21 +4107,16 @@ main_loop() { #? main loop... #* If NOT waiting for input and time left is greater than 500ms, wait 500ms and loop if [[ -z $input_to_filter ]] && ((time_left>=500)); then - # wait_string="0.5" wait_string="5" time_left=$((time_left-500)) #* If waiting for input and time left is greater than "50 ms", wait 50ms and loop - # elif [[ -n $input_to_filter ]] && ((time_left>=50)); then - # wait_string="0.05" - # time_left=$((time_left-50)) elif [[ -n $input_to_filter ]] && ((time_left>=100)); then wait_string="1" time_left=$((time_left-100)) #* Else format wait string with padded zeroes if needed and break loop else - #printf -v wait_string ".%03d" "${time_left}" if ((time_left>=100)); then wait_string=$((time_left/100)); else wait_string=0; fi time_left=0 fi @@ -3780,7 +4166,7 @@ else fi #* Set up traps for ctrl-c, soft kill, window resize, ctrl-z and resume from ctrl-z -trap 'quitting=1; time_left=0' SIGINT #SIGQUIT SIGTERM +trap 'quitting=1; time_left=0' SIGINT SIGQUIT SIGTERM trap 'resized=1; time_left=0' SIGWINCH trap 'sleepy=1; time_left=0' SIGTSTP trap 'resume_' SIGCONT From 54ff694f79fe641b4a6518b95372644753064bee Mon Sep 17 00:00:00 2001 From: aristocratos Date: Sun, 10 May 2020 20:24:45 +0200 Subject: [PATCH 02/52] changes to net graph rescaling parameters --- bashtop | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/bashtop b/bashtop index 96f1fc9..ac0bd05 100755 --- a/bashtop +++ b/bashtop @@ -2381,12 +2381,9 @@ collect_net() { #? Collect information from "/proc/net/dev" if ((${net[speed_${direction}]}>${net[${direction}_graph_max]})); then ((++net[${direction}_new_max])) if ((net[${direction}_new_low]>0)); then ((net[${direction}_new_low]--)); fi - elif ((${net[${direction}_graph_max]}>10<<10 & ${net[speed_${direction}]}<${net[${direction}_graph_max]}/8)); then + elif ((${net[${direction}_graph_max]}>10<<10 & ${net[speed_${direction}]}<${net[${direction}_graph_max]}/10)); then ((++net[${direction}_new_low])) if ((net[${direction}_new_max]>0)); then ((net[${direction}_new_max]--)); fi - # else - # net[${direction}_new_low]=0 - # net[${direction}_new_max]=0 fi #* Copy download and upload speed to history arrays and trim earlier entries @@ -2399,7 +2396,7 @@ collect_net() { #? Collect information from "/proc/net/dev" #* Check for new max value and set flag to adjust resolution of graph if needed if ((${net[${direction}_new_max]}>=5)); then - net[${direction}_graph_max]=$((${net[${direction}_max]}+(${net[${direction}_max]}/2) )) + net[${direction}_graph_max]=$((${net[${direction}_max]}+(${net[${direction}_max]}/3) )) net[${direction}_redraw]=1 net[${direction}_new_max]=0 From 55d0c3e2d25580fc8788c6eaf73a1f4dd30d18c1 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Mon, 11 May 2020 16:52:11 +0200 Subject: [PATCH 03/52] Fixed: Unescaped "\" in process list and indent fixes. --- bashtop | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/bashtop b/bashtop index ac0bd05..590cc01 100755 --- a/bashtop +++ b/bashtop @@ -12,6 +12,8 @@ # shellcheck disable=SC2004 #arithmetic brackets warning # shellcheck disable=SC2017 #arithmetic precision warning # shellcheck disable=SC2207 #split array warning +# shellcheck disable=SC2154 #variable referenced but not assigned +# shellcheck disable=SC1003 #info: single quote escape # Copyright 2020 Aristocratos @@ -412,8 +414,8 @@ color_init_() { #? Check for theme file and set colors hex2rgb=${hex2rgb//#/} - if [[ ${#hex2rgb} == 6 ]] && is_hex "$hex2rgb"; then hex2rgb="$((${hex}${hex2rgb:0:2})) $((${hex}${hex2rgb:2:2})) $((${hex}${hex2rgb:4:2}))" - elif [[ ${#hex2rgb} == 2 ]] && is_hex "$hex2rgb"; then hex2rgb="$((${hex}${hex2rgb:0:2})) $((${hex}${hex2rgb:0:2})) $((${hex}${hex2rgb:0:2}))" + if [[ ${#hex2rgb} == 6 ]] && is_hex "$hex2rgb"; then hex2rgb="$((${hex}${hex2rgb:0:2})) $((${hex}${hex2rgb:2:2})) $((${hex}${hex2rgb:4:2}))" + elif [[ ${#hex2rgb} == 2 ]] && is_hex "$hex2rgb"; then hex2rgb="$((${hex}${hex2rgb:0:2})) $((${hex}${hex2rgb:0:2})) $((${hex}${hex2rgb:0:2}))" else dec_test=(${hex2rgb}) if [[ ${#dec_test[@]} -eq 3 ]] && is_int "${dec_test[@]}"; then hex2rgb="${dec_test[*]}" @@ -2100,7 +2102,7 @@ collect_processes() { #? Collect process information and calculate accurate cpu unset 'proc[detailed_cpu]' if [[ -z $filter ]]; then - options="-t" + options="-t" fi readarray ${options} proc_array < <(ps ax${tree:+f} -o pid:${proc[pid_len]}=Pid:,comm:${format_cmd}=${tree:-Program:}${format_args},nlwp:3=Tr:,euser:6=User:,pmem=Mem%,pcpu:10=Cpu% --sort ${proc[reverse]:--}${sort}) @@ -2110,7 +2112,7 @@ collect_processes() { #? Collect process information and calculate accurate cpu if [[ -n $filter ]]; then grep_array[0]="${proc_array[0]}" - readarray -O 1 -t grep_array < <(echo -e " ${proc_array[*]:1}" | grep -e "${filter}" ${proc[detailed_pid]:+-e ${proc[detailed_pid]}} | cut -c 2- || true) + readarray -O 1 -t grep_array < <(echo -e " ${proc_array[*]:1}" | grep -e "${filter}" ${proc[detailed_pid]:+-e ${proc[detailed_pid]}} | cut -c 2- || true) proc_array=("${grep_array[@]}") fi @@ -2126,7 +2128,7 @@ collect_processes() { #? Collect process information and calculate accurate cpu get_ms proc[new_timestamp] for readline in "${proc_array[@]:1}"; do - ((++count)) + ((++count)) if ((count==height-3 & breaking==0)); then if [[ -n $filter || $proc_sorting != "cpu lazy" || ${proc[selected]} -gt 0 || ${proc[page]} -gt 1 || ${proc_reversed} == true ]]; then : @@ -2732,7 +2734,7 @@ draw_mem() { #? Draw mem, swap and disk statistics if [[ -z $meter_mod_w ]]; then print -v mem_out -jr 4 -t "${type_name[${value}_percent]}%"; fi fi done - done + done #* Create text and meters for disks and adapt sizes based on available height @@ -2944,6 +2946,8 @@ draw_processes() { #? Draw processes and values to screen pid="${out_line::$((proc[pid_len]+1))}"; pid="${pid// /}" pid_graph="pid_${pid}_graph" + out_line="${out_line//'\'/'\\'}" + if ((current_num==proc[selected])); then print -v proc_out -bg ${theme[selected_bg]} -fg ${theme[selected_fg]} -b; proc[selected_pid]="$pid" else print -v proc_out -rs -fg $((fg_r-fg_step_r)) $((fg_b-fg_step_b)) $((fg_b-fg_step_b)); fi From cea0a87b968788ce7c5e0560266d6373601d7475 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Mon, 11 May 2020 19:56:26 +0200 Subject: [PATCH 04/52] Fix cpu temp colors not working when above high temp --- bashtop | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/bashtop b/bashtop index 590cc01..ba90df8 100755 --- a/bashtop +++ b/bashtop @@ -1944,12 +1944,14 @@ collect_cpu_temps() { #? Collect cpu temperatures fi if [[ $check_temp == true ]]; then + local tmp_temp="$(( (${cpu[temp_${i}]}-20)*100/(cpu[temp_high]-20) ))" + if ((tmp_temp>100)); then tmp_temp=100; elif ((tmp_temp<0)); then tmp_temp=0; fi for((i=0;i<=threads;i++)); do local -n cpu_temp_history="cpu_temp_history_$i" if ((${#cpu_temp_history[@]}>20)); then - cpu_temp_history=( "${cpu_temp_history[@]:10}" "$(( (${cpu[temp_${i}]}-20)*100/(cpu[temp_high]-20) ))") + cpu_temp_history=( "${cpu_temp_history[@]:10}" "${tmp_temp}") else - cpu_temp_history+=("$(( (${cpu[temp_${i}]}-20)*100/(cpu[temp_high]-20) ))") + cpu_temp_history+=("${tmp_temp}") fi done fi From b710edb83d65bb5a515aa0abda4759964b25cade Mon Sep 17 00:00:00 2001 From: aristocratos Date: Mon, 11 May 2020 20:05:11 +0200 Subject: [PATCH 05/52] v0.8.29 Small fixes and changes --- CHANGELOG.md | 6 ++++++ bashtop | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ec45bcd..e487f83 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## v0.8.29 + +* Fixed: Cpu temperature colors not working when above high temp value +* Fixed: Unescaped "\" in process list and indent fixes +* Changed: Changes to net graph rescaling parameters + ## v0.8.28 * Fixed: Ctrl-C and Ctrl-Z not registering after change to "dd" diff --git a/bashtop b/bashtop index ba90df8..44292da 100755 --- a/bashtop +++ b/bashtop @@ -66,7 +66,7 @@ banner=( "██╔══██╗██╔══██║╚════██║██╔══██║ ██║ ██║ ██║██╔═══╝ " "██████╔╝██║ ██║███████║██║ ██║ ██║ ╚██████╔╝██║ " "╚═════╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ") -declare version="0.8.28" +declare version="0.8.29" declare banner_width=${#banner[0]} banner_colors=("#E62525" "#CD2121" "#B31D1D" "#9A1919" "#801414") From 734348c60704b240388de1327c7f7da99e5b596a Mon Sep 17 00:00:00 2001 From: aristocratos Date: Mon, 11 May 2020 20:24:07 +0200 Subject: [PATCH 06/52] Added: monokai_mod.theme --- themes/index.txt | 1 + themes/monokai_mod.theme | 89 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+) create mode 100644 themes/monokai_mod.theme diff --git a/themes/index.txt b/themes/index.txt index 8274eb8..cd0d5f3 100644 --- a/themes/index.txt +++ b/themes/index.txt @@ -3,6 +3,7 @@ flat-remix-light.theme flat-remix.theme greyscale.theme gruvbox_dark.theme +monokai_mod.theme monokai_nobg.theme monokai.theme solarized_dark.theme diff --git a/themes/monokai_mod.theme b/themes/monokai_mod.theme new file mode 100644 index 0000000..95a811c --- /dev/null +++ b/themes/monokai_mod.theme @@ -0,0 +1,89 @@ +#Bashtop monokai mod theme +#by aristocratos + +# Colors should be in 6 or 2 character hexadecimal or single spaced rgb decimal: "#RRGGBB", "#BW" or "0-255 0-255 0-255" +# example for white: "#FFFFFF", "#ff" or "255 255 255". + +# All graphs and meters can be gradients +# For single color graphs leave "mid" and "end" variable empty. +# Use "start" and "end" variables for two color gradient +# Use "start", "mid" and "end" for three color gradient + +# Main background, empty for terminal default, need to be empty if you want transparent background +theme[main_bg]="" + +# Main text color +theme[main_fg]="#F8F8F2" + +# Title color for boxes +theme[title]="#F8F8F2" + +# Higlight color for keyboard shortcuts +theme[hi_fg]="#F92672" + +# Background color of selected item in processes box +theme[selected_bg]="#7a1137" + +# Foreground color of selected item in processes box +theme[selected_fg]="#F8F8F2" + +# Color of inactive/disabled text +theme[inactive_fg]="#595647" + +# Misc colors for processes box including mini cpu graphs, details memory graph and details status text +theme[proc_misc]="#A6E22E" + +# Cpu box outline color +theme[cpu_box]="#75715E" + +# Memory/disks box outline color +theme[mem_box]="#75715E" + +# Net up/down box outline color +theme[net_box]="#75715E" + +# Processes box outline color +theme[proc_box]="#75715E" + +# Box divider line and small boxes line color +theme[div_line]="#595647" + +# Temperature graph colors +theme[temp_start]="#7976B7" +theme[temp_mid]="#D8B8B2" +theme[temp_end]="#F92672" + +# CPU graph colors +theme[cpu_start]="#A6E22E" +theme[cpu_mid]="#F8F8F2" #b05475" +theme[cpu_end]="#F92672" + +# Mem/Disk free meter +theme[free_start]="#75715E" +theme[free_mid]="a9c474" +theme[free_end]="#e2f5bc" + +# Mem/Disk cached meter +theme[cached_start]="#75715E" +theme[cached_mid]="#66D9EF" +theme[cached_end]="#aae7f2" + +# Mem/Disk available meter +theme[available_start]="#75715E" +theme[available_mid]="#E6DB74" +theme[available_end]="#f2ecb6" + +# Mem/Disk used meter +theme[used_start]="#75715E" +theme[used_mid]="#F92672" +theme[used_end]="#ff87b2" + +# Download graph colors +theme[download_start]="#2d2042" +theme[download_mid]="#7352a8" +theme[download_end]="#ccaefc" + +# Upload graph colors +theme[upload_start]="#570d33" +theme[upload_mid]="#cf277d" +theme[upload_end]="#fa91c7" From 19cef12f30b56911a89e54d8c3def03c05eda07c Mon Sep 17 00:00:00 2001 From: aristocratos Date: Wed, 13 May 2020 18:38:37 +0200 Subject: [PATCH 07/52] Fixed crash on network down --- bashtop | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/bashtop b/bashtop index 44292da..78d7c12 100755 --- a/bashtop +++ b/bashtop @@ -16,7 +16,7 @@ # shellcheck disable=SC1003 #info: single quote escape -# Copyright 2020 Aristocratos +# Copyright 2020 Aristocratos (jakob@qvantnet.com) # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -67,6 +67,9 @@ banner=( "██████╔╝██║ ██║███████║██║ ██║ ██║ ╚██████╔╝██║ " "╚═════╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ") declare version="0.8.29" + +#* Get latest version of BashTOP from https://github.com/aristocratos/bashtop + declare banner_width=${#banner[0]} banner_colors=("#E62525" "#CD2121" "#B31D1D" "#9A1919" "#801414") @@ -311,9 +314,8 @@ init_() { #? Collect needed information and set options before startig main loop mem[counter]=10 collect_mem init - #* Get default network device from "ip route" command and call init for net collection - get_value -v 'net[device]' -ss "$(ip route get 1.1.1.1)" -k "dev" -mk 1 - collect_net init + #* Get default network device from "ip route" command and call init for net collection if device is found + get_net_device #* Check if newer version of bashtop is available from https://github.com/aristocratos/bashtop if [[ -n $curled && $update_check == "true" ]]; then @@ -894,6 +896,11 @@ get_themes() { done } +get_net_device() { #? Check for internet connection and name of network device + if ! get_value -v 'net[device]' -ss "$(ip route get 1.1.1.1 2>/dev/null)" -k "dev" -mk 1; then net[no_device]=1 + else unset 'net[no_device]'; collect_net init; fi +} + cur_pos() { #? Get cursor postion, argument "line" prints current line, argument "col" prints current column, no argument prints both in format "line column" local line col IFS=';' read -sdR -p $'\E[6n' line col @@ -2342,6 +2349,8 @@ collect_net() { #? Collect information from "/proc/net/dev" local operations operation direction index unit_selector speed speed_B total local -a net_dev history_sorted history_last + if [[ -n ${net[no_device]} ]]; then return; fi + if [[ $1 == "init" ]]; then for direction in "download" "upload"; do net[${direction}_max]=0 @@ -2353,7 +2362,7 @@ collect_net() { #? Collect information from "/proc/net/dev" fi #* Get the line with relevant net device from /proc/net/dev into array net_dev, index 1 is download, index 9 is upload - get_value -map net_dev -sf "/proc/net/dev" -k "${net[device]}" -a + if ! get_value -map net_dev -sf "/proc/net/dev" -k "${net[device]}" -a; then net[no_device]=1; return; fi #* Timestamp the values to accurately calculate values in seconds get_ms net[new_timestamp] @@ -3051,6 +3060,8 @@ draw_processes() { #? Draw processes and values to screen draw_net() { #? Draw net information and graphs to screen local net_out + if [[ -n ${net[no_device]} ]]; then return; fi + #* Get variables from previous calculations local col=$((box[net_col]+1)) line=$((box[net_line]+1)) width=$((box[net_width]-2)) height=$((box[net_height]-2)) local n_width=${box[n_width]} n_height=${box[n_height]} n_col=${box[n_col]} n_line=${box[n_line]} main_fg="${theme[main_fg]}" @@ -3256,6 +3267,9 @@ help_() { #? Shows the help overlay "(T, t)" "(K, k)" "(I, i)" + " " + " " + " " ) descriptions=( "Shows main menu." @@ -3274,6 +3288,9 @@ help_() { #? Shows the help overlay "Terminate selected process with SIGTERM - 15." "Kill selected process with SIGKILL - 9." "Interrupt selected process with SIGINT - 2." + " " + "For bug reporting and project updates, visit:" + "\e[1mhttps://github.com/aristocratos/bashtop" ) if [[ -n $pause_screen ]]; then from_menu=1; fi @@ -4097,6 +4114,14 @@ main_loop() { #? main loop... echo -en "${draw_out}${proc_out}${clock_out}" unset draw_out + #* Periodically check for new network device if non was found at start or was removed + if ((net[device_check]>10)); then + net[device_check]=0 + get_net_device + elif [[ -n ${net[no_device]} ]]; then + ((++net[device_check])) + fi + #* Compare timestamps to get exact time needed to wait until next loop get_ms timestamp_end time_left=$((timestamp_start+update_ms-timestamp_end)) From 1418aea1bcf6c4181b377c34273632339ed14616 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Wed, 13 May 2020 20:51:58 +0200 Subject: [PATCH 08/52] v0.8.30 Fix for crash on missing net device --- CHANGELOG.md | 4 ++++ bashtop | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e487f83..f0fc58e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## v.0.8.30 + +* Fixed: Crash on missing net device + ## v0.8.29 * Fixed: Cpu temperature colors not working when above high temp value diff --git a/bashtop b/bashtop index 78d7c12..aabfd99 100755 --- a/bashtop +++ b/bashtop @@ -66,7 +66,7 @@ banner=( "██╔══██╗██╔══██║╚════██║██╔══██║ ██║ ██║ ██║██╔═══╝ " "██████╔╝██║ ██║███████║██║ ██║ ██║ ╚██████╔╝██║ " "╚═════╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ") -declare version="0.8.29" +declare version="0.8.30" #* Get latest version of BashTOP from https://github.com/aristocratos/bashtop From 68c5b3044e2afc8301386d8cba39ae9886f6c182 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Sat, 16 May 2020 16:30:36 +0200 Subject: [PATCH 09/52] Fixed 2-color gradient generation and theme file error checking --- bashtop | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/bashtop b/bashtop index aabfd99..6ae6d7e 100755 --- a/bashtop +++ b/bashtop @@ -392,6 +392,7 @@ color_init_() { #? Check for theme file and set colors local -A rgb local -a dec_test local -a convert_color=("main_bg" "temp_start" "temp_mid" "temp_end" "cpu_start" "cpu_mid" "cpu_end" "upload_start" "upload_mid" "upload_end" "download_start" "download_mid" "download_end" "used_start" "used_mid" "used_end" "available_start" "available_mid" "available_end" "cached_start" "cached_mid" "cached_end" "free_start" "free_mid" "free_end" "proc_misc" "main_fg_dec") + local -a set_color=("main_fg" "title" "hi_fg" "div_line" "inactive_fg" "selected_fg" "selected_bg" "cpu_box" "mem_box" "net_box" "proc_box") for theme_unset in ${!theme[@]}; do unset 'theme[${theme_unset}]' @@ -430,18 +431,15 @@ color_init_() { #? Check for theme file and set colors #* Set background color if set, otherwise use terminal default if [[ -n ${theme[main_bg]} ]]; then theme[main_bg_dec]="${theme[main_bg]}"; theme[main_bg]=";48;2;${theme[main_bg]// /;}"; fi - #* Set colors from theme file if found, otherwise use default values - theme[main_fg]="${theme[main_fg]:-$main_fg}" - theme[title]="${theme[title]:-$title}" - theme[hi_fg]="${theme[hi_fg]:-$hi_fg}" - theme[div_line]="${theme[div_line]:-$div_line}" - theme[inactive_fg]="${theme[inactive_fg]:-$inactive_fg}" - theme[selected_fg]="${theme[selected_fg]:-$selected_fg}" - theme[selected_bg]="${theme[selected_bg]:-$selected_bg}" - box[cpu_color]="${theme[cpu_box]:-$cpu_box}" - box[mem_color]="${theme[mem_box]:-$mem_box}" - box[net_color]="${theme[net_box]:-$net_box}" - box[processes_color]="${theme[proc_box]:-$proc_box}" + #* Set colors from theme file if found and valid hexadecimal or integers, otherwise use default values + for color_name in ${set_color[@]}; do + if ! is_hex ${theme[$color_name]} && ! is_int ${theme[$color_name]}; then theme[${color_name}]="${!color_name}"; fi + done + + box[cpu_color]="${theme[cpu_box]}" + box[mem_color]="${theme[mem_box]}" + box[net_color]="${theme[net_box]}" + box[processes_color]="${theme[proc_box]}" #* Create color arrays from one, two or three color gradient, 100 values in each for array_name in "temp" "cpu" "upload" "download" "used" "available" "cached" "free"; do @@ -452,9 +450,9 @@ color_init_() { #? Check for theme file and set colors rgb[red]=${rgb_start[0]}; rgb[green]=${rgb_start[1]}; rgb[blue]=${rgb_start[2]} if [[ -z ${rgb_mid[*]} ]] && ((rgb_end[0]+rgb_end[1]+rgb_end[2]>rgb_start[0]+rgb_start[1]+rgb_start[2])); then - rgb_mid=( $((rgb_end[0]/2)) $((rgb_end[1]/2)) $((rgb_end[2]/2)) ) + rgb_mid=( $(( rgb_start[0]+( (rgb_end[0]-rgb_start[0])/2) )) $((rgb_start[1]+( (rgb_end[1]-rgb_start[1])/2) )) $((rgb_start[2]+( (rgb_end[2]-rgb_start[2])/2) )) ) elif [[ -z ${rgb_mid[*]} ]]; then - rgb_mid=( $((rgb_start[0]/2)) $((rgb_start[1]/2)) $((rgb_start[2]/2)) ) + rgb_mid=( $(( rgb_end[0]+( (rgb_start[0]-rgb_end[0])/2) )) $(( rgb_end[1]+( (rgb_start[1]-rgb_end[1])/2) )) $(( rgb_end[2]+( (rgb_start[2]-rgb_end[2])/2) )) ) fi for((i=0;i<=100;i++,y=0)); do From ff9012ab36c61ea96451a0974e5f611c55c36bb4 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Sat, 16 May 2020 17:53:32 +0200 Subject: [PATCH 10/52] v0.8.31 Fixes for theme parsing --- CHANGELOG.md | 7 ++++++- bashtop | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f0fc58e..818b901 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ # Changelog -## v.0.8.30 +## v0.8.31 + +* Fixed: Theme 2-color gradient generation +* Fixed: Theme file error checking + +## v0.8.30 * Fixed: Crash on missing net device diff --git a/bashtop b/bashtop index 6ae6d7e..2277cff 100755 --- a/bashtop +++ b/bashtop @@ -66,7 +66,7 @@ banner=( "██╔══██╗██╔══██║╚════██║██╔══██║ ██║ ██║ ██║██╔═══╝ " "██████╔╝██║ ██║███████║██║ ██║ ██║ ╚██████╔╝██║ " "╚═════╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ") -declare version="0.8.30" +declare version="0.8.31" #* Get latest version of BashTOP from https://github.com/aristocratos/bashtop From 98d2f84894085b9d7cb289f43ecbce76a3edb971 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Thu, 21 May 2020 11:35:39 +0200 Subject: [PATCH 11/52] v0.8.32 Fix for corrupted default theme --- CHANGELOG.md | 4 ++++ bashtop | 6 +++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 818b901..02c412b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## v0.8.32 + +* Fixed: Error in theme error checking corrupting default theme + ## v0.8.31 * Fixed: Theme 2-color gradient generation diff --git a/bashtop b/bashtop index 2277cff..f3ddd73 100755 --- a/bashtop +++ b/bashtop @@ -66,7 +66,7 @@ banner=( "██╔══██╗██╔══██║╚════██║██╔══██║ ██║ ██║ ██║██╔═══╝ " "██████╔╝██║ ██║███████║██║ ██║ ██║ ╚██████╔╝██║ " "╚═════╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ") -declare version="0.8.31" +declare version="0.8.32" #* Get latest version of BashTOP from https://github.com/aristocratos/bashtop @@ -432,8 +432,8 @@ color_init_() { #? Check for theme file and set colors if [[ -n ${theme[main_bg]} ]]; then theme[main_bg_dec]="${theme[main_bg]}"; theme[main_bg]=";48;2;${theme[main_bg]// /;}"; fi #* Set colors from theme file if found and valid hexadecimal or integers, otherwise use default values - for color_name in ${set_color[@]}; do - if ! is_hex ${theme[$color_name]} && ! is_int ${theme[$color_name]}; then theme[${color_name}]="${!color_name}"; fi + for color_name in "${set_color[@]}"; do + if [[ -z ${theme[$color_name]} ]] || ! is_hex "${theme[$color_name]}" && ! is_int "${theme[$color_name]}"; then theme[${color_name}]="${!color_name}"; fi done box[cpu_color]="${theme[cpu_box]}" From ab7aac45d57811ade3d3c257e42927cb211c1eba Mon Sep 17 00:00:00 2001 From: aristocratos Date: Fri, 22 May 2020 19:13:02 +0200 Subject: [PATCH 12/52] Added: Support for OSX with python psutil module --- bashtop | 665 +++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 565 insertions(+), 100 deletions(-) diff --git a/bashtop b/bashtop index f3ddd73..ccbace0 100755 --- a/bashtop +++ b/bashtop @@ -40,7 +40,7 @@ case "$(uname -s)" in MINGW*) system=MinGw;; *) system="Other" esac -if [[ "$system" != "Linux" ]]; then +if [[ "$system" != "Linux" && "$system" != "MacOS" ]]; then echo "This version of bashtop does not support $system platform." exit 1 fi @@ -73,6 +73,15 @@ declare version="0.8.32" declare banner_width=${#banner[0]} banner_colors=("#E62525" "#CD2121" "#B31D1D" "#9A1919" "#801414") +if [[ $system == "MacOS" ]]; then tool_prefix="g"; fi + +for tool in "dd" "df" "stty" "sed" "uptime"; do + declare -n set_tool="${tool}" + set_tool="${tool_prefix}${tool}" +done + +read tty_height tty_width < <(${stty} size) + #? Start default variables------------------------------------------------------------------------------> #? These values are used to create "$HOME/.config/bashtop/bashtop.cfg" #? Any changes made here will be ignored if config file exists @@ -121,6 +130,9 @@ update_check="true" #* Enable graphs with double the horizontal resolution, increases cpu usage hires_graphs="false" +#* Enable the use of psutil python module for data collection, default when not on linux +use_psutil="true" + aaz_config() { : ; } #! Do not remove this line! #? End default variables--------------------------------------------------------------------------------> @@ -160,11 +172,12 @@ declare -a options_array=("color_theme" "update_ms" "proc_sorting" "check_temp" "proc_reversed" "proc_gradient" "disks_filter" "hires_graphs" "net_totals_reset" "update_check" "error_logging") declare -a save_array=(${options_array[*]/net_totals_reset/}) declare -a sorting=( "pid" "program" "arguments" "threads" "user" "memory" "cpu lazy" "cpu responsive" "tree" ) -declare -a pid_history detail_graph detail_history detail_mem_history +declare -a detail_graph detail_history detail_mem_history disks_io +declare -A pid_history declare time_left timestamp_start timestamp_end timestamp_input_start timestamp_input_end time_string mem_out proc_misc prev_screen pause_screen filter input_to_filter declare no_epoch proc_det proc_misc2 sleeping=0 detail_mem_graph proc_det2 proc_out curled git_version has_iostat -declare esc_character tab backspace sleepy late_update skip_process_draw winches quitting theme_int notifier saved_stty -declare -a disks_free disks_total disks_name disks_free_percent disks_io saved_key themes +declare esc_character tab backspace sleepy late_update skip_process_draw winches quitting theme_int notifier saved_stty nic_int net_misc skip_net_draw +declare -a disks_free disks_total disks_name disks_free_percent saved_key themes nic_list old_procs printf -v esc_character "\u1b" printf -v tab "\u09" printf -v backspace "\u7F" #? Backspace set to DELETE @@ -174,8 +187,6 @@ printf -v enter_key "\uD" printf -v ctrl_c "\u03" printf -v ctrl_z "\u1A" -read tty_height tty_width < <(stty size) - #* Symbols for graphs declare -a graph_symbol graph_symbol=(" " "⡀" "⣀" "⣄" "⣤" "⣦" "⣴" "⣶" "⣷" "⣾" "⣿") @@ -263,11 +274,11 @@ fi init_() { #? Collect needed information and set options before startig main loop local i #* Set terminal options, save and clear screen - saved_stty="$(stty -g)" + saved_stty="$(${stty} -g)" tput smcup - stty -echo + tput clear + ${stty} -echo tput civis - keys_stty="$(stty -g)" #* Check if "sensors" command is available, if not, disable temperature collection if [[ $check_temp != false ]] && command -v sensors >/dev/null 2>&1; then check_temp="true"; else check_temp="false"; fi @@ -279,7 +290,7 @@ init_() { #? Collect needed information and set options before startig main loop if [[ -n $curled ]] && command -v notify-send >/dev/null 2>&1; then notifier=1; else unset notifier; fi #* Check if "iostat" command is available, if not, disable disk io stat collection - if command -v iostat >/dev/null 2>&1; then has_iostat=1; else unset has_iostat; fi + if [[ $use_psutil == false ]] && command -v iostat >/dev/null 2>&1; then has_iostat=1; else unset has_iostat; fi #* Get number of cores and cpu threads get_cpu_info @@ -289,7 +300,7 @@ init_() { #? Collect needed information and set options before startig main loop #* Get processor BCLK local param_var - if [[ -e /usr/include/asm-generic/param.h ]]; then + if [[ $use_psutil == false ]] && [[ -e /usr/include/asm-generic/param.h ]]; then param_var="$(> "$config_file" @@ -763,20 +781,36 @@ floating_humanizer() { #? Convert integer to floating point and scale up in ste } get_cpu_info() { - local lscpu_var param_var - lscpu_var="$(lscpu)" - if [[ -z ${cpu[threads]} || -z ${cpu[cores]} ]]; then - if ! get_value -v 'cpu[threads]' -sv "lscpu_var" -k "CPU(s):" -i || [[ ${cpu[threads]} == "0" ]]; then - cpu[threads]="$(nproc 2>/dev/null ||true)" - if [[ -z ${cpu[threads]} ]]; then cpu[threads]="1"; fi - cpu[cores]=${cpu[threads]} - else - get_value -v 'cpu[cores]' -sv "lscpu_var" -k "Core(s)" -i + local lscpu_var + if [[ $use_psutil == true ]]; then + if [[ -z ${cpu[threads]} || -z ${cpu[cores]} ]]; then + read cpu[threads] cpu[cores] < <(python3 -c "import psutil; print(psutil.cpu_count(logical=True), psutil.cpu_count(logical=False))") + fi + + if [[ $system == "MacOS" ]]; then + lscpu_var="Model name: $(sysctl -n machdep.cpu.brand_string)" + elif command -v lscpu >/dev/null 2>&1; then + lscpu_var="$(lscpu)" + fi + + else + if command -v lscpu >/dev/null 2>&1; then lscpu_var="$(lscpu)"; fi + if [[ -z ${cpu[threads]} || -z ${cpu[cores]} ]]; then + if ! get_value -v 'cpu[threads]' -sv "lscpu_var" -k "CPU(s):" -i || [[ ${cpu[threads]} == "0" ]]; then + cpu[threads]="$(nproc 2>/dev/null ||true)" + if [[ -z ${cpu[threads]} ]]; then cpu[threads]="1"; fi + cpu[cores]=${cpu[threads]} + else + get_value -v 'cpu[cores]' -sv "lscpu_var" -k "Core(s)" -i + fi fi fi + if [[ -z $custom_cpu_name ]]; then if ! get_value -v 'cpu[model]' -sv "lscpu_var" -k "Model name:" -a -b -k "CPU" -mk -1; then - get_value -v 'cpu[model]' -sv "lscpu_var" -k "Model name:" -r " " + if ! get_value -v 'cpu[model]' -sv "lscpu_var" -k "Model name:" -r " "; then + cpu[model]="cpu" + fi fi else cpu[model]="${custom_cpu_name}" @@ -894,9 +928,48 @@ get_themes() { done } -get_net_device() { #? Check for internet connection and name of network device - if ! get_value -v 'net[device]' -ss "$(ip route get 1.1.1.1 2>/dev/null)" -k "dev" -mk 1; then net[no_device]=1 - else unset 'net[no_device]'; collect_net init; fi +get_net_device() { #? Check for internet connection, name of default network device and create list of all devices + if [[ $use_psutil == true ]]; then get_net_device_psutil; return; fi + local -a netdev + local ndline + if ! get_value -v 'net[device]' -ss "$(ip route get 1.1.1.1 2>/dev/null)" -k "dev" -mk 1; then + net[no_device]=1 + else + unset 'net[no_device]' 'nic_list[@]' nic_int + readarray -t netdev /dev/null <tty_width*2)); then @@ -1843,7 +1949,7 @@ collect_cpu() { #? Collects cpu stats from /proc/stat and compares with previous done #* Get current cpu frequency from "/proc/cpuinfo" and convert to appropriate unit - if [[ -z ${cpu[no_cpu_info]} ]] && ! get_value -v 'cpu[freq]' -sf "/proc/cpuinfo" -k "cpu MHz" -i; then + if [[ $use_psutil == false && -z ${cpu[no_cpu_info]} ]] && ! get_value -v 'cpu[freq]' -sf "/proc/cpuinfo" -k "cpu MHz" -i; then cpu[no_cpu_info]=1 fi @@ -1858,12 +1964,14 @@ collect_cpu() { #? Collects cpu stats from /proc/stat and compares with previous else cpu[freq_string]=""; fi #* Get load average and uptime from uptime command - local uptime_var - read -r uptime_var < <(uptime 2>/dev/null || true) - cpu[load_avg]="${uptime_var#*average: }" - cpu[load_avg]="${cpu[load_avg]//,/}" - cpu[uptime]="${uptime_var#*up }" - cpu[uptime]="${cpu[uptime]%%, *}" + if [[ $use_psutil == false ]]; then + local uptime_var + read -r uptime_var < <(${uptime} 2>/dev/null || true) + cpu[load_avg]="${uptime_var#*average: }" + cpu[load_avg]="${cpu[load_avg]//,/}" + cpu[uptime]="${uptime_var#*up }" + cpu[uptime]="${cpu[uptime]%%, *}" + fi #* Collect cpu temps if enabled if [[ $check_temp == true ]]; then collect_cpu_temps; fi @@ -1971,16 +2079,37 @@ collect_mem() { #? Collect memory information from "/proc/meminfo" local i tmp value array mem_info height=$((box[mem_height]-2)) skip filter_value local -a mem_array swap_array available=("mem") - #* Get memory and swap information from "/proc/meminfo" and calculate percentages - read -rd '' mem_info >10 +except: + cmem = 0 +print(mem.total>>10, mem.free>>10, mem.available>>10, cmem, swap.total>>10, swap.free>>10) +EOF + ) + if [[ -n $swap_on && -n ${swap[total]} ]] && ((swap[total]>0)); then + swap[free_percent]=$((swap[free]*100/swap[total])) + swap[used]=$((swap[total]-swap[free])) + swap[used_percent]=$((swap[used]*100/swap[total])) + available+=("swap") + else + unset swap_on + fi + else + read -rd '' mem_info 0)); then + if [[ -n $swap_on && $use_psutil == false ]] && get_value -v swap[total] -sv "mem_info" -k "SwapTotal:" -i && ((swap[total]>0)); then get_value -v 'swap[free]' -sv "mem_info" -k "SwapFree:" -i swap[free_percent]=$((swap[free]*100/swap[total])) @@ -1996,7 +2125,7 @@ collect_mem() { #? Collect memory information from "/proc/meminfo" swap[used_percent]=$((swap[used]*100/swap[total])) available+=("swap") - else + elif [[ $use_psutil == false ]]; then unset swap_on fi @@ -2013,9 +2142,10 @@ collect_mem() { #? Collect memory information from "/proc/meminfo" local df_array df_line line_array dev_path dev_name iostat_var disk_read disk_write disk_io_string local -a device_array iostat_array unset 'disks_free[@]' 'disks_used[@]' 'disks_used_percent[@]' 'disks_total[@]' 'disks_name[@]' 'disks_free_percent[@]' 'disks_io[@]' - readarray -t df_array < <(df -x squashfs -x tmpfs -x devtmpfs -x overlay) + readarray -t df_array < <(${df} -x squashfs -x tmpfs -x devtmpfs -x overlay 2>/dev/null || true) for df_line in "${df_array[@]:1}"; do line_array=(${df_line}) + if ! is_int "${line_array[2]}"; then continue; fi if [[ ${line_array[5]} == "/" ]]; then disks_name+=("root") else disks_name+=("${line_array[5]##*/}"); fi @@ -2035,15 +2165,22 @@ collect_mem() { #? Collect memory information from "/proc/meminfo" disks_free+=("$(floating_humanizer -s 1 -B ${line_array[3]})") disks_free_percent+=("$((100-${line_array[4]%'%'}))") - #* Get read/write stats for disk if "iostat" is available - if [[ -n $has_iostat ]]; then + #* Get read/write stats for disk if iostat or psutil is available + if [[ -n $has_iostat || $use_psutil == true ]]; then + unset iostat_var disk_io_string dev_name="${line_array[0]##*/}" dev_path="${line_array[0]%${dev_name}}" if [[ ${dev_name::2} == "md" ]]; then dev_name="${dev_name::3}"; fi unset iostat_var disk_io_string 'iostat_array[@]' - read -r iostat_var < <(iostat -dkz "${dev_path}${dev_name}" | tail -n +4) + if [[ $use_psutil == true && $system == "MacOS" && ${disks_name[-1]} == "root" ]]; then + read -r iostat_var < <(python3 -c "import psutil; disk = psutil.disk_io_counters(perdisk=False); print(disk.read_bytes>>10, disk.write_bytes>>10)") + elif [[ $use_psutil == true && $system != "MacOS" ]]; then + read -r iostat_var < <(python3 -c "import os, psutil; disk = psutil.disk_io_counters(perdisk=True)[os.path.realpath('${dev_path}${dev_name}').split('/')[-1]]; print(disk.read_bytes>>10, disk.write_bytes>>10)") + elif [[ $use_psutil == false ]]; then + read -r iostat_var < <(iostat -dkz "${dev_path}${dev_name}" | tail -n +4) + fi iostat_array=(${iostat_var}) - if [[ -n ${iostat_array[-2]} ]]; then + if [[ -n ${iostat_var} ]]; then disk_read=$((iostat_array[-2]-${disks[${dev_name}_read]:-${iostat_array[-2]}})) disk_write=$((iostat_array[-1]-${disks[${dev_name}_write]:-${iostat_array[-1]}})) @@ -2068,13 +2205,15 @@ collect_mem() { #? Collect memory information from "/proc/meminfo" if ((${#disks_name[@]}>=height/2)); then break; fi done + } collect_processes() { #? Collect process information and calculate accurate cpu usage + if [[ $use_psutil == true ]]; then collect_processes_psutil $1; return; fi local argument="$1" if [[ -n $skip_process_draw && $argument != "now" ]]; then return; fi local width=${box[processes_width]} height=${box[processes_height]} format_args format_cmd readline sort symbol="▼" cpu_title options pid_string tmp selected - local tree tree_compare1 tree_compare2 tree_compare3 no_core_divide + local tree tree_compare1 tree_compare2 tree_compare3 no_core_divide pids local -a grep_array saved_proc_array if [[ $argument == "now" ]]; then skip_process_draw=1; fi @@ -2165,9 +2304,7 @@ collect_processes() { #? Collect process information and calculate accurate cpu fi fi - if [[ ! ${pid_history[*]} =~ ${pid} ]]; then - pid_history+=("${pid}") - fi + pid_history[${pid}]="1" if [[ -n $filter || $proc_sorting == "cpu responsive" ]] && [[ ${proc_array[count]:${proc[pid_len]}:1} != " " ]]; then unset pid_string @@ -2329,16 +2466,281 @@ collect_processes() { #? Collect process information and calculate accurate cpu ((++proc[general_counter])) if ((proc[general_counter]>100)); then proc[general_counter]=0 - for ((i=0;i<${#pid_history[@]};i++)); do - if [[ -n ${pid_history[$i]} && ! -e /proc/${pid_history[$i]} ]]; then - unset "pid_${pid_history[$i]}_graph" "pid_${pid_history[$i]}_graph_even" "pid_${pid_history[$i]}_graph_odd" "pid_${pid_history[$i]}_graph_last_type" "pid_${pid_history[$i]}_graph_last_val" - unset "pid_${pid_history[$i]}_count" - unset "proc[new_${pid_history[$i]}_ticks]" - unset "proc[old_${pid_history[$i]}_ticks]" - unset "pid_history[${i}]" + for pids in ${!pid_history[@]}; do + if [[ ! -e /proc/${pids} ]]; then + unset "pid_${pids}_graph" "pid_${pids}_graph_even" "pid_${pids}_graph_odd" "pid_${pids}_graph_last_type" "pid_${pids}_graph_last_val" + unset "pid_${pids}_count" + unset "proc[new_${pids}_ticks]" + unset "proc[old_${pids}_ticks]" + unset "pid_history[${pids}]" + fi + done + fi + +} + +collect_processes_psutil() { + local argument=$1 + if [[ -n $skip_process_draw && $argument != "now" ]]; then return; fi + if [[ $argument == "now" ]]; then skip_process_draw=1; fi + local prog_len arg_len symbol="▼" sorting selected imports time_elapsed no_core_divide width=${box[processes_width]} height=${box[processes_height]} + local cmdargs titleargs titletr hide_self pid pcpu_usage pids p_count cpu_int pids + + #* Timestamp the values in milliseconds to accurately calculate cpu usage + get_ms proc[new_timestamp] + + if [[ $proc_per_core == true ]]; then no_core_divide="1"; fi + + time_elapsed=$((proc[new_timestamp]-proc[old_timestamp])) + + case ${proc_sorting} in + "pid") + selected="Pid:" + sorting="p.info['pid'], reverse=True" + ;; + "program") + selected="Program:" + sorting="p.info['name'], reverse=False" + ;; + "arguments") + selected="Arguments:" + sorting="' '.join(str(p.info['cmdline'])) or p.info['name'], reverse=False" + ;; + "threads") + selected="Threads:" + sorting="str(p.info['num_threads']), reverse=True" + ;; + "user") + selected="User:" + sorting="p.info['username'], reverse=False" + ;; + "memory") + selected="Mem%" + sorting="str(p.info['memory_percent']), reverse=True" + ;; + "cpu lazy"|"tree") + selected="Cpu%" + sorting="(sum(p.info['cpu_times'][:2]) * 1000 / (time.time() - p.info['create_time'])), reverse=True" + imports=1 + ;; + "cpu responsive") + selected="Cpu%" + sorting="float( (sum(p.info['cpu_times'][:2]) - procs.get(p.info['pid'], 0)) * 100000 / (${time_elapsed} * ${no_core_divide:-${cpu[threads]}}) ), reverse=True" + ;; + esac + + if [[ -n ${proc[reverse]} ]]; then + symbol="▲" + if [[ ${sorting:(-4)} == "True" ]]; then sorting="${sorting::-4}False" + elif [[ ${sorting:(-5)} == "False" ]]; then sorting="${sorting::-5}True" + fi + fi + + if ((proc[detailed]==0)) && [[ -n ${proc[detailed_name]} ]]; then + unset 'proc[detailed_name]' 'proc[detailed_killed]' 'proc[detailed_cpu_int]' 'proc[detailed_cmd]' + unset 'proc[detailed_mem]' 'proc[detailed_mem_int]' 'proc[detailed_user]' 'proc[detailed_threads]' + unset 'detail_graph[@]' 'detail_mem_graph' 'detail_history[@]' 'detail_mem_history[@]' + unset 'proc[detailed_runtime]' 'proc[detailed_mem_string]' 'proc[detailed_parent_pid]' 'proc[detailed_parent_name]' + fi + + unset 'proc[detailed_cpu]' + + if [[ -z ${old_procs[*]} ]]; then old_procs=("{ }"); fi + + if ((width>60)); then + arg_len=$((width-55)) + prog_len=15 + cmdargs="f\"{' '.join(p.info['cmdline']) or '[' + p.info['name'] + ']':<${arg_len}.$((arg_len-1))}\"," + titleargs="{'Arguments:':<$((arg_len-4))}" + titletr="{'Threads:'}" + else + prog_len=$((width-40)) + titletr=" {'Tr:'}" + fi + + unset 'proc_array[@]' + readarray -t proc_array < <(python3 - </dev/null +import os, psutil +${imports:+"import time"} + +selfpid = os.getpid() +procs = ${old_procs[@]} +err = [ 0.0, 0.0 ] +search = '${filter}' + +print(f"{'Pid:':>7} {'Program:':<${prog_len}}${titleargs}${titletr} {'User:':<9}Mem%{'Cpu%':>11}") + +for p in sorted(psutil.process_iter(['pid', 'name', 'cmdline', 'num_threads', 'username', 'memory_percent', 'cpu_times', 'create_time'], err), key=lambda p: ${sorting}): + if p.info['pid'] == selfpid: + continue + if p.info['cpu_times'] == err: + p.info['memory_percent'] = 0.0 + p.info['num_threads'] = 0 + p.info['cmdline'] = '' + if search: + found = False + for value in [ p.info['name'], ' '.join(p.info['cmdline']), str(p.info['pid']), p.info['username'] ]: + if search in value: + found = True + break + if not found: + continue + + cpu = float((sum(p.info['cpu_times'][:2]) - procs.get(p.info['pid'], sum(p.info['cpu_times'][:2]))) * 100000 / (${time_elapsed} * ${no_core_divide:-${cpu[threads]}})) + mem = p.info['memory_percent'] + print(f"{p.info['pid']:>7} ", + f"{p.info['name']:<${prog_len}.$((prog_len-1))}", + ${cmdargs} + f"{p.info['num_threads']:>4} " if p.info['num_threads'] < 1000 else '999> ', + f"{p.info['username']:<9.9}", + f"{mem:>4.1f}" if mem < 100 else f"{mem:>4.0f} ", + f"{cpu:>11.1f} " if cpu < 100 else f"{cpu:>11.0f} ", + f"{sum(p.info['cpu_times'][:2])}", + sep='') +EOF +) + + proc_array[0]="${proc_array[0]/ ${selected}/${symbol}${selected}}" + proc[pages]=$(( (${#proc_array[@]}-1)/(height-3)+1 )) + if ((proc[page]>proc[pages])); then proc[page]=${proc[pages]}; fi + + unset 'old_procs[@]' + old_procs=("{") + + for((i=1;i<${#proc_array[@]};i++)); do + if [[ -z ${proc_array[i]} ]]; then continue; fi + + out_arr=(${proc_array[i]}) + old_procs+=(" ${out_arr[0]}: ${out_arr[-1]},") + proc_array[i]="${proc_array[i]% ${out_arr[-1]}}" + + pid="${out_arr[0]}" + pcpu_usage="${out_arr[-2]}" + + printf -v cpu_int "%.0f" "${pcpu_usage}" + + pid_history[${pid}]="1" + + #* Create small graphs for all visible processes using more than 1% cpu time + pid_graph="pid_${pid}_graph" + local -n pid_count="pid_${pid}_count" + + if [[ ${cpu_int} -gt 0 ]]; then pid_count=5; fi + + if [[ -z ${!pid_graph} && ${cpu_int} -gt 0 ]]; then + tmp_value_array=("$((cpu_int+4))") + create_mini_graph -o "pid_${pid}_graph" -nc -w 5 "tmp_value_array" + elif [[ ${pid_count} -gt 0 ]]; then + if [[ ${cpu_int} -gt 9 ]]; then + create_mini_graph -nc -add-value "pid_${pid}_graph" "$((cpu_int+15))" + else + create_mini_graph -nc -add-value "pid_${pid}_graph" "$((cpu_int+9))" + fi + pid_count=$((${pid_count}-1)) + elif [[ ${pid_count} == "0" ]]; then + unset "pid_${pid}_graph" "pid_${pid}_graph_even" "pid_${pid}_graph_odd" "pid_${pid}_graph_last_type" "pid_${pid}_graph_last_val" + unset "pid_${pid}_count" + fi + + #* Get info for detailed box if enabled + if [[ ${pid} == "${proc[detailed_pid]}" ]]; then + if [[ -z ${proc[detailed_name]} ]]; then + local get_mem mem_string cmdline="" + local -a det_array + readarray -t det_array < <(python3 - <8)); then proc[detailed_runtime]="${det_array[1]/ days, /-}" + else proc[detailed_runtime]="${det_array[1]}"; fi + + proc[detailed_mem_count]=0 + proc[detailed_mem]="${out_arr[-3]}" + proc[detailed_mem_int]="${proc[detailed_mem]/./}" + if [[ ${proc[detailed_mem_int]::1} == "0" ]]; then proc[detailed_mem_int]="${proc[detailed_mem_int]:1}0"; fi + #* Scale up low mem values to see any changes on mini graph + if ((proc[detailed_mem_int]>900)); then proc[detailed_mem_int]=$((proc[detailed_mem_int]/10)) + elif ((proc[detailed_mem_int]>600)); then proc[detailed_mem_int]=$((proc[detailed_mem_int]/8)) + elif ((proc[detailed_mem_int]>300)); then proc[detailed_mem_int]=$((proc[detailed_mem_int]/5)) + elif ((proc[detailed_mem_int]>100)); then proc[detailed_mem_int]=$((proc[detailed_mem_int]/2)) + elif ((proc[detailed_mem_int]<50)); then proc[detailed_mem_int]=$((proc[detailed_mem_int]*2)); fi + + #* Copy process cpu usage to history array and trim earlier entries + if ((${#detail_history[@]}>box[details_width]*2)); then + detail_history=( "${detail_history[@]:${box[details_width]}}" "$((cpu_int+4))") + else + detail_history+=("$((cpu_int+4))") + fi + + #* Copy process mem usage to history array and trim earlier entries + if ((${#detail_mem_history[@]}>box[details_width])); then + detail_mem_history=( "${detail_mem_history[@]:$((box[details_width]/2))}" "${proc[detailed_mem_int]}") + else + detail_mem_history+=("${proc[detailed_mem_int]}") + fi + fi + + if ((i==height-2)); then + if [[ ${proc[selected]} -gt 0 || ${proc[page]} -gt 1 || -z ${proc[detailed_cpu]} ]]; then : + else break; fi + fi + + done + old_procs[-1]="${old_procs[-1]%,} }" + + proc[old_timestamp]=${proc[new_timestamp]} + + if ((proc[detailed]==1)) && [[ -z ${proc[detailed_cpu]} && -z ${proc[detailed_killed]} ]]; then proc[detailed_killed]=1; proc[detailed_change]=1 + elif [[ -n ${proc[detailed_cpu]} ]]; then unset 'proc[detailed_killed]'; fi + + + + #* Clear up memory by removing variables and graphs of no longer running processes + ((++proc[general_counter])) + if ((proc[general_counter]>100)); then + proc[general_counter]=0 + for pids in ${!pid_history[@]}; do + if [[ ! -e /proc/${pids} ]]; then + unset "pid_${pids}_graph" "pid_${pids}_graph_even" "pid_${pids}_graph_odd" "pid_${pids}_graph_last_type" "pid_${pids}_graph_last_val" + unset "pid_${pids}_count" + unset "pid_history[${pids}]" fi done - pid_history=(${pid_history[@]}) fi } @@ -2357,10 +2759,16 @@ collect_net() { #? Collect information from "/proc/net/dev" net[${direction}_max_current]=0 net[${direction}_graph_max]=$((50<<10)) done + unset 'download_graph[@]' 'upload_graph[@]' 'net_history_download[@]' 'net_history_upload[@]' fi - #* Get the line with relevant net device from /proc/net/dev into array net_dev, index 1 is download, index 9 is upload - if ! get_value -map net_dev -sf "/proc/net/dev" -k "${net[device]}" -a; then net[no_device]=1; return; fi + #* Get the line with relevant net device from /proc/net/dev or psutil into array net_dev, index 1 is download, index 9 is upload + if [[ $use_psutil == true ]]; then + read -a net_dev < <(python3 -c "import psutil; net = psutil.net_io_counters(pernic=True)['${net[device]}']; print(0,net.bytes_recv,0,0,0,0,0,0,0,net.bytes_sent)" 2>/dev/null) + if [[ -z ${net_dev[*]} ]]; then net[no_device]=1; return; fi + else + if ! get_value -map net_dev -sf "/proc/net/dev" -k "${net[device]}" -a; then net[no_device]=1; return; fi + fi #* Timestamp the values to accurately calculate values in seconds get_ms net[new_timestamp] @@ -2372,6 +2780,7 @@ collect_net() { #? Collect information from "/proc/net/dev" if [[ -n ${net[old_${direction}]} ]]; then #* Get total, convert to floating point and format string to best fitting unit in Bytes + if ((net[nic_change]==1 & net[reset]==1)); then unset "net[total_offset_${direction}]"; net[reset]=0; fi if ((net[reset]==1)) && [[ -z ${net[total_offset_${direction}]} || ${net[total_offset_${direction}]} -gt ${net[new_${direction}]} ]]; then net[total_offset_${direction}]=${net[new_${direction}]} elif ((net[reset]==0)) && [[ -n ${net[total_offset_${direction}]} ]]; then unset "net[total_offset_${direction}]"; fi @@ -2691,7 +3100,8 @@ draw_mem() { #? Draw mem, swap and disk statistics local i swap_used_meter swap_free_meter mem_available_meter mem_free_meter mem_used_meter mem_cached_meter normal_color="${theme[main_fg]}" value_text local meter_mod_w meter_mod_pos value type m_title meter_options - local -a types=("mem") + local -a types=("mem") values=("used" "available" "free") + if [[ $system != "MacOS" ]]; then values+=("cached"); fi unset mem_out if [[ -n $swap_on ]]; then types+=("swap"); fi @@ -2714,7 +3124,7 @@ draw_mem() { #? Draw mem, swap and disk statistics #* Print name of type and total amount in humanized base 2 bytes print -v mem_out -m $y_pos $m_col -rs -fg ${theme[title]} -b -jl 9 -t "${m_title^}:" -m $((y_pos++)) $((mem_line-10)) -jr 9 -trans -t " ${type_name[total_string]::$((m_width-11))}" - for value in "used" "available" "cached" "free"; do + for value in "${values[@]}"; do if [[ $type == "swap" && $value == "available" ]]; then value="free" elif [[ $type == "swap" && $value == "cached" ]]; then break 2; fi @@ -2760,7 +3170,7 @@ draw_mem() { #? Draw mem, swap and disk statistics #* Print folder disk is mounted on, total size in humanized base 2 bytes and io stats if enabled print -v mem_out -m $((y_pos++)) $m_col -rs -fg ${theme[title]} -b -t "${disks_name[disk_num]::10}" name_len=${#disks_name[disk_num]}; if ((name_len>10)); then name_len=10; fi - if [[ -n $has_iostat && ${disks_io[disk_num]} != "0" ]] && ((m_width-11-name_len>6)); then + if [[ -n ${disks_io[disk_num]} && ${disks_io[disk_num]} != "0" ]] && ((m_width-11-name_len>6)); then print -v mem_out -jc $((m_width-name_len-10)) -rs -fg ${theme[main_fg]} -t "${disks_io[disk_num]::$((m_width-10-name_len))}" just_val=8 else @@ -3057,8 +3467,10 @@ draw_processes() { #? Draw processes and values to screen } draw_net() { #? Draw net information and graphs to screen - local net_out + local net_out argument=$1 if [[ -n ${net[no_device]} ]]; then return; fi + if [[ -n $skip_net_draw && $argument != "now" ]]; then return; fi + if [[ $argument == "now" ]]; then skip_net_draw=1; fi #* Get variables from previous calculations local col=$((box[net_col]+1)) line=$((box[net_line]+1)) width=$((box[net_width]-2)) height=$((box[net_height]-2)) @@ -3071,27 +3483,32 @@ draw_net() { #? Draw net information and graphs to screen if ((graph_a_size*20)); then + if ((net[download_redraw]==1 | net[nic_change]==1 | resized>0)); then create_graph -o download_graph -d $line $col ${net[graph_a_size]} $((width-n_width-2)) -c color_download_graph -n -max "${net[download_graph_max]}" net_history_download else create_graph -max "${net[download_graph_max]}" -add-last download_graph net_history_download fi - if ((net[upload_redraw]==1 | resized>0)); then + if ((net[upload_redraw]==1 | net[nic_change]==1 | resized>0)); then create_graph -o upload_graph -d $((line+net[graph_a_size])) $col ${net[graph_b_size]} $((width-n_width-2)) -c color_upload_graph -i -n -max "${net[upload_graph_max]}" net_history_upload else create_graph -max "${net[upload_graph_max]}" -i -add-last upload_graph net_history_upload fi + if ((net[nic_change]==1 | resized>0)); then + local dev_len=${#net[device]} + if ((dev_len>15)); then dev_len=15; fi + unset net_misc 'net[nic_change]' + print -v net_out -m $((line-1)) $((width-23)) -rs -fg ${box[net_color]} -rp 23 -t "─" + print -v net_misc -m $((line-1)) $((width-7-dev_len)) -rs -fg ${box[net_color]} -t "┤" -fg ${theme[hi_fg]} -b -t "‹b " -fg ${theme[title]} -t "${net[device]::15}" -fg ${theme[hi_fg]} -t " n›" -rs -fg ${box[net_color]} -t "├" + net_out+="${net_misc}" + fi + #* Create text depening on box height local ypos=$n_line @@ -3110,6 +3527,7 @@ draw_net() { #? Draw net information and graphs to screen #* Print graphs and text to output variable draw_out+="${download_graph[*]}${upload_graph[*]}${net_out}" + if [[ $argument == "now" ]]; then echo -en "${download_graph[*]}${upload_graph[*]}${net_out}"; fi } draw_clock() { #? Draw a clock at top of screen @@ -3136,7 +3554,7 @@ pause_() { #? Pause input and draw a darkened version of main ui local pause_out ext_var if [[ -n $1 && $1 != "off" ]]; then local -n pause_out=${1}; ext_var=1; fi if [[ $1 != "off" ]]; then - prev_screen="${boxes_out}${proc_det}${last_screen}${mem_out}${detail_graph[*]}${proc_out}${proc_misc}${proc_misc2}${update_string}${clock_out}" + prev_screen="${boxes_out}${proc_det}${last_screen}${net_misc}${mem_out}${detail_graph[*]}${proc_out}${proc_misc}${proc_misc2}${update_string}${clock_out}" if [[ -n $skip_process_draw ]]; then prev_screen+="${proc_out}" unset skip_process_draw proc_out @@ -3144,7 +3562,7 @@ pause_() { #? Pause input and draw a darkened version of main ui unset pause_screen print -v pause_screen -rs -b -fg ${theme[inactive_fg]} - pause_screen+="${theme[main_bg]}m$(sed -E 's/\\e\[[0-9;\-]*m//g' <<< "${prev_screen}")\e[0m" #\e[1;38;5;236 + pause_screen+="${theme[main_bg]}m$(${sed} -E 's/\\e\[[0-9;\-]*m//g' <<< "${prev_screen}")\e[0m" #\e[1;38;5;236 if [[ -z $ext_var ]]; then echo -en "${pause_screen}" else pause_out="${pause_screen}"; fi @@ -3216,7 +3634,7 @@ menu_() { #? Shows the main menu overlay else wait_string="0"; time_left=0; fi get_key -v keypress -w ${wait_string} - if [[ $(stty size) != "$tty_height $tty_width" ]]; then resized; fi + if [[ $(${stty} size) != "$tty_height $tty_width" ]]; then resized; fi if ((resized>0)); then calc_sizes; draw_bg quiet; time_left=0; unset menu_out unset bannerd @@ -3258,7 +3676,8 @@ help_() { #? Shows the help overlay "(Enter)" "(Pg Up) (Pg Down)" "(Home) (End)" - "(Left, Right)" + "(Left) (Right)" + "(b, B) (n, N)" "(R, r)" "(F, f)" "(C, c)" @@ -3280,6 +3699,7 @@ help_() { #? Shows the help overlay "Jump 1 page in process list." "Jump to first or last page in process list." "Select previous/next sorting column." + "Select previous/next network device." "Reverse sorting order in processes box." "Input a string to filter processes with." "Clear any entered filter." @@ -3347,7 +3767,7 @@ help_() { #? Shows the help overlay esac fi - if [[ $(stty size) != "$tty_height $tty_width" ]]; then resized; fi + if [[ $(${stty} size) != "$tty_height $tty_width" ]]; then resized; fi if ((resized>0)); then sleep 0.5 calc_sizes; draw_bg quiet; redraw=1 @@ -3653,7 +4073,8 @@ options_() { #? Shows the options overlay selected_var="true" if [[ $selected == "proc_reversed" ]]; then proc[order_change]=1; proc[reverse]="+"; fi fi - if [[ $selected == "check_temp" ]]; then resized=1; fi + if [[ $selected == "check_temp" ]] && command -v sensors >/dev/null 2>&1; then resized=1 + else check_temp="false"; fi ;; "proc_sorting right") if ((proc[sorting_int]<${#sorting[@]}-1)); then ((++proc[sorting_int])) @@ -3701,7 +4122,7 @@ options_() { #? Shows the options overlay draw_bg quiet fi - if [[ $(stty size) != "$tty_height $tty_width" ]]; then resized; fi + if [[ $(${stty} size) != "$tty_height $tty_width" ]]; then resized; fi if ((resized>0)); then calc_sizes; draw_bg quiet @@ -3783,7 +4204,7 @@ killer_() { #? Kill process with selected signal else wait_string="0"; time_left=0; fi get_key -v keypress -w ${wait_string} - if [[ $(stty size) != "$tty_height $tty_width" ]]; then resized; fi + if [[ $(${stty} size) != "$tty_height $tty_width" ]]; then resized; fi if ((resized>0)); then calc_sizes; draw_bg quiet; time_left=0; unset killer_out killer_box fi @@ -3844,10 +4265,10 @@ get_key() { #? Get one key from standard input and translate key code to readabl else unset key - key=$(stty -cooked min 0 time ${wait_time:-0}; dd bs=1 count=1 2>/dev/null) + key=$(${stty} -cooked min 0 time ${wait_time:-0} 2>/dev/null; ${dd} bs=1 count=1 2>/dev/null) if [[ -z ${key:+s} ]]; then key_out="" - stty isig + ${stty} isig if [[ -z $save ]]; then return 0 else return 1; fi fi @@ -3859,7 +4280,7 @@ get_key() { #? Get one key from standard input and translate key code to readabl elif [[ $key == "${backspace}" || $key == "${backspace_real}" ]]; then key="backspace" elif [[ $key == "${tab}" ]]; then key="tab" elif [[ $key == "$esc_character" ]]; then - esc=1; key=$(stty -cooked isig min 0 time 0; dd bs=1 count=3 2>/dev/null); fi + esc=1; key=$(${stty} -cooked min 0 time 0 2>/dev/null; ${dd} bs=1 count=3 2>/dev/null); fi if [[ -z $key && $esc -eq 1 ]]; then key="escape" elif [[ $esc -eq 1 ]]; then case "${key}" in @@ -3892,8 +4313,8 @@ get_key() { #? Get one key from standard input and translate key code to readabl fi - stty -cooked isig min 0 time 0; dd bs=512 count=1 >/dev/null 2>&1 - stty isig + ${stty} -cooked min 0 time 0 >/dev/null 2>&1; ${dd} bs=512 count=1 >/dev/null 2>&1 + ${stty} isig if [[ -n $save && -n $key ]]; then saved_key+=("${key}"); return 0; fi if [[ -n $ext_out ]]; then key_out="${key}" @@ -3930,6 +4351,28 @@ process_input() { #? Process keypresses for main ui proc_sorting="${sorting[proc[sorting_int]]}" filter_change=1 ;; + n|N) #* Switch to next network device + if ((${#nic_list[@]}>1)); then + if ((nic_int<${#nic_list[@]}-1)); then ((++nic_int)) + else nic_int=0; fi + net[device]="${nic_list[nic_int]}" + net[nic_change]=1 + collect_net init + collect_net + draw_net now + fi + ;; + b|B) #* Switch to previous network device + if ((${#nic_list[@]}>1)); then + if ((nic_int>0)); then ((nic_int--)) + else nic_int=$((${#nic_list[@]}-1)); fi + net[device]="${nic_list[nic_int]}" + net[nic_change]=1 + collect_net init + collect_net + draw_net now + fi + ;; up|shift_tab) #* Move process selector up one if [[ ${proc[selected]} -gt 0 ]]; then ((proc[selected]--)) @@ -4094,7 +4537,7 @@ main_loop() { #? main loop... #* Timestamp for accurate timer get_ms timestamp_start - if [[ $(stty size) != "$tty_height $tty_width" ]]; then resized; fi + if [[ $(${stty} size) != "$tty_height $tty_width" ]]; then resized; fi if ((resized>0)); then calc_sizes @@ -4161,7 +4604,7 @@ main_loop() { #? main loop... draw_update_string fi - if ((skip_process_draw==1)); then unset skip_process_draw; fi + unset skip_process_draw skip_net_draw } #? Pre main loop @@ -4191,6 +4634,28 @@ else unset 'save_array[@]' fi +#* Force the use of python psutil on MacOS +if [[ $system == "MacOS" ]]; then use_psutil="true"; fi + +#* Check for python3 and psutil if "use_psutil" is true +if [[ $use_psutil == true ]]; then + if ! command -v python3 >/dev/null 2>&1; then + echo "Error: Missing python3!" + if [[ $system == "Linux" ]]; then + use_psutil="false" + else + exit 1 + fi + elif ! python3 -c "import psutil" >/dev/null 2>&1; then + echo "Error: Missing python3 psutil module!" + if [[ $system == "Linux" ]]; then + use_psutil="false" + else + exit 1 + fi + fi +fi + #* Set up traps for ctrl-c, soft kill, window resize, ctrl-z and resume from ctrl-z trap 'quitting=1; time_left=0' SIGINT SIGQUIT SIGTERM trap 'resized=1; time_left=0' SIGWINCH From 44af9247fd75e13555480c176967de27ed393708 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Sat, 23 May 2020 00:57:35 +0200 Subject: [PATCH 13/52] Updated instructions and information for OSX --- README.md | 99 +++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 74 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index f80f7b9..85a22d1 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,10 @@ # ![bashtop](Imgs/logo-t.png) ![os](https://img.shields.io/badge/Os-Linux-yellow?logo=linux) -![usage](https://img.shields.io/badge/Usage-Linux%20resource%20monitor-red) +![os](https://img.shields.io/badge/Os-OSX-green?logo=apple) +![usage](https://img.shields.io/badge/Usage-System%20resource%20monitor-red) ![Bash](https://img.shields.io/badge/Bash-v4.4%5E-green?logo=GNU%20bash) +![Python](https://img.shields.io/badge/Python-v3.6%5E-purple?logo=python) ![bashtop_version](https://img.shields.io/github/v/tag/aristocratos/bashtop?label=version) [![Donate](https://img.shields.io/badge/-Donate-yellow?logo=paypal)](https://paypal.me/aristocratos) [![Sponsor](https://img.shields.io/badge/-Sponsor-red?logo=github)](https://github.com/sponsors/aristocratos) @@ -16,8 +18,8 @@ * [Themes](#themes) * [Upcoming](#upcoming) (Updated, Python port) * [Support and funding](#support-and-funding) -* [Compatibility](#compatibility) -* [Dependencies](#dependencies) +* [Compatibility](#compatibility) (Updated, OSX Support) +* [Dependencies](#dependencies) (Updated) * [Screenshots](#screenshots) * [Installation](#installation) (Updated) * [Configurability](#configurability) @@ -58,20 +60,20 @@ Let me know if you want to contribute with new themes. ## Upcoming -#### (Mac OSX and *BSD support) +#### (Python port) -Currently rewriting to use python3 [psutil](https://github.com/giampaolo/psutil) for data collection instead of linux specific tools. -This will add python 3 and psutil as dependencies, but will make bashtop cross platform compatible. +~~Currently rewriting to use python3 [psutil](https://github.com/giampaolo/psutil) for data collection instead of linux specific tools. +This will add python 3 and psutil as dependencies, but will make bashtop cross platform compatible.~~ -~~This will be in a new branch called bashtop-psutil when I'm done with initial testing~~ +~~This will be integrated in to main version when done and add the possibility to switch between psutil and linux tools for users running linux.~~ -This will be integrated in to main version when done and add the possibility to switch between psutil and linux tools for users running linux. +Bashtop is now Mac OS X compatible! #### Update -Work on a complete python port will begin this summer. My aim is to keep it compatible with pypy3 for a lot of added efficiency. +Work on a complete python port ~~will begin this summer~~ has begun. My aim is to keep it compatible with pypy3 for a lot of added efficiency. -Bash(py)top? +PyPyTop? ## Support and funding @@ -90,7 +92,12 @@ Any support is greatly appreciated! ## Compatibility -Should work on most modern linux distributions. +Should work on most modern linux distributions and on Mac OS X. + +Will not display correctly on the standard terminal on OSX! +Recommended alternative [iTerm2](https://www.iterm2.com/) + +Will also need to be run as superuser on OSX to display stats for processes not owned by user. For correct display, a terminal with support for: @@ -109,24 +116,38 @@ Dropbear seems to not be able to set correct locale. So if accessing bashtop ove ## Dependencies +## Linux and OSX + **[bash](https://www.gnu.org/software/bash/)** (v4.4 or later) Script functionality will most probably break with earlier versions. Bash version 5 is highly recommended to make use of $EPOCHREALTIME variable instead of a lot of external date command calls. -**[GNU Core Utilities](https://www.gnu.org/software/coreutils/)** +**[GNU coreutils](https://www.gnu.org/software/coreutils/)** -**[GNU Grep](https://www.gnu.org/software/grep/)** +**[GNU sed](https://www.gnu.org/software/sed/)** + +## Linux using /proc for data collection + +**[GNU grep](https://www.gnu.org/software/grep/)** **[ps from procps-ng](https://gitlab.com/procps-ng/procps)** (v3.1.15 or later) -**[sed](https://www.gnu.org/software/sed/)** +**[GNU awk](https://www.gnu.org/software/gawk/)** -**[awk](https://www.gnu.org/software/gawk/)** +## OSX or Linux using psutil for data collecton -(Optional) **[lm-sensors](https://github.com/lm-sensors/lm-sensors)** Needed to show CPU temperatures +**[Python3](https://www.python.org/downloads/)** (v3.6 or later) -(Optional) **[curl](https://curl.haxx.se/download.html)** (v7.16.2 or later) Needed if you want messages about updates and the ability to download themes. +**[psutil python module](https://github.com/giampaolo/psutil)** -(Optional) **[iostat (part of sysstat)](https://github.com/sysstat/sysstat)** Needed if you want disk read/write stats +## Optionals for additional stats + +(Optional OSX) **[osx-cpu-temp](https://github.com/lavoiesl/osx-cpu-temp)** Needed to show CPU temperatures. + +(Optional Linux) **[lm-sensors](https://github.com/lm-sensors/lm-sensors)** Needed to show CPU temperatures. + +(Optional Linux) **[iostat (part of sysstat)](https://github.com/sysstat/sysstat)** Needed if you want disk read/write stats and are not using psutil data collection. + +(Optional OSX/Linux) **[curl](https://curl.haxx.se/download.html)** (v7.16.2 or later) Needed if you want messages about updates and the ability to download themes. ## Screenshots @@ -141,20 +162,45 @@ Options menu. ## Installation -#### Manual installation +#### Dependencies installation OSX -Copy or link "bashtop" into PATH, or install with Makefile: - ->From cloned directory +>Install homebrew if not already installed ``` bash - sudo make install +/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)" +``` + +>Install dependencies + +``` bash +brew install bash coreutils gnu-sed python3 git +pip3 install psutil +``` + +>Install optional dependency osx-cpu-temp + +``` bash +git clone https://github.com/lavoiesl/osx-cpu-temp.git +cd osx-cpu-temp +make +sudo make install +``` + +#### Manual installation Linux and OSX + + +>Clone and install + +``` bash +git clone https://github.com/aristocratos/bashtop.git +cd bashtop +sudo make install ``` >to uninstall it ``` bash - sudo make uninstall +sudo make uninstall ``` #### Arch based @@ -277,6 +323,9 @@ update_check="true" #* Enable graphs with double the horizontal resolution, increases cpu usage hires_graphs="false" + +#* Enable the use of psutil python3 module for data collection, default on OSX +use_psutil="true" ``` #### Command line options: (not yet implemented) @@ -291,7 +340,7 @@ USAGE: bashtop Might finish off items out of order since I usually work on multiple at a time. - [x] Add options to change colors for text, graphs and meters. -- [ ] Fix cross platform compatibility for Mac OSX and *BSD: Currently in testing. +- [x] Fix cross platform compatibility for Mac OSX and *BSD: Working on OSX, not fully tested on *BSD. - [x] Add support for showing AMD cpu temperatures. - [x] Add option to show tree view of processes. - [x] Add option to reset network download/upload totals. From d7cc0052ac46e01ef17c8290897aefa584322c85 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Sat, 23 May 2020 00:58:33 +0200 Subject: [PATCH 14/52] psutil and OSX fixes --- bashtop | 84 ++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 54 insertions(+), 30 deletions(-) diff --git a/bashtop b/bashtop index ccbace0..bf67b54 100755 --- a/bashtop +++ b/bashtop @@ -50,7 +50,6 @@ bash_version_major=${BASH_VERSINFO[0]} bash_version_minor=${BASH_VERSINFO[1]} if [[ "$bash_version_major" -lt 4 ]] || [[ "$bash_version_major" == 4 && "$bash_version_minor" -lt 4 ]]; then echo "ERROR: Bash 4.4 or later is required (you are using Bash $bash_version_major.$bash_version_minor)." - echo " Consider upgrading your distribution to get a more recent Bash version." exit 1 fi @@ -75,7 +74,7 @@ banner_colors=("#E62525" "#CD2121" "#B31D1D" "#9A1919" "#801414") if [[ $system == "MacOS" ]]; then tool_prefix="g"; fi -for tool in "dd" "df" "stty" "sed" "uptime"; do +for tool in "dd" "df" "stty" "sed"; do declare -n set_tool="${tool}" set_tool="${tool_prefix}${tool}" done @@ -130,7 +129,7 @@ update_check="true" #* Enable graphs with double the horizontal resolution, increases cpu usage hires_graphs="false" -#* Enable the use of psutil python module for data collection, default when not on linux +#* Enable the use of psutil python3 module for data collection, default on OSX use_psutil="true" aaz_config() { : ; } #! Do not remove this line! @@ -168,14 +167,14 @@ declare -A cpu mem swap proc net box theme disks declare -a cpu_usage cpu_graph_a cpu_graph_b color_meter color_temp_graph color_cpu color_cpu_graph cpu_history color_mem_graph color_swap_graph declare -a mem_history swap_history net_history_download net_history_upload mem_graph swap_graph proc_array download_graph upload_graph trace_array declare resized=1 size_error clock tty_width tty_height hex="16#" cpu_p_box swap_on=1 draw_out esc_character boxes_out last_screen clock_out update_string -declare -a options_array=("color_theme" "update_ms" "proc_sorting" "check_temp" "draw_clock" "background_update" "custom_cpu_name" "proc_per_core" +declare -a options_array=("color_theme" "update_ms" "use_psutil" "proc_sorting" "check_temp" "draw_clock" "background_update" "custom_cpu_name" "proc_per_core" "proc_reversed" "proc_gradient" "disks_filter" "hires_graphs" "net_totals_reset" "update_check" "error_logging") declare -a save_array=(${options_array[*]/net_totals_reset/}) declare -a sorting=( "pid" "program" "arguments" "threads" "user" "memory" "cpu lazy" "cpu responsive" "tree" ) declare -a detail_graph detail_history detail_mem_history disks_io declare -A pid_history declare time_left timestamp_start timestamp_end timestamp_input_start timestamp_input_end time_string mem_out proc_misc prev_screen pause_screen filter input_to_filter -declare no_epoch proc_det proc_misc2 sleeping=0 detail_mem_graph proc_det2 proc_out curled git_version has_iostat +declare no_epoch proc_det proc_misc2 sleeping=0 detail_mem_graph proc_det2 proc_out curled git_version has_iostat sensor_comm declare esc_character tab backspace sleepy late_update skip_process_draw winches quitting theme_int notifier saved_stty nic_int net_misc skip_net_draw declare -a disks_free disks_total disks_name disks_free_percent saved_key themes nic_list old_procs printf -v esc_character "\u1b" @@ -276,12 +275,20 @@ init_() { #? Collect needed information and set options before startig main loop #* Set terminal options, save and clear screen saved_stty="$(${stty} -g)" tput smcup + echo -en "\033]0;BashTOP\a" tput clear ${stty} -echo tput civis - #* Check if "sensors" command is available, if not, disable temperature collection - if [[ $check_temp != false ]] && command -v sensors >/dev/null 2>&1; then check_temp="true"; else check_temp="false"; fi + + #* Check if "sensors", "osx-cpu-temp" or "vcgencmd" commands is available, if not, disable temperature collection + if [[ $check_temp == true ]]; then + local checker + for checker in "vcgencmd" "sensors" "osx-cpu-temp"; do + if command -v "${checker}" >/dev/null 2>&1; then sensor_comm="${checker}"; fi + done + if [[ -z $sensor_comm ]]; then check_temp="false"; fi + fi #* Check if "curl" command is available, if not, disable update check and theme downloads if command -v curl >/dev/null 2>&1; then curled=1; else unset curled; fi @@ -512,6 +519,7 @@ quit_() { #? Clean exit tput rmcup tput cnorm ${stty} "${saved_stty}" + echo -en "\033]0;\a" #* Save any changed values to config file if [[ $config_file != "/dev/null" ]]; then @@ -526,6 +534,7 @@ sleep_() { #? Restore terminal options, stop and send to background if caught SI tput rmcup tput cnorm ${stty} "${saved_stty}" + echo -en "\033]0;\a" kill -s SIGSTOP $$ } @@ -533,6 +542,7 @@ sleep_() { #? Restore terminal options, stop and send to background if caught SI resume_() { #? Set terminal options and resume if caught SIGCONT ('fg' from terminal) sleepy=0 tput smcup + echo -en "\033]0;BashTOP\a" tput clear ${stty} -echo tput civis @@ -1966,7 +1976,7 @@ EOF #* Get load average and uptime from uptime command if [[ $use_psutil == false ]]; then local uptime_var - read -r uptime_var < <(${uptime} 2>/dev/null || true) + read -r uptime_var < <(uptime 2>/dev/null || true) cpu[load_avg]="${uptime_var#*average: }" cpu[load_avg]="${cpu[load_avg]//,/}" cpu[uptime]="${uptime_var#*up }" @@ -1978,11 +1988,15 @@ EOF } collect_cpu_temps() { #? Collect cpu temperatures - local unit c div threads=${cpu[threads]} sens_var i it ccd_value breaking core_value + local unit c div threads=${cpu[threads]} sens_var i it ccd_value breaking core_value misc_var local -a ccd_array core_array #* Fetch output from "sensors" command to a variable - read -rd '' sens_var < <(sensors) ||true + if [[ $sensor_comm == "sensors" ]]; then + read -rd '' sens_var < <(sensors 2>/dev/null || true) || true + elif [[ $sensor_comm != "sensors" ]]; then + read -r misc_var < <(${sensor_comm} measure_temp 2>/dev/null ||true) + fi #* Get CPU package temp for intel cpus if get_value -v 'cpu[temp_0]' -sv "sens_var" -k "Package*:" -mk 1 || get_value -v 'cpu[temp_0]' -sv "sens_var" -k "Core 0:" -mk 1; then @@ -2037,11 +2051,9 @@ collect_cpu_temps() { #? Collect cpu temperatures z=$((z+i)) done - #* Get CPU package temp for Rapberry Pi cpus - elif command -v vcgencmd >/dev/null 2>&1; then - read -r cpu[temp_0] < <(vcgencmd measure_temp 2>/dev/null ||true) ||true - if [[ -z ${cpu[temp_0]} ]]; then cpu[temp_0]="temp=0.0°C"; fi - cpu[temp_0]="${cpu[temp_0]#temp=}" + #* Get CPU package temp for Rapberry Pi cpus and for OSX + elif [[ $sensor_comm != "sensors" && -n ${misc_var} ]]; then + cpu[temp_0]="${misc_var#temp=}" cpu[temp_unit]="°${cpu[temp_0]:(-1)}"; cpu[temp_0]=${cpu[temp_0]%.*}; if [[ ${cpu[temp_0]::1} == "+" ]]; then cpu[temp_0]=${cpu[temp_0]#+}; fi cpu[temp_high]="75"; cpu[temp_crit]=$((cpu[temp_high]+10)) @@ -2050,16 +2062,17 @@ collect_cpu_temps() { #? Collect cpu temperatures cpu[temp_${i}]="${cpu[temp_0]}" done - #* If unsuccessful turn off temperature checking else check_temp="false" + resized=1 fi if [[ $check_temp == true ]]; then - local tmp_temp="$(( (${cpu[temp_${i}]}-20)*100/(cpu[temp_high]-20) ))" - if ((tmp_temp>100)); then tmp_temp=100; elif ((tmp_temp<0)); then tmp_temp=0; fi + local tmp_temp for((i=0;i<=threads;i++)); do + tmp_temp="$(( (${cpu[temp_${i}]}-20)*100/(cpu[temp_high]-20) ))" + if ((tmp_temp>100)); then tmp_temp=100; elif ((tmp_temp<0)); then tmp_temp=0; fi local -n cpu_temp_history="cpu_temp_history_$i" if ((${#cpu_temp_history[@]}>20)); then cpu_temp_history=( "${cpu_temp_history[@]:10}" "${tmp_temp}") @@ -3099,9 +3112,10 @@ draw_mem() { #? Draw mem, swap and disk statistics if ((mem[counter]>0 & resized==0)); then return; fi local i swap_used_meter swap_free_meter mem_available_meter mem_free_meter mem_used_meter mem_cached_meter normal_color="${theme[main_fg]}" value_text - local meter_mod_w meter_mod_pos value type m_title meter_options - local -a types=("mem") values=("used" "available" "free") - if [[ $system != "MacOS" ]]; then values+=("cached"); fi + local meter_mod_w meter_mod_pos value type m_title meter_options values + local -a types=("mem") + if [[ $system == "MacOS" ]]; then values="used available free" + else values="used available cached free"; fi unset mem_out if [[ -n $swap_on ]]; then types+=("swap"); fi @@ -3124,9 +3138,8 @@ draw_mem() { #? Draw mem, swap and disk statistics #* Print name of type and total amount in humanized base 2 bytes print -v mem_out -m $y_pos $m_col -rs -fg ${theme[title]} -b -jl 9 -t "${m_title^}:" -m $((y_pos++)) $((mem_line-10)) -jr 9 -trans -t " ${type_name[total_string]::$((m_width-11))}" - for value in "${values[@]}"; do - if [[ $type == "swap" && $value == "available" ]]; then value="free" - elif [[ $type == "swap" && $value == "cached" ]]; then break 2; fi + for value in ${values}; do + if [[ $type == "swap" && $value =~ available|cached ]]; then continue; fi value_text="${value::$((m_width-12))}" if ((height<14)); then value_text="${value_text::5}"; fi @@ -3266,7 +3279,7 @@ draw_processes() { #? Draw processes and values to screen print -v proc_det2 -m $((d_line+i)) ${d_col} -fg ${box[processes_color]} -t "│" -r $((detail_graph_width+1)) -fg ${theme[div_line]} -t "│" -r $((right_width+1)) -fg ${box[processes_color]} -t "│" done - print -v proc_det2 -m ${d_line} ${d_col} -t "┌" -m ${d_line} $((d_col+d_width)) -t "┐" + print -v proc_det2 -m ${d_line} ${d_col} -t "┌" -m ${d_line} $((d_col+d_width-1)) -t "┐" print -v proc_det2 -m ${d_line} $((d_col+2+detail_graph_width)) -t "┬" -m $((d_line+d_height)) $((d_col+detail_graph_width+2)) -t "┴" print -v proc_det2 -m $((d_line+d_height)) ${d_col} -t "├" -r 1 -t "┤" -fg ${theme[title]} -b -t "${this_box}" -rs -fg ${box[processes_color]} -t "├" -r $((d_width-5-${#this_box})) -t "┤" print -v proc_det2 -m ${d_line} $((d_col+2)) -t "┤" -fg ${theme[title]} -b -t "${proc[detailed_name],,}" -rs -fg ${box[processes_color]} -t "├" @@ -3810,6 +3823,12 @@ options_() { #? Shows the options overlay "loops processing time." " " "Max value: 86400000 ms = 24 hours.") + desc_use_psutil=( "Enable the use of psutil python3 module for" + "data collection, default on Mac OSX" + " " + "True or false." + " " + "Can only be switched off when on Linux.") desc_proc_sorting=( "Processes sorting." "Valid values are \"pid\", \"program\", \"arguments\"," "\"threads\", \"user\", \"memory\", \"cpu lazy\"" @@ -4064,7 +4083,7 @@ options_() { #? Shows the options overlay if ((net[reset]==1)); then net_totals_reset="Off"; net[reset]=0 else net_totals_reset="On"; net[reset]=1; fi ;; - "check_temp"*|"error_logging"*|"background_update"*|"proc_reversed"*|"proc_gradient"*|"proc_per_core"*|"update_check"*|"hires_graphs"*) + "check_temp"*|"error_logging"*|"background_update"*|"proc_reversed"*|"proc_gradient"*|"proc_per_core"*|"update_check"*|"hires_graphs"*|"use_psutil"*) local -n selected_var=${selected} if [[ ${selected_var} == "true" ]]; then selected_var="false" @@ -4073,8 +4092,15 @@ options_() { #? Shows the options overlay selected_var="true" if [[ $selected == "proc_reversed" ]]; then proc[order_change]=1; proc[reverse]="+"; fi fi - if [[ $selected == "check_temp" ]] && command -v sensors >/dev/null 2>&1; then resized=1 - else check_temp="false"; fi + if [[ $selected == "check_temp" ]]; then + local checker + for checker in "vcgencmd" "sensors" "osx-cpu-temp"; do + if command -v "${checker}" >/dev/null 2>&1; then sensor_comm="${checker}"; fi + done + if [[ -z $sensor_comm ]]; then check_temp="false"; fi + fi + if [[ $selected == "use_psutil" && $system != "Linux" ]]; then use_psutil="true"; fi + ;; "proc_sorting right") if ((proc[sorting_int]<${#sorting[@]}-1)); then ((++proc[sorting_int])) @@ -4662,8 +4688,6 @@ trap 'resized=1; time_left=0' SIGWINCH trap 'sleepy=1; time_left=0' SIGTSTP trap 'resume_' SIGCONT - - #* Set up error logging to file if enabled if [[ $error_logging == true ]]; then set -o errtrace From 491b28bea53a97b26f08975585d6de57f84cca91 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Sat, 23 May 2020 01:52:41 +0200 Subject: [PATCH 15/52] Updated OSX info --- README.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 85a22d1..2ed990c 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,8 @@ Resource monitor that shows usage and stats for processor, memory, disks, networ * UI menu for changing all config file options. * Auto scaling graph for network usage. * Shows message in menu if new version is available +* Shows current read and write speeds for disks +* Multiple data collection methods which can be switched if running on Linux ## Themes @@ -99,6 +101,8 @@ Recommended alternative [iTerm2](https://www.iterm2.com/) Will also need to be run as superuser on OSX to display stats for processes not owned by user. +The disk io stats on OSX shows iostats for all disks at the top instead of per disk because of limitations with psutil on OSX. + For correct display, a terminal with support for: * 24-bit truecolor @@ -279,7 +283,7 @@ Config files stored in "$HOME/.config/bashtop" folder #### bashtop.cfg: (auto generated if not found) ```bash -#? Config file for bashtop v. 0.8.28 +#? Config file for bashtop v. 0.9.0 #* Color theme, looks for a .theme file in "$HOME/.config/bashtop/themes", "Default" for builtin default theme color_theme="Default" @@ -294,7 +298,7 @@ proc_sorting="cpu lazy" #* Reverse sorting order, "true" or "false" proc_reversed="false" -#* Check cpu temperature, only works if "sensors" command is available and have values for "Package" and "Core" +#* Check cpu temperature, only works if "sensors", "vcgencmd" or "osx-cpu-temp" commands is available check_temp="true" #* Draw a clock at top of screen, formatting according to strftime, empty string to disable From 226cf89a3d543b7b89a5e1ec94c4009a68e83126 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Sat, 23 May 2020 01:57:16 +0200 Subject: [PATCH 16/52] v0.9.0 Added Mac OS X support! --- CHANGELOG.md | 5 +++++ bashtop | 31 +++++++++++++++++++++---------- 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 02c412b..c608c32 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +## v0.9.0 + +* Added: Mac OS X support with python3 psutil data collection +* Added: Ability to switch between all available network devices + ## v0.8.32 * Fixed: Error in theme error checking corrupting default theme diff --git a/bashtop b/bashtop index bf67b54..e5f1aab 100755 --- a/bashtop +++ b/bashtop @@ -65,15 +65,15 @@ banner=( "██╔══██╗██╔══██║╚════██║██╔══██║ ██║ ██║ ██║██╔═══╝ " "██████╔╝██║ ██║███████║██║ ██║ ██║ ╚██████╔╝██║ " "╚═════╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ") -declare version="0.8.32" +declare version="0.9.0" #* Get latest version of BashTOP from https://github.com/aristocratos/bashtop declare banner_width=${#banner[0]} banner_colors=("#E62525" "#CD2121" "#B31D1D" "#9A1919" "#801414") +#* Set correct names for GNU tools depending on OS if [[ $system == "MacOS" ]]; then tool_prefix="g"; fi - for tool in "dd" "df" "stty" "sed"; do declare -n set_tool="${tool}" set_tool="${tool_prefix}${tool}" @@ -99,7 +99,7 @@ proc_sorting="cpu lazy" #* Reverse sorting order, "true" or "false" proc_reversed="false" -#* Check cpu temperature, only works if "sensors" command is available and have values for "Package" and "Core" +#* Check cpu temperature, only works if "sensors", "vcgencmd" or "osx-cpu-temp" commands is available check_temp="true" #* Draw a clock at top of screen, formatting according to strftime, empty string to disable @@ -3126,6 +3126,7 @@ draw_mem() { #? Draw mem, swap and disk statistics #* Create text and meters for memory and swap and adapt sizes based on available height local y_pos=$m_line v_height=8 list value meter inv_meter + if [[ $system == "MacOS" ]]; then v_height=4; fi for type in ${types[@]}; do local -n type_name="$type" if [[ $type == "mem" ]]; then @@ -3165,6 +3166,7 @@ draw_mem() { #? Draw mem, swap and disk statistics if [[ -z $meter_mod_w ]]; then print -v mem_out -jr 4 -t "${type_name[${value}_percent]}%"; fi fi + if [[ $system == "MacOS" ]] && ((height>8)); then ((y_pos++)); fi done done @@ -3834,19 +3836,20 @@ options_() { #? Shows the options overlay "\"threads\", \"user\", \"memory\", \"cpu lazy\"" "\"cpu responsive\" and \"tree\"." " " - "\"cpu lazy\" uses ps commands internal sorting" - "and updates top process over a period of time." + "\"cpu lazy\" shows cpu usage over the lifetime" + "of a process." " " "\"cpu responsive\" updates sorting directly at a" - "cost of cpu time." + "cost of cpu time (unless using psutil)." " " "\"tree\" shows a tree structure of running" - "processes.") + "processes. (not available with psutil)") desc_check_temp=( "Check cpu temperature." " " - "Only works if sensors command is available" - "and show values for Package and Core" - "temperatures.") + "True or false." + " " + "Only works if sensors, vcgencmd or osx-cpu-temp" + "commands is available.") desc_draw_clock=( "Draw a clock at top of screen." " " "Formatting according to strftime, empty" @@ -4369,12 +4372,20 @@ process_input() { #? Process keypresses for main ui if ((proc[sorting_int]>0)); then ((proc[sorting_int]--)) else proc[sorting_int]=$((${#sorting[@]}-1)); fi proc_sorting="${sorting[proc[sorting_int]]}" + if [[ $proc_sorting == "tree" && $use_psutil == true ]]; then + ((proc[sorting_int]--)) + proc_sorting="${sorting[proc[sorting_int]]}" + fi filter_change=1 ;; right) #* Move right in processes sorting column if ((proc[sorting_int]<${#sorting[@]}-1)); then ((++proc[sorting_int])) else proc[sorting_int]=0; fi proc_sorting="${sorting[proc[sorting_int]]}" + if [[ $proc_sorting == "tree" && $use_psutil == true ]]; then + proc[sorting_int]=0 + proc_sorting="${sorting[proc[sorting_int]]}" + fi filter_change=1 ;; n|N) #* Switch to next network device From 102e015c2cb5cb35cd2b33ea659bebdf1d2cf8a6 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Sat, 23 May 2020 12:07:14 +0200 Subject: [PATCH 17/52] Fixed: Expanded graph history for hires graphs --- bashtop | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bashtop b/bashtop index e5f1aab..3e12c00 100755 --- a/bashtop +++ b/bashtop @@ -1943,8 +1943,8 @@ EOF done #* Copy cpu usage for cpu package and cores to cpu history arrays and trim earlier entries - if ((${#cpu_history[@]}>tty_width*2)); then - cpu_history=( "${cpu_history[@]:$tty_width}" "${cpu_usage[0]}") + if ((${#cpu_history[@]}>tty_width*4)); then + cpu_history=( "${cpu_history[@]:$((tty_width*2))}" "${cpu_usage[0]}") else cpu_history+=("${cpu_usage[0]}") fi @@ -2821,8 +2821,8 @@ collect_net() { #? Collect information from "/proc/net/dev" #* Copy download and upload speed to history arrays and trim earlier entries local -n history="net_history_${direction}" - if ((${#history[@]}>box[net_width]*2)); then - history=( "${history[@]:${box[net_width]}}" "${net[speed_${direction}]}") + if ((${#history[@]}>box[net_width]*4)); then + history=( "${history[@]:$((box[net_width]*2))}" "${net[speed_${direction}]}") else history+=("${net[speed_${direction}]}") fi From d1b40f333933141b5c94155a576158a4834838b3 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Sat, 23 May 2020 17:50:56 +0200 Subject: [PATCH 18/52] Added: Support for FreeBSD --- bashtop | 78 +++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 51 insertions(+), 27 deletions(-) diff --git a/bashtop b/bashtop index 3e12c00..f943650 100755 --- a/bashtop +++ b/bashtop @@ -35,12 +35,13 @@ declare -x LC_MESSAGES="C" LC_NUMERIC="C" LC_ALL="" #* Fail if running on unsupported OS case "$(uname -s)" in Linux*) system=Linux;; + *BSD) system=BSD;; Darwin*) system=MacOS;; CYGWIN*) system=Cygwin;; MINGW*) system=MinGw;; *) system="Other" esac -if [[ "$system" != "Linux" && "$system" != "MacOS" ]]; then +if [[ ! $system =~ Linux|MacOS|BSD ]]; then echo "This version of bashtop does not support $system platform." exit 1 fi @@ -73,12 +74,20 @@ declare banner_width=${#banner[0]} banner_colors=("#E62525" "#CD2121" "#B31D1D" "#9A1919" "#801414") #* Set correct names for GNU tools depending on OS -if [[ $system == "MacOS" ]]; then tool_prefix="g"; fi -for tool in "dd" "df" "stty" "sed"; do +if [[ $system != "Linux" ]]; then tool_prefix="g"; fi +for tool in "dd" "df" "stty" "tail" "realpath" "sed"; do declare -n set_tool="${tool}" set_tool="${tool_prefix}${tool}" done +if ! command -v ${dd} >/dev/null 2>&1; then + echo "ERROR: Missing GNU coreutils!" + exit 1 +elif ! command -v ${sed} >/dev/null 2>&1; then + echo "ERROR: Missing GNU sed!" + exit 1 +fi + read tty_height tty_width < <(${stty} size) #? Start default variables------------------------------------------------------------------------------> @@ -186,6 +195,12 @@ printf -v enter_key "\uD" printf -v ctrl_c "\u03" printf -v ctrl_z "\u1A" +hide_cursor='\033[?25l' #* Hide terminal cursor +show_cursor='\033[?25h' #* Show terminal cursor +alt_screen='\033[?1049h' #* Switch to alternate screen +normal_screen='\033[?1049l' #* Switch to normal screen +clear_screen='\033[2J' #* Clear screen + #* Symbols for graphs declare -a graph_symbol graph_symbol=(" " "⡀" "⣀" "⣄" "⣤" "⣦" "⣴" "⣶" "⣷" "⣾" "⣿") @@ -274,11 +289,12 @@ init_() { #? Collect needed information and set options before startig main loop local i #* Set terminal options, save and clear screen saved_stty="$(${stty} -g)" - tput smcup + #tput smcup + echo -en "${alt_screen}${hide_cursor}${clear_screen}" echo -en "\033]0;BashTOP\a" - tput clear + #tput clear ${stty} -echo - tput civis + #tput civis #* Check if "sensors", "osx-cpu-temp" or "vcgencmd" commands is available, if not, disable temperature collection @@ -515,9 +531,10 @@ color_init_() { #? Check for theme file and set colors quit_() { #? Clean exit #* Restore terminal options and screen - tput clear - tput rmcup - tput cnorm + #tput clear + #tput rmcup + #tput cnorm + echo -en "${clear_screen}${normal_screen}${show_cursor}" ${stty} "${saved_stty}" echo -en "\033]0;\a" @@ -530,9 +547,10 @@ quit_() { #? Clean exit } sleep_() { #? Restore terminal options, stop and send to background if caught SIGTSTP (ctrl+z) - tput clear - tput rmcup - tput cnorm + # tput clear + # tput rmcup + # tput cnorm + echo -en "${clear_screen}${normal_screen}${show_cursor}" ${stty} "${saved_stty}" echo -en "\033]0;\a" @@ -541,11 +559,12 @@ sleep_() { #? Restore terminal options, stop and send to background if caught SI resume_() { #? Set terminal options and resume if caught SIGCONT ('fg' from terminal) sleepy=0 - tput smcup + #tput smcup + echo -en "${alt_screen}${hide_cursor}${clear_screen}" echo -en "\033]0;BashTOP\a" - tput clear + #tput clear ${stty} -echo - tput civis + #tput civis if [[ -n $pause_screen ]]; then echo -en "$pause_screen" @@ -614,7 +633,7 @@ draw_banner() { #? Draw banner, usage: draw_banner [output variable] create_config() { #? Creates a new config file with default values from above local c_line c_read this_file - this_file="$(realpath "$0")" + this_file="$(${realpath} "$0")" echo "#? Config file for bashtop v. ${version}" > "$config_file" while IFS= read -r c_line; do if [[ $c_line =~ aaz_config() ]]; then break @@ -1913,7 +1932,10 @@ for thread in threads: print(f'cpu{x}', int(thread.user*10), int(thread.nice*10), int(thread.system*10), int(thread.idle*10)) x += 1 -print(round(psutil.cpu_freq().current)) +try: + print(round(psutil.cpu_freq().current)) +except: + print(0) print(str(timedelta(seconds=round(time()-psutil.boot_time(),0)))[:-3]) @@ -2152,7 +2174,7 @@ EOF done #* Get disk information from "df" command - local df_array df_line line_array dev_path dev_name iostat_var disk_read disk_write disk_io_string + local df_array df_line line_array dev_path dev_name iostat_var disk_read disk_write disk_io_string df_count=0 local -a device_array iostat_array unset 'disks_free[@]' 'disks_used[@]' 'disks_used_percent[@]' 'disks_total[@]' 'disks_name[@]' 'disks_free_percent[@]' 'disks_io[@]' readarray -t df_array < <(${df} -x squashfs -x tmpfs -x devtmpfs -x overlay 2>/dev/null || true) @@ -2185,10 +2207,10 @@ EOF dev_path="${line_array[0]%${dev_name}}" if [[ ${dev_name::2} == "md" ]]; then dev_name="${dev_name::3}"; fi unset iostat_var disk_io_string 'iostat_array[@]' - if [[ $use_psutil == true && $system == "MacOS" && ${disks_name[-1]} == "root" ]]; then - read -r iostat_var < <(python3 -c "import psutil; disk = psutil.disk_io_counters(perdisk=False); print(disk.read_bytes>>10, disk.write_bytes>>10)") - elif [[ $use_psutil == true && $system != "MacOS" ]]; then - read -r iostat_var < <(python3 -c "import os, psutil; disk = psutil.disk_io_counters(perdisk=True)[os.path.realpath('${dev_path}${dev_name}').split('/')[-1]]; print(disk.read_bytes>>10, disk.write_bytes>>10)") + if [[ $use_psutil == true && $system != "Linux" ]] && ((df_count==0)); then + read -r iostat_var < <(python3 -c "import psutil; disk = psutil.disk_io_counters(perdisk=False); print(disk.read_bytes>>10, disk.write_bytes>>10)" 2>/dev/null) + elif [[ $use_psutil == true && $system == "Linux" ]]; then + read -r iostat_var < <(python3 -c "import os, psutil; disk = psutil.disk_io_counters(perdisk=True)[os.path.realpath('${dev_path}${dev_name}').split('/')[-1]]; print(disk.read_bytes>>10, disk.write_bytes>>10)" 2>/dev/null) elif [[ $use_psutil == false ]]; then read -r iostat_var < <(iostat -dkz "${dev_path}${dev_name}" | tail -n +4) fi @@ -2216,6 +2238,7 @@ EOF fi if ((${#disks_name[@]}>=height/2)); then break; fi + ((++df_count)) done @@ -2497,12 +2520,13 @@ collect_processes_psutil() { if [[ -n $skip_process_draw && $argument != "now" ]]; then return; fi if [[ $argument == "now" ]]; then skip_process_draw=1; fi local prog_len arg_len symbol="▼" sorting selected imports time_elapsed no_core_divide width=${box[processes_width]} height=${box[processes_height]} - local cmdargs titleargs titletr hide_self pid pcpu_usage pids p_count cpu_int pids + local cmdargs titleargs titletr hide_self pid pcpu_usage pids p_count cpu_int pids bsd_idle #* Timestamp the values in milliseconds to accurately calculate cpu usage get_ms proc[new_timestamp] if [[ $proc_per_core == true ]]; then no_core_divide="1"; fi + if [[ $system == "BSD" ]]; then bsd_idle="or p.info['name'] == 'idle'"; fi time_elapsed=$((proc[new_timestamp]-proc[old_timestamp])) @@ -2584,7 +2608,7 @@ search = '${filter}' print(f"{'Pid:':>7} {'Program:':<${prog_len}}${titleargs}${titletr} {'User:':<9}Mem%{'Cpu%':>11}") for p in sorted(psutil.process_iter(['pid', 'name', 'cmdline', 'num_threads', 'username', 'memory_percent', 'cpu_times', 'create_time'], err), key=lambda p: ${sorting}): - if p.info['pid'] == selfpid: + if p.info['pid'] == selfpid ${bsd_idle}: continue if p.info['cpu_times'] == err: p.info['memory_percent'] = 0.0 @@ -4671,8 +4695,8 @@ else unset 'save_array[@]' fi -#* Force the use of python psutil on MacOS -if [[ $system == "MacOS" ]]; then use_psutil="true"; fi +#* Force the use of python psutil if not on Linux +if [[ $system != "Linux" ]]; then use_psutil="true"; fi #* Check for python3 and psutil if "use_psutil" is true if [[ $use_psutil == true ]]; then @@ -4706,7 +4730,7 @@ if [[ $error_logging == true ]]; then #* Remove everything but the last 500 lines of error log if larger than 500 lines if [[ -e "${config_dir}/error.log" && $(wc -l <"${config_dir}/error.log") -gt 500 ]]; then - tail -n 500 "${config_dir}/error.log" > "${config_dir}/tmp" + ${tail} -n 500 "${config_dir}/error.log" > "${config_dir}/tmp" rm "${config_dir}/error.log" mv "${config_dir}/tmp" "${config_dir}/error.log" fi From 7a109586a77079d76bf1f4e5a003abdb09521f7a Mon Sep 17 00:00:00 2001 From: aristocratos Date: Sat, 23 May 2020 18:21:41 +0200 Subject: [PATCH 19/52] Added info for FreeBSD --- README.md | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 2ed990c..0607ffe 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,11 @@ # ![bashtop](Imgs/logo-t.png) -![os](https://img.shields.io/badge/Os-Linux-yellow?logo=linux) -![os](https://img.shields.io/badge/Os-OSX-green?logo=apple) -![usage](https://img.shields.io/badge/Usage-System%20resource%20monitor-red) +![Linux](https://img.shields.io/badge/-Linux-grey?logo=linux) +![OSX](https://img.shields.io/badge/-OSX-black?logo=apple) +![FreeBSD](https://img.shields.io/badge/-FreeBSD-red?logo=freebsd) +![Usage](https://img.shields.io/badge/Usage-System%20resource%20monitor-blue) ![Bash](https://img.shields.io/badge/Bash-v4.4%5E-green?logo=GNU%20bash) -![Python](https://img.shields.io/badge/Python-v3.6%5E-purple?logo=python) +![Python](https://img.shields.io/badge/Python-v3.6%5E-orange?logo=python) ![bashtop_version](https://img.shields.io/github/v/tag/aristocratos/bashtop?label=version) [![Donate](https://img.shields.io/badge/-Donate-yellow?logo=paypal)](https://paypal.me/aristocratos) [![Sponsor](https://img.shields.io/badge/-Sponsor-red?logo=github)](https://github.com/sponsors/aristocratos) @@ -62,16 +63,14 @@ Let me know if you want to contribute with new themes. ## Upcoming -#### (Python port) - ~~Currently rewriting to use python3 [psutil](https://github.com/giampaolo/psutil) for data collection instead of linux specific tools. This will add python 3 and psutil as dependencies, but will make bashtop cross platform compatible.~~ ~~This will be integrated in to main version when done and add the possibility to switch between psutil and linux tools for users running linux.~~ -Bashtop is now Mac OS X compatible! +Bashtop is now Mac OS X and FreeBSD compatible! -#### Update +#### Python port Work on a complete python port ~~will begin this summer~~ has begun. My aim is to keep it compatible with pypy3 for a lot of added efficiency. @@ -94,7 +93,7 @@ Any support is greatly appreciated! ## Compatibility -Should work on most modern linux distributions and on Mac OS X. +Should work on most modern linux distributions, on Mac OS X and on FreeBSD. Will not display correctly on the standard terminal on OSX! Recommended alternative [iTerm2](https://www.iterm2.com/) @@ -120,7 +119,7 @@ Dropbear seems to not be able to set correct locale. So if accessing bashtop ove ## Dependencies -## Linux and OSX +## Linux, OSX and FreeBSD **[bash](https://www.gnu.org/software/bash/)** (v4.4 or later) Script functionality will most probably break with earlier versions. Bash version 5 is highly recommended to make use of $EPOCHREALTIME variable instead of a lot of external date command calls. @@ -137,7 +136,7 @@ Bash version 5 is highly recommended to make use of $EPOCHREALTIME variable inst **[GNU awk](https://www.gnu.org/software/gawk/)** -## OSX or Linux using psutil for data collecton +## OSX and FreeBSD or Linux using psutil for data collection **[Python3](https://www.python.org/downloads/)** (v3.6 or later) @@ -151,7 +150,7 @@ Bash version 5 is highly recommended to make use of $EPOCHREALTIME variable inst (Optional Linux) **[iostat (part of sysstat)](https://github.com/sysstat/sysstat)** Needed if you want disk read/write stats and are not using psutil data collection. -(Optional OSX/Linux) **[curl](https://curl.haxx.se/download.html)** (v7.16.2 or later) Needed if you want messages about updates and the ability to download themes. +(Optional OSX/Linux/FreeBSD) **[curl](https://curl.haxx.se/download.html)** (v7.16.2 or later) Needed if you want messages about updates and the ability to download themes. ## Screenshots @@ -190,8 +189,17 @@ make sudo make install ``` -#### Manual installation Linux and OSX +#### Dependencies installation FreeBSD +>Install with pkg and pip + +``` bash +sudo pkg install coreutils gsed python3 git +sudo python3 -m ensurepip +sudo pip3 install psutil +``` + +#### Manual installation Linux, OSX and FreeBSD >Clone and install @@ -344,7 +352,7 @@ USAGE: bashtop Might finish off items out of order since I usually work on multiple at a time. - [x] Add options to change colors for text, graphs and meters. -- [x] Fix cross platform compatibility for Mac OSX and *BSD: Working on OSX, not fully tested on *BSD. +- [x] Fix cross platform compatibility for Mac OSX and *BSD: Working on OSX, and FreeBSD. - [x] Add support for showing AMD cpu temperatures. - [x] Add option to show tree view of processes. - [x] Add option to reset network download/upload totals. From f38585a9d29c3f1dde5024b2affe21b7d6cc209f Mon Sep 17 00:00:00 2001 From: aristocratos Date: Sat, 23 May 2020 18:26:57 +0200 Subject: [PATCH 20/52] v0.9.1 Added support for FreeBSD --- CHANGELOG.md | 6 ++++++ bashtop | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c608c32..a275f41 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## v0.9.1 + +* Added: FreeBSD support with python3 psutil data collection +* Added: Check for gnu tools on non Linux platforms +* Fixed: Increased graph history to avoid cut off on high resolution graphs + ## v0.9.0 * Added: Mac OS X support with python3 psutil data collection diff --git a/bashtop b/bashtop index f943650..7e4c470 100755 --- a/bashtop +++ b/bashtop @@ -66,7 +66,7 @@ banner=( "██╔══██╗██╔══██║╚════██║██╔══██║ ██║ ██║ ██║██╔═══╝ " "██████╔╝██║ ██║███████║██║ ██║ ██║ ╚██████╔╝██║ " "╚═════╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ") -declare version="0.9.0" +declare version="0.9.1" #* Get latest version of BashTOP from https://github.com/aristocratos/bashtop From a16cb82f3b698ed4ec46fba29cc22ac966649a4a Mon Sep 17 00:00:00 2001 From: aristocratos Date: Sat, 23 May 2020 18:34:06 +0200 Subject: [PATCH 21/52] Corrections in Compatibility --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 0607ffe..2f6f853 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ * [Themes](#themes) * [Upcoming](#upcoming) (Updated, Python port) * [Support and funding](#support-and-funding) -* [Compatibility](#compatibility) (Updated, OSX Support) +* [Compatibility](#compatibility) (Updated, OSX and FreeBSD Support) * [Dependencies](#dependencies) (Updated) * [Screenshots](#screenshots) * [Installation](#installation) (Updated) @@ -100,7 +100,7 @@ Recommended alternative [iTerm2](https://www.iterm2.com/) Will also need to be run as superuser on OSX to display stats for processes not owned by user. -The disk io stats on OSX shows iostats for all disks at the top instead of per disk because of limitations with psutil on OSX. +The disk io stats on OSX and FreeBSD shows iostats for all disks at the top instead of per disk. For correct display, a terminal with support for: @@ -219,7 +219,7 @@ sudo make uninstall Available in the AUR as [bashtop-git](https://aur.archlinux.org/packages/bashtop-git/) -Available in the Arch Linux repository as [bashtop](https://www.archlinux.org/packages/community/any/bashtop/) (Flagged out-of-date on 2020-04-28) +Available in the Arch Linux repository as [bashtop](https://www.archlinux.org/packages/community/any/bashtop/) #### Debian based From 5bb62802f0f7772aaab78395baf9e791e2764e11 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Mon, 25 May 2020 09:26:23 +0200 Subject: [PATCH 22/52] Fixed: Correct prefixes for GNU tools, Added: Init progress status, Changed: replaced tput commands with escape sequence commands --- bashtop | 145 +++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 90 insertions(+), 55 deletions(-) diff --git a/bashtop b/bashtop index 7e4c470..30d4b57 100755 --- a/bashtop +++ b/bashtop @@ -75,7 +75,7 @@ banner_colors=("#E62525" "#CD2121" "#B31D1D" "#9A1919" "#801414") #* Set correct names for GNU tools depending on OS if [[ $system != "Linux" ]]; then tool_prefix="g"; fi -for tool in "dd" "df" "stty" "tail" "realpath" "sed"; do +for tool in "dd" "df" "stty" "tail" "realpath" "wc" "rm" "mv" "sleep" "stdbuf" "mkfifo" "date" "kill" "sed"; do declare -n set_tool="${tool}" set_tool="${tool_prefix}${tool}" done @@ -262,13 +262,15 @@ else tmpdir="/dev/shm" elif [[ -w /tmp ]]; then tmpdir="/tmp" + elif [[ -w "$HOME" ]]; then + tmpdir="$HOME" fi - if [[ -n $tmpdir ]] && command -v stdbuf >/dev/null 2>&1; then - mkfifo "${tmpdir}/bashtop_datefifo" - exec 5> >(exec stdbuf -o0 date -f - +%s%3N > "${tmpdir}/bashtop_datefifo" 2>&1) + if [[ -n $tmpdir ]] && command -v ${stdbuf} >/dev/null 2>&1; then + ${mkfifo} "${tmpdir}/bashtop_datefifo" + exec 5> >(exec ${stdbuf} -o0 ${date} -f - +%s%3N > "${tmpdir}/bashtop_datefifo" 2>&1) exec 6< "${tmpdir}/bashtop_datefifo" - rm "${tmpdir}/bashtop_datefifo" + ${rm} -f "${tmpdir}/bashtop_datefifo" get_ms() { #? Set given variable to current epoch millisecond with date command through background fifo local -n ms_out=$1 @@ -280,24 +282,46 @@ else get_ms() { #? Set given variable to current epoch millisecond with forked date command local -n ms_out=$1 ms_out="" - read ms_out < <(date +%s%3N) + read ms_out < <(${date} +%s%3N) } fi fi init_() { #? Collect needed information and set options before startig main loop - local i + local i stx=0 #* Set terminal options, save and clear screen saved_stty="$(${stty} -g)" - #tput smcup echo -en "${alt_screen}${hide_cursor}${clear_screen}" echo -en "\033]0;BashTOP\a" - #tput clear ${stty} -echo - #tput civis + #* Wait for resize if terminal size is smaller then 80x24 + if (($tty_width<80 | $tty_height<24)); then resized; echo -en "${clear_screen}"; fi + + #* Draw banner to banner array + local letter b_color banner_line y=0 + local -a banner_out + #print -v banner_out[0] -t "\e[0m" + for banner_line in "${banner[@]}"; do + #* Read banner array letter by letter to set correct color for filled vs outline characters + while read -rN1 letter; do + if [[ $letter == "█" ]]; then b_color="${banner_colors[$y]}" + else b_color=$((80-y*6)); fi + if [[ $letter == " " ]]; then + print -v banner_out[y] -r 1 + else + print -v banner_out[y] -fg ${b_color} "${letter}" + fi + done <<<"$banner_line" + ((++y)) + done + banner=("${banner_out[@]}") + + #* Draw banner to screen and show status while running init + draw_banner $((tty_height/2-10)) #* Check if "sensors", "osx-cpu-temp" or "vcgencmd" commands is available, if not, disable temperature collection + print -m $(( (tty_height/2-3)+stx++ )) 0 -bg "#00" -fg "#cc" -b -c "Checking available tools..." if [[ $check_temp == true ]]; then local checker for checker in "vcgencmd" "sensors" "osx-cpu-temp"; do @@ -316,6 +340,8 @@ init_() { #? Collect needed information and set options before startig main loop if [[ $use_psutil == false ]] && command -v iostat >/dev/null 2>&1; then has_iostat=1; else unset has_iostat; fi #* Get number of cores and cpu threads + print -bg "#00" -fg "#30ff50" -r 1 -t "√" + print -m $(( (tty_height/2-3)+stx++ )) 0 -bg "#00" -fg "#cc" -c -b "Checking cpu..." get_cpu_info #* Set graph resolution @@ -339,60 +365,53 @@ init_() { #? Collect needed information and set options before startig main loop proc[pid_len]="7" fi - #* Wait for resize if terminal size is smaller then 80x24 - if (($tty_width<80 | $tty_height<24)); then resized; fi - #* Calculate sizes of boxes + print -bg "#00" -fg "#30ff50" -r 1 -t "√" + print -m $(( (tty_height/2-3)+stx++ )) 0 -bg "#00" -fg "#cc" -c -b "Calculating sizes..." calc_sizes #* Call init for cpu data collection + print -bg "#00" -fg "#30ff50" -r 1 -t "√" + print -m $(( (tty_height/2-3)+stx++ )) 0 -bg "#00" -fg "#cc" -c -b "Running cpu collection init..." collect_cpu init #* Call init for memory data collection and check if swap is available + print -bg "#00" -fg "#30ff50" -r 1 -t "√" + print -m $(( (tty_height/2-3)+stx++ )) 0 -bg "#00" -fg "#cc" -c -b "Running mem collection init..." mem[counter]=10 collect_mem init #* Get default network device from "ip route" command and call init for net collection if device is found + print -bg "#00" -fg "#30ff50" -r 1 -t "√" + print -m $(( (tty_height/2-3)+stx++ )) 0 -bg "#00" -fg "#cc" -c -b "Checking network devices..." get_net_device #* Check if newer version of bashtop is available from https://github.com/aristocratos/bashtop if [[ -n $curled && $update_check == "true" ]]; then - if ! get_value -v git_version -ss "$(curl -m 2 --raw -r 0-3500 https://raw.githubusercontent.com/aristocratos/bashtop/master/bashtop 2>/dev/null)" -k "version=" -r "[^0-9.]"; then unset git_version; fi + print -bg "#00" -fg "#30ff50" -r 1 -t "√" + print -m $(( (tty_height/2-3)+stx++ )) 0 -bg "#00" -fg "#cc" -c -b "Checking for updates..." + if ! get_value -v git_version -ss "$(curl -m 4 --raw -r 0-3500 https://raw.githubusercontent.com/aristocratos/bashtop/master/bashtop 2>/dev/null)" -k "version=" -r "[^0-9.]"; then unset git_version; fi fi - #* Draw banner to banner array and notify about new updates - local letter b_color banner_line y=0 - local -a banner_out - #print -v banner_out[0] -t "\e[0m" - for banner_line in "${banner[@]}"; do - #* Read banner array letter by letter to set correct color for filled vs outline characters - while read -rN1 letter; do - if [[ $letter == "█" ]]; then b_color="${banner_colors[$y]}" - else b_color=$((80-y*6)); fi - if [[ $letter == " " ]]; then - print -v banner_out[y] -r 1 - else - print -v banner_out[y] -fg ${b_color} "${letter}" - fi - done <<<"$banner_line" - ((++y)) - done - print -v banner_out[y] -rs -fg cc -b "← esc" + #* Add update notification to banner if new version is available + local banner_out_up + print -v banner_out_up -rs -fg cc -b "← esc" if [[ -n $git_version && $git_version != "$version" ]]; then - print -v banner_out[y] -rs -fg "#80cc80" -r 15 "[${git_version} available!]" -r $((9-${#git_version})) + print -v banner_out_up -rs -fg "#80cc80" -r 15 "[${git_version} available!]" -r $((9-${#git_version})) if [[ -n $notifier ]]; then notify-send -u normal\ "Bashtop Update!" "New version of Bashtop available\!\nCurrent version: ${version}\n\New version: ${git_version}\nDownload at github.com/aristocratos/bashtop"\ -i face-glasses -t 10000 fi else - print -v banner_out[y] -r 37 + print -v banner_out_up -r 37 fi - print -v banner_out[y] -fg cc -i -b "Version: ${version}" -rs - unset 'banner[@]' - banner=("${banner_out[@]}") + print -v banner_out_up -fg cc -i -b "Version: ${version}" -rs + banner+=("${banner_out_up}") #* Get theme and set colors + print -bg "#00" -fg "#30ff50" -r 1 -t "√" + print -m $(( (tty_height/2-3)+stx++ )) 0 -bg "#00" -fg "#cc" -c -b "Generating colors for theme..." color_init_ #* Set up internals for quick processes sorting switching @@ -414,10 +433,32 @@ init_() { #? Collect needed information and set options before startig main loop fi #* Call init for processes data collection + print -bg "#00" -fg "#30ff50" -r 1 -t "√" + print -m $(( (tty_height/2-3)+stx++ )) 0 -bg "#00" -fg "#cc" -c -b "Running process collection init..." proc[selected]=0 proc[page]=1 collect_processes init + #* Draw first screen + print -bg "#00" -fg "#30ff50" -r 1 -t "√" + print -m $(( (tty_height/2-3)+stx++ )) 0 -bg "#00" -fg "#cc" -c -b "Drawing screen..." + + draw_bg quiet + get_ms timestamp_start + + for task in processes cpu mem net; do + collect_${task} + draw_${task} + done + last_screen="${draw_out}" + + print -bg "#00" -fg "#30ff50" -r 1 -t "√" -rs + sleep 0.5 + + draw_clock + echo -en "${clear_screen}${draw_out}${proc_out}${clock_out}" + resized=0 + unset draw_out } color_init_() { #? Check for theme file and set colors @@ -531,9 +572,6 @@ color_init_() { #? Check for theme file and set colors quit_() { #? Clean exit #* Restore terminal options and screen - #tput clear - #tput rmcup - #tput cnorm echo -en "${clear_screen}${normal_screen}${show_cursor}" ${stty} "${saved_stty}" echo -en "\033]0;\a" @@ -547,24 +585,18 @@ quit_() { #? Clean exit } sleep_() { #? Restore terminal options, stop and send to background if caught SIGTSTP (ctrl+z) - # tput clear - # tput rmcup - # tput cnorm echo -en "${clear_screen}${normal_screen}${show_cursor}" ${stty} "${saved_stty}" echo -en "\033]0;\a" - kill -s SIGSTOP $$ + ${kill} -s SIGSTOP $$ } resume_() { #? Set terminal options and resume if caught SIGCONT ('fg' from terminal) sleepy=0 - #tput smcup echo -en "${alt_screen}${hide_cursor}${clear_screen}" echo -en "\033]0;BashTOP\a" - #tput clear ${stty} -echo - #tput civis if [[ -n $pause_screen ]]; then echo -en "$pause_screen" @@ -602,7 +634,7 @@ resized() { #? Get new terminal size if terminal is resized else create_box -w 30 -h 3 -c 1 -l 1 -lc "#EE2020" -title "resizing" print -jc 28 -fg ${theme[title]} "New size: ${tty_width}x${tty_height}" - sleep 0.2 + ${sleep} 0.2 if [[ $(${stty} size) != "$tty_height $tty_width" ]]; then winches=0; fi fi done @@ -611,11 +643,11 @@ resized() { #? Get new terminal size if terminal is resized size_error_msg() { #? Shows error message if terminal size is below 80x25 local width=$tty_width local height=$tty_height - tput clear + echo -en "${clear_screen}" create_box -full -lc "#EE2020" -title "resize window" print -rs -m $((tty_height/2-1)) 2 -fg ${theme[title]} -c -l 11 "Current size: " -bg "#00" -fg dd2020 -d 1 -c "${tty_width}x${tty_height}" -rs print -d 1 -fg ${theme[title]} -c -l 15 "Need to be atleast:" -bg "#00" -fg 30dd50 -d 1 -c "80x24" -rs - while [[ $(${stty} size) == "$tty_height $tty_width" ]]; do sleep 0.2; if [[ -n $quitting ]]; then quit_; fi ; done + while [[ $(${stty} size) == "$tty_height $tty_width" ]]; do ${sleep} 0.2; if [[ -n $quitting ]]; then quit_; fi ; done } @@ -818,6 +850,9 @@ get_cpu_info() { if [[ $system == "MacOS" ]]; then lscpu_var="Model name: $(sysctl -n machdep.cpu.brand_string)" + elif [[ $system == "BSD" ]]; then + lscpu_var="$(sysctl hw.model)" + lscpu_var="${lscpu_var/hw.model:/Model name:}" elif command -v lscpu >/dev/null 2>&1; then lscpu_var="$(lscpu)" fi @@ -3808,7 +3843,7 @@ help_() { #? Shows the help overlay if [[ $(${stty} size) != "$tty_height $tty_width" ]]; then resized; fi if ((resized>0)); then - sleep 0.5 + ${sleep} 0.5 calc_sizes; draw_bg quiet; redraw=1 d_banner=1 unset bannerd menu_out @@ -4278,7 +4313,7 @@ killer_() { #? Kill process with selected signal unpause_ break elif ((confirmed>0)) && [[ -z $status ]]; then - if kill -${sig} ${kill_pid} >/dev/null 2>&1; then + if ${kill} -${sig} ${kill_pid} >/dev/null 2>&1; then status="success" else if ! ps -p ${kill_pid} >/dev/null 2>&1; then @@ -4729,10 +4764,10 @@ if [[ $error_logging == true ]]; then trap 'traperr' ERR #* Remove everything but the last 500 lines of error log if larger than 500 lines - if [[ -e "${config_dir}/error.log" && $(wc -l <"${config_dir}/error.log") -gt 500 ]]; then + if [[ -e "${config_dir}/error.log" && $(${wc} -l <"${config_dir}/error.log") -gt 500 ]]; then ${tail} -n 500 "${config_dir}/error.log" > "${config_dir}/tmp" - rm "${config_dir}/error.log" - mv "${config_dir}/tmp" "${config_dir}/error.log" + ${rm} -f "${config_dir}/error.log" + ${mv} -f "${config_dir}/tmp" "${config_dir}/error.log" fi ( echo " " ; echo "New instance of bashtop version: ${version} Pid: $$" ) >> "${config_dir}/error.log" exec 2>>"${config_dir}/error.log" From eaca66cee54d536c3de37524fcd82199d61dd46c Mon Sep 17 00:00:00 2001 From: aristocratos Date: Mon, 25 May 2020 09:30:41 +0200 Subject: [PATCH 23/52] v0.9.2 Added startup progress screen and fixed prefixes for some missed GNU tools --- CHANGELOG.md | 6 ++++++ bashtop | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a275f41..5f323d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## v0.9.2 + +* Fixed: Correct prefixes for some missed GNU tools +* Added: Startup progress screen +* Changed: replaced tput commands with escape sequence commands + ## v0.9.1 * Added: FreeBSD support with python3 psutil data collection diff --git a/bashtop b/bashtop index 30d4b57..f0fcb0b 100755 --- a/bashtop +++ b/bashtop @@ -66,7 +66,7 @@ banner=( "██╔══██╗██╔══██║╚════██║██╔══██║ ██║ ██║ ██║██╔═══╝ " "██████╔╝██║ ██║███████║██║ ██║ ██║ ╚██████╔╝██║ " "╚═════╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ") -declare version="0.9.1" +declare version="0.9.2" #* Get latest version of BashTOP from https://github.com/aristocratos/bashtop From ae6250a1f42e1008fd8b443776271dc531a700fc Mon Sep 17 00:00:00 2001 From: aristocratos Date: Mon, 25 May 2020 11:38:23 +0200 Subject: [PATCH 24/52] Updated OSX instructions --- README.md | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/README.md b/README.md index 2f6f853..dbf5d99 100644 --- a/README.md +++ b/README.md @@ -183,10 +183,7 @@ pip3 install psutil >Install optional dependency osx-cpu-temp ``` bash -git clone https://github.com/lavoiesl/osx-cpu-temp.git -cd osx-cpu-temp -make -sudo make install +brew install osx-cpu-temp ``` #### Dependencies installation FreeBSD From c7631c0cea3f2d52136372f221bcc7df83b764b8 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Mon, 25 May 2020 12:37:59 +0200 Subject: [PATCH 25/52] Fixed resizing problems in iTerm2 and removed redudant error checking in print function for lower cpu usage --- bashtop | 70 +++++++++++++++++++++++++++++++-------------------------- 1 file changed, 38 insertions(+), 32 deletions(-) diff --git a/bashtop b/bashtop index f0fcb0b..6398dd9 100755 --- a/bashtop +++ b/bashtop @@ -4,7 +4,7 @@ # shellcheck disable=SC2034 #Unused variables # shellcheck disable=SC2068 #Double quote array warning # shellcheck disable=SC2086 # Double quote warning -## shellcheck disable=SC2120 +# shellcheck disable=SC2140 # Word form warning # shellcheck disable=SC2162 #Read without -r # shellcheck disable=SC2206 #Word split warning # shellcheck disable=SC2178 #Array to string warning @@ -306,7 +306,7 @@ init_() { #? Collect needed information and set options before startig main loop #* Read banner array letter by letter to set correct color for filled vs outline characters while read -rN1 letter; do if [[ $letter == "█" ]]; then b_color="${banner_colors[$y]}" - else b_color=$((80-y*6)); fi + else b_color="#$((80-y*6))"; fi if [[ $letter == " " ]]; then print -v banner_out[y] -r 1 else @@ -395,7 +395,7 @@ init_() { #? Collect needed information and set options before startig main loop #* Add update notification to banner if new version is available local banner_out_up - print -v banner_out_up -rs -fg cc -b "← esc" + print -v banner_out_up -rs -fg "#cc" -b "← esc" if [[ -n $git_version && $git_version != "$version" ]]; then print -v banner_out_up -rs -fg "#80cc80" -r 15 "[${git_version} available!]" -r $((9-${#git_version})) if [[ -n $notifier ]]; then @@ -406,7 +406,7 @@ init_() { #? Collect needed information and set options before startig main loop else print -v banner_out_up -r 37 fi - print -v banner_out_up -fg cc -i -b "Version: ${version}" -rs + print -v banner_out_up -fg "#cc" -i -b "Version: ${version}" -rs banner+=("${banner_out_up}") #* Get theme and set colors @@ -632,6 +632,7 @@ resized() { #? Get new terminal size if terminal is resized size_error_msg winches=0 else + echo -en "${clear_screen}" create_box -w 30 -h 3 -c 1 -l 1 -lc "#EE2020" -title "resizing" print -jc 28 -fg ${theme[title]} "New size: ${tty_width}x${tty_height}" ${sleep} 0.2 @@ -645,8 +646,8 @@ size_error_msg() { #? Shows error message if terminal size is below 80x25 local height=$tty_height echo -en "${clear_screen}" create_box -full -lc "#EE2020" -title "resize window" - print -rs -m $((tty_height/2-1)) 2 -fg ${theme[title]} -c -l 11 "Current size: " -bg "#00" -fg dd2020 -d 1 -c "${tty_width}x${tty_height}" -rs - print -d 1 -fg ${theme[title]} -c -l 15 "Need to be atleast:" -bg "#00" -fg 30dd50 -d 1 -c "80x24" -rs + print -rs -m $((tty_height/2-1)) 2 -fg ${theme[title]} -c -l 11 "Current size: " -bg "#00" -fg "#dd2020" -d 1 -c "${tty_width}x${tty_height}" -rs + print -d 1 -fg ${theme[title]} -c -l 15 "Need to be atleast:" -bg "#00" -fg "#30dd50" -d 1 -c "80x24" -rs while [[ $(${stty} size) == "$tty_height $tty_width" ]]; do ${sleep} 0.2; if [[ -n $quitting ]]; then quit_; fi ; done } @@ -1247,7 +1248,7 @@ create_graph() { #? Create a graph from an array of percentage values, usage; #* Set up graph array print side numbers and lines print -v graph_array[0] -rs - print -v graph_array[0] -m $((line+g_index[0])) ${col} ${normal_vals:+-jr 3 -fg ee -b -t "${side_num[0]}" -rs -fg ${theme[main_fg]} -t "${g_char[0]}"} -fg ${colors[100]} + print -v graph_array[0] -m $((line+g_index[0])) ${col} ${normal_vals:+-jr 3 -fg "#ee" -b -t "${side_num[0]}" -rs -fg ${theme[main_fg]} -t "${g_char[0]}"} -fg ${colors[100]} for((i=1;i <0-255> <0-255>" - val=${2//#/} - if is_int "${@:2:3}"; then fgc="\e[38;2;$2;$3;$4m"; shift 3 - elif [[ ${#val} == 6 ]] && is_hex "$val"; then fgc="\e[38;2;$((${hex}${val:0:2}));$((${hex}${val:2:2}));$((${hex}${val:4:2}))m"; shift - elif [[ ${#val} == 2 ]] && is_hex "$val"; then fgc="\e[38;2;$((${hex}${val:0:2}));$((${hex}${val:0:2}));$((${hex}${val:0:2}))m"; shift + if [[ ${2::1} == "#" ]]; then + val=${2//#/} + if [[ ${#val} == 6 ]]; then fgc="\e[38;2;$((${hex}${val:0:2}));$((${hex}${val:2:2}));$((${hex}${val:4:2}))m"; shift + elif [[ ${#val} == 2 ]]; then fgc="\e[38;2;$((${hex}${val:0:2}));$((${hex}${val:0:2}));$((${hex}${val:0:2}))m"; shift + fi + elif is_int "${@:2:3}"; then fgc="\e[38;2;$2;$3;$4m"; shift 3 fi ;; -bg|-background) #? Set text background color, accepts either 6 digit hexadecimal "#RRGGBB", 2 digit hex (greyscale) or decimal RGB "<0-255> <0-255> <0-255>" - val=${2//#/} - if is_int "${@:2:3}"; then bgc="\e[48;2;$2;$3;$4m"; shift 3 - elif [[ ${#val} == 6 ]] && is_hex "$val"; then bgc="\e[48;2;$((${hex}${val:0:2}));$((${hex}${val:2:2}));$((${hex}${val:4:2}))m"; shift - elif [[ ${#val} == 2 ]] && is_hex "$val"; then bgc="\e[48;2;$((${hex}${val:0:2}));$((${hex}${val:0:2}));$((${hex}${val:0:2}))m"; shift + if [[ ${2::1} == "#" ]]; then + val=${2//#/} + if [[ ${#val} == 6 ]]; then bgc="\e[48;2;$((${hex}${val:0:2}));$((${hex}${val:2:2}));$((${hex}${val:4:2}))m"; shift + elif [[ ${#val} == 2 ]]; then bgc="\e[48;2;$((${hex}${val:0:2}));$((${hex}${val:0:2}));$((${hex}${val:0:2}))m"; shift + fi + elif is_int "${@:2:3}"; then bgc="\e[48;2;$2;$3;$4m"; shift 3 fi ;; -c|-center) center=1;; #? Center text horizontally on screen @@ -1885,15 +1890,15 @@ print() { #? Print text, set true-color foreground/background color, add effects -bl|-blink) effect="${effect}${effect:+;}5";; #? Enable blinking text +bl|+blink) effect="${effect}${effect:+;}25";; #? Disable blinking text -f|-font) if [[ $2 =~ ^(sans-serif|script|fraktur|monospace|double-struck)$ ]]; then custom_font="$2"; shift; fi;; #? Set custom font - -m|-move) if is_int "${@:2:2}"; then add_command="${add_command}\e[${2};${3}f"; shift 2; fi;; #? Move to postion "LINE" "COLUMN" - -l|-left) if is_int "$2"; then add_command="${add_command}\e[${2}D"; shift; fi;; #? Move left x columns - -r|-right) if is_int "$2"; then add_command="${add_command}\e[${2}C"; shift; fi;; #? Move right x columns - -u|-up) if is_int "$2"; then add_command="${add_command}\e[${2}A"; shift; fi;; #? Move up x lines - -d|-down) if is_int "$2"; then add_command="${add_command}\e[${2}B"; shift; fi;; #? Move down x lines - -jl|-justify-left) if is_int "$2"; then justify_left="${2}"; shift; fi;; #? Justify string left within given width - -jr|-justify-right) if is_int "$2"; then justify_right="${2}"; shift; fi;; #? Justify string right within given width - -jc|-justify-center) if is_int "$2"; then justify_center="${2}"; shift; fi;; #? Justify string center within given width - -rp|-repeat) if is_int "$2"; then repeat=${2}; shift; fi;; #? Repeat next string x number of times + -m|-move) add_command="${add_command}\e[${2};${3}f"; shift 2;; #? Move to postion "LINE" "COLUMN" + -l|-left) add_command="${add_command}\e[${2}D"; shift;; #? Move left x columns + -r|-right) add_command="${add_command}\e[${2}C"; shift;; #? Move right x columns + -u|-up) add_command="${add_command}\e[${2}A"; shift;; #? Move up x lines + -d|-down) add_command="${add_command}\e[${2}B"; shift;; #? Move down x lines + -jl|-justify-left) justify_left="${2}"; shift;; #? Justify string left within given width + -jr|-justify-right) justify_right="${2}"; shift;; #? Justify string right within given width + -jc|-justify-center) justify_center="${2}"; shift;; #? Justify string center within given width + -rp|-repeat) repeat=${2}; shift;; #? Repeat next string x number of times -sc|-save) add_command="\e[s${add_command}";; #? Save cursor position -rc|-restore) add_command="${add_command}\e[u";; #? Restore cursor position -trans) trans=1;; #? Make whitespace transparent @@ -3185,7 +3190,7 @@ draw_mem() { #? Draw mem, swap and disk statistics #* Create text and meters for memory and swap and adapt sizes based on available height local y_pos=$m_line v_height=8 list value meter inv_meter - if [[ $system == "MacOS" ]]; then v_height=4; fi + if [[ $system == "MacOS" ]]; then v_height=6; fi for type in ${types[@]}; do local -n type_name="$type" if [[ $type == "mem" ]]; then @@ -3225,7 +3230,7 @@ draw_mem() { #? Draw mem, swap and disk statistics if [[ -z $meter_mod_w ]]; then print -v mem_out -jr 4 -t "${type_name[${value}_percent]}%"; fi fi - if [[ $system == "MacOS" ]] && ((height>8)); then ((y_pos++)); fi + if [[ $system == "MacOS" && -z $swap_on ]] && ((height>8)); then ((y_pos++)); fi done done @@ -3344,7 +3349,7 @@ draw_processes() { #? Draw processes and values to screen print -v proc_det2 -m ${d_line} $((d_col+2+detail_graph_width)) -t "┬" -m $((d_line+d_height)) $((d_col+detail_graph_width+2)) -t "┴" print -v proc_det2 -m $((d_line+d_height)) ${d_col} -t "├" -r 1 -t "┤" -fg ${theme[title]} -b -t "${this_box}" -rs -fg ${box[processes_color]} -t "├" -r $((d_width-5-${#this_box})) -t "┤" print -v proc_det2 -m ${d_line} $((d_col+2)) -t "┤" -fg ${theme[title]} -b -t "${proc[detailed_name],,}" -rs -fg ${box[processes_color]} -t "├" - if ((tty_width>128)); then print -v proc_det2 -m -r 1 -t "┤" -fg ${theme[title]} -b -t "${proc[detailed_pid]}" -rs -fg ${box[processes_color]} -t "├"; fi + if ((tty_width>128)); then print -v proc_det2 -r 1 -t "┤" -fg ${theme[title]} -b -t "${proc[detailed_pid]}" -rs -fg ${box[processes_color]} -t "├"; fi @@ -3654,7 +3659,7 @@ unpause_() { #? Unpause menu_() { #? Shows the main menu overlay local menu i count keypress selected_int=0 selected up local_rez d_banner=1 menu_out bannerd skipped menu_pause out_out wait_string trans local -a menus=("options" "help" "quit") color - + unset bannerd menu_out until false; do #* Put program to sleep if caught ctrl-z @@ -3712,6 +3717,7 @@ menu_() { #? Shows the main menu overlay if ((resized>0)); then calc_sizes; draw_bg quiet; time_left=0; unset menu_out unset bannerd + echo -en "${clear_screen}" fi case "$keypress" in From 732bea1369f35b2f2f512fe1f321f0f9329a9ab4 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Mon, 25 May 2020 13:48:29 +0200 Subject: [PATCH 26/52] Fixed memory display in OSX --- bashtop | 47 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 35 insertions(+), 12 deletions(-) diff --git a/bashtop b/bashtop index 6398dd9..9c3e52e 100755 --- a/bashtop +++ b/bashtop @@ -2163,7 +2163,7 @@ swap = psutil.swap_memory() try: cmem = mem.cached>>10 except: - cmem = 0 + cmem = mem.active>>10 print(mem.total>>10, mem.free>>10, mem.available>>10, cmem, swap.total>>10, swap.free>>10) EOF ) @@ -2217,10 +2217,34 @@ EOF local df_array df_line line_array dev_path dev_name iostat_var disk_read disk_write disk_io_string df_count=0 local -a device_array iostat_array unset 'disks_free[@]' 'disks_used[@]' 'disks_used_percent[@]' 'disks_total[@]' 'disks_name[@]' 'disks_free_percent[@]' 'disks_io[@]' - readarray -t df_array < <(${df} -x squashfs -x tmpfs -x devtmpfs -x overlay 2>/dev/null || true) + if [[ $system == "MacOS" ]]; then + readarray -t df_array < <(df -k 2>/dev/null || true) + else + readarray -t df_array < <(${df} -x squashfs -x tmpfs -x devtmpfs -x overlay 2>/dev/null || true) + fi for df_line in "${df_array[@]:1}"; do line_array=(${df_line}) - if ! is_int "${line_array[2]}"; then continue; fi + if ! is_int "${line_array[1]}"; then continue; fi + + if [[ $system == "MacOS" ]]; then + if [[ ${line_array[0]} == "devfs" ]]; then continue; fi + if [[ ${line_array[8]} == "/private/var/vm" ]]; then + swap[total]="${line_array[1]}" + swap[used]="${line_array[2]}" + swap[free]="${line_array[3]}" + swap[free_percent]=$((swap[free]*100/swap[total])) + swap[used_percent]=$((swap[used]*100/swap[total])) + + #* Convert values to floating point and humanize + for value in total used free; do + local -n this_value="swap[${value}]" this_string="swap[${value}_string]" + floating_humanizer -v this_string -s 1 -B "${this_value}" + done + + continue + fi + line_array[5]="${line_array[8]}" + fi if [[ ${line_array[5]} == "/" ]]; then disks_name+=("root") else disks_name+=("${line_array[5]##*/}"); fi @@ -3176,13 +3200,11 @@ draw_mem() { #? Draw mem, swap and disk statistics if ((mem[counter]>0 & resized==0)); then return; fi local i swap_used_meter swap_free_meter mem_available_meter mem_free_meter mem_used_meter mem_cached_meter normal_color="${theme[main_fg]}" value_text - local meter_mod_w meter_mod_pos value type m_title meter_options values + local meter_mod_w meter_mod_pos value type m_title meter_options values="used available cached free" local -a types=("mem") - if [[ $system == "MacOS" ]]; then values="used available free" - else values="used available cached free"; fi unset mem_out - if [[ -n $swap_on ]]; then types+=("swap"); fi + if [[ -n ${swap[total]} ]]; then types+=("swap"); fi #* Get variables from previous calculations local col=$((box[mem_col]+1)) line=$((box[mem_line]+1)) width=$((box[mem_width]-2)) height=$((box[mem_height]-2)) @@ -3190,7 +3212,7 @@ draw_mem() { #? Draw mem, swap and disk statistics #* Create text and meters for memory and swap and adapt sizes based on available height local y_pos=$m_line v_height=8 list value meter inv_meter - if [[ $system == "MacOS" ]]; then v_height=6; fi + for type in ${types[@]}; do local -n type_name="$type" if [[ $type == "mem" ]]; then @@ -3201,16 +3223,17 @@ draw_mem() { #? Draw mem, swap and disk statistics fi #* Print name of type and total amount in humanized base 2 bytes - print -v mem_out -m $y_pos $m_col -rs -fg ${theme[title]} -b -jl 9 -t "${m_title^}:" -m $((y_pos++)) $((mem_line-10)) -jr 9 -trans -t " ${type_name[total_string]::$((m_width-11))}" + print -v mem_out -m $y_pos $m_col -rs -fg ${theme[title]} -b -jl 9 -t "${m_title^}:" -m $((y_pos++)) $((mem_line-10)) -jr 9 -t " ${type_name[total_string]::$((m_width-11))}" for value in ${values}; do if [[ $type == "swap" && $value =~ available|cached ]]; then continue; fi - value_text="${value::$((m_width-12))}" + if [[ $system == "MacOS" && $value == "cached" ]]; then value_text="active" + else value_text="${value::$((m_width-12))}"; fi if ((height<14)); then value_text="${value_text::5}"; fi #* Print name of value and value amount in humanized base 2 bytes - print -v mem_out -m $y_pos $m_col -rs -fg $normal_color -jl 9 -t "${value_text^}:" -m $((y_pos++)) $((mem_line-10)) -jr 9 -trans -t " ${type_name[${value}_string]::$((m_width-11))}" + print -v mem_out -m $y_pos $m_col -rs -fg $normal_color -jl 9 -t "${value_text^}:" -m $((y_pos++)) $((mem_line-10)) -jr 9 -t " ${type_name[${value}_string]::$((m_width-11))}" #* Create meter for value and calculate size and placement depending on terminal size if ((height>v_height++ | tty_width>100)); then @@ -3230,7 +3253,7 @@ draw_mem() { #? Draw mem, swap and disk statistics if [[ -z $meter_mod_w ]]; then print -v mem_out -jr 4 -t "${type_name[${value}_percent]}%"; fi fi - if [[ $system == "MacOS" && -z $swap_on ]] && ((height>8)); then ((y_pos++)); fi + #if [[ $system == "MacOS" && -z $swap_on ]] && ((height>14)); then ((y_pos++)); fi done done From 6927ee954bed80c978654a0078455e073d109d7f Mon Sep 17 00:00:00 2001 From: aristocratos Date: Mon, 25 May 2020 14:00:20 +0200 Subject: [PATCH 27/52] v0.9.3 OSX fixes and misc optimizations --- CHANGELOG.md | 7 +++++++ bashtop | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5f323d8..e216d6f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## v0.9.3 + +* Fixed: Resizing problems in iTerm2 +* Changed: Removed redundant error checking in print function for lower cpu usage +* Fixed: Memory in OSX now shows active memory usage and /private/var/vm as swap memory +* Fixed: Disks in OSX changed from using "GNU df" to "BSD df" for better compatibility + ## v0.9.2 * Fixed: Correct prefixes for some missed GNU tools diff --git a/bashtop b/bashtop index 9c3e52e..9b6e555 100755 --- a/bashtop +++ b/bashtop @@ -66,7 +66,7 @@ banner=( "██╔══██╗██╔══██║╚════██║██╔══██║ ██║ ██║ ██║██╔═══╝ " "██████╔╝██║ ██║███████║██║ ██║ ██║ ╚██████╔╝██║ " "╚═════╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ") -declare version="0.9.2" +declare version="0.9.3" #* Get latest version of BashTOP from https://github.com/aristocratos/bashtop From 4fbf9351ae256675679e317e8bafb3fad04d3096 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Mon, 25 May 2020 16:40:58 +0200 Subject: [PATCH 28/52] Fixed missing path for OSX df and correct swap usage for OSX --- bashtop | 27 +++++---------------------- 1 file changed, 5 insertions(+), 22 deletions(-) diff --git a/bashtop b/bashtop index 9b6e555..76f0bcf 100755 --- a/bashtop +++ b/bashtop @@ -2218,7 +2218,7 @@ EOF local -a device_array iostat_array unset 'disks_free[@]' 'disks_used[@]' 'disks_used_percent[@]' 'disks_total[@]' 'disks_name[@]' 'disks_free_percent[@]' 'disks_io[@]' if [[ $system == "MacOS" ]]; then - readarray -t df_array < <(df -k 2>/dev/null || true) + readarray -t df_array < <(/bin/df -k -P 2>/dev/null || true) else readarray -t df_array < <(${df} -x squashfs -x tmpfs -x devtmpfs -x overlay 2>/dev/null || true) fi @@ -2226,25 +2226,7 @@ EOF line_array=(${df_line}) if ! is_int "${line_array[1]}"; then continue; fi - if [[ $system == "MacOS" ]]; then - if [[ ${line_array[0]} == "devfs" ]]; then continue; fi - if [[ ${line_array[8]} == "/private/var/vm" ]]; then - swap[total]="${line_array[1]}" - swap[used]="${line_array[2]}" - swap[free]="${line_array[3]}" - swap[free_percent]=$((swap[free]*100/swap[total])) - swap[used_percent]=$((swap[used]*100/swap[total])) - - #* Convert values to floating point and humanize - for value in total used free; do - local -n this_value="swap[${value}]" this_string="swap[${value}_string]" - floating_humanizer -v this_string -s 1 -B "${this_value}" - done - - continue - fi - line_array[5]="${line_array[8]}" - fi + if [[ $system == "MacOS" && ( ${line_array[0]} == "devfs" || ${line_array[5]} == "/private/var/vm" ) ]]; then continue; fi if [[ ${line_array[5]} == "/" ]]; then disks_name+=("root") else disks_name+=("${line_array[5]##*/}"); fi @@ -2273,6 +2255,7 @@ EOF unset iostat_var disk_io_string 'iostat_array[@]' if [[ $use_psutil == true && $system != "Linux" ]] && ((df_count==0)); then read -r iostat_var < <(python3 -c "import psutil; disk = psutil.disk_io_counters(perdisk=False); print(disk.read_bytes>>10, disk.write_bytes>>10)" 2>/dev/null) + df_count=1 elif [[ $use_psutil == true && $system == "Linux" ]]; then read -r iostat_var < <(python3 -c "import os, psutil; disk = psutil.disk_io_counters(perdisk=True)[os.path.realpath('${dev_path}${dev_name}').split('/')[-1]]; print(disk.read_bytes>>10, disk.write_bytes>>10)" 2>/dev/null) elif [[ $use_psutil == false ]]; then @@ -2302,7 +2285,7 @@ EOF fi if ((${#disks_name[@]}>=height/2)); then break; fi - ((++df_count)) + done @@ -3204,7 +3187,7 @@ draw_mem() { #? Draw mem, swap and disk statistics local -a types=("mem") unset mem_out - if [[ -n ${swap[total]} ]]; then types+=("swap"); fi + if [[ -n ${swap[total]} && ${swap[total]} -gt 0 ]]; then types+=("swap"); fi #* Get variables from previous calculations local col=$((box[mem_col]+1)) line=$((box[mem_line]+1)) width=$((box[mem_width]-2)) height=$((box[mem_height]-2)) From da37e5df9f98fe791e713a763e113af919570175 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Mon, 25 May 2020 16:47:31 +0200 Subject: [PATCH 29/52] Updated info fields for multi platform --- .github/ISSUE_TEMPLATE/bug_report.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 6bc053e..1e38b4a 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -24,11 +24,13 @@ assignees: aristocratos [If applicable, add screenshots to help explain your problem.] **Info (please complete the following information):** - - Bashtop version: - - Linux distribution and version: - - Terminal used: - - Font used: - - Bash version, "bash --version" (version 4.4 or above is required): + - Bashtop version: + - (Linux) Linux distribution and version: + - (Linux) Data collection type (/proc or psutil): + - (OSX/FreeBSD) Os release version: + - Terminal used: + - Font used: + - Bash version, "bash --version" (version 4.4 or above is required): - Locales: output of "locale -v" **Additional context** From f75bbe3203bfabf9153df9ffe4ee73e18c8e4a65 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Mon, 25 May 2020 16:48:58 +0200 Subject: [PATCH 30/52] v0.9.4 More OSX fixes --- CHANGELOG.md | 4 ++++ bashtop | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e216d6f..2eb17e0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## v0.9.4 + +* Fixed: Missing path for OSX df and correct swap usage reporting for OSX + ## v0.9.3 * Fixed: Resizing problems in iTerm2 diff --git a/bashtop b/bashtop index 76f0bcf..34d6078 100755 --- a/bashtop +++ b/bashtop @@ -66,7 +66,7 @@ banner=( "██╔══██╗██╔══██║╚════██║██╔══██║ ██║ ██║ ██║██╔═══╝ " "██████╔╝██║ ██║███████║██║ ██║ ██║ ╚██████╔╝██║ " "╚═════╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ") -declare version="0.9.3" +declare version="0.9.4" #* Get latest version of BashTOP from https://github.com/aristocratos/bashtop From ade02471d5225c142c2c850cafc8718a57724dff Mon Sep 17 00:00:00 2001 From: aristocratos Date: Mon, 25 May 2020 17:25:29 +0200 Subject: [PATCH 31/52] Added UTF-8 locale check --- bashtop | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/bashtop b/bashtop index 34d6078..41686c0 100755 --- a/bashtop +++ b/bashtop @@ -57,6 +57,21 @@ fi shopt -qu failglob nullglob shopt -qs extglob globasciiranges globstar +#* Check for UTF-8 locale and set LANG variable if not set +if [[ ! $LANG =~ UTF-8|utf-8 ]]; then + for set_lang in $(locale -a); do + if [[ $set_lang =~ UTF-8|utf-8 ]]; then + declare -x LANG="${set_lang}" + set_lang="found" + break + fi + done + if [[ $set_lang != "found" ]]; then + echo "ERROR: No UTF-8 locale found!" + exit 1 + fi +fi + declare -a banner banner_colors banner=( @@ -390,7 +405,7 @@ init_() { #? Collect needed information and set options before startig main loop if [[ -n $curled && $update_check == "true" ]]; then print -bg "#00" -fg "#30ff50" -r 1 -t "√" print -m $(( (tty_height/2-3)+stx++ )) 0 -bg "#00" -fg "#cc" -c -b "Checking for updates..." - if ! get_value -v git_version -ss "$(curl -m 4 --raw -r 0-3500 https://raw.githubusercontent.com/aristocratos/bashtop/master/bashtop 2>/dev/null)" -k "version=" -r "[^0-9.]"; then unset git_version; fi + if ! get_value -v git_version -ss "$(curl -m 4 --raw -r 0-5000 https://raw.githubusercontent.com/aristocratos/bashtop/master/bashtop 2>/dev/null)" -k "version=" -r "[^0-9.]"; then unset git_version; fi fi #* Add update notification to banner if new version is available From 611e78b5dc822049e8b141c687e1e8866d992f8f Mon Sep 17 00:00:00 2001 From: aristocratos Date: Tue, 26 May 2020 18:35:18 +0200 Subject: [PATCH 32/52] Fixed filter out zero sized disks and added some psutil error checks --- bashtop | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/bashtop b/bashtop index 41686c0..6cc416a 100755 --- a/bashtop +++ b/bashtop @@ -861,7 +861,7 @@ get_cpu_info() { local lscpu_var if [[ $use_psutil == true ]]; then if [[ -z ${cpu[threads]} || -z ${cpu[cores]} ]]; then - read cpu[threads] cpu[cores] < <(python3 -c "import psutil; print(psutil.cpu_count(logical=True), psutil.cpu_count(logical=False))") + read cpu[threads] cpu[cores] < <(python3 -c "import psutil; print(psutil.cpu_count(logical=True), psutil.cpu_count(logical=False))" 2>/dev/null) fi if [[ $system == "MacOS" ]]; then @@ -2168,10 +2168,11 @@ collect_mem() { #? Collect memory information from "/proc/meminfo" local i tmp value array mem_info height=$((box[mem_height]-2)) skip filter_value local -a mem_array swap_array available=("mem") + unset 'mem[total]' #* Get memory and swap information from "/proc/meminfo" or psutil and calculate percentages if [[ $use_psutil == true ]]; then - read mem[total] mem[free] mem[available] mem[cached] swap[total] swap[free] < <(python3 - </dev/null <>10, mem.free>>10, mem.available>>10, cmem, swap.total>>10, swap.free>>10) EOF ) + if [[ -z ${mem[total]} ]]; then return; fi if [[ -n $swap_on && -n ${swap[total]} ]] && ((swap[total]>0)); then swap[free_percent]=$((swap[free]*100/swap[total])) swap[used]=$((swap[total]-swap[free])) @@ -2239,7 +2241,7 @@ EOF fi for df_line in "${df_array[@]:1}"; do line_array=(${df_line}) - if ! is_int "${line_array[1]}"; then continue; fi + if ! is_int "${line_array[1]}" || ((line_array[1]<=0)); then continue; fi if [[ $system == "MacOS" && ( ${line_array[0]} == "devfs" || ${line_array[5]} == "/private/var/vm" ) ]]; then continue; fi @@ -2658,7 +2660,7 @@ collect_processes_psutil() { fi unset 'proc_array[@]' - readarray -t proc_array < <(python3 - </dev/null + readarray -t proc_array < <(python3 - 2>/dev/null <proc[pages])); then proc[page]=${proc[pages]}; fi @@ -2746,7 +2749,7 @@ EOF if [[ -z ${proc[detailed_name]} ]]; then local get_mem mem_string cmdline="" local -a det_array - readarray -t det_array < <(python3 - </dev/null </dev/null < Date: Tue, 26 May 2020 18:43:51 +0200 Subject: [PATCH 33/52] v0.9.5 Added UTF-8 check, psutil error checks and filter for zero sized disks --- CHANGELOG.md | 5 +++++ bashtop | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2eb17e0..abff396 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +## v0.9.5 + +* Added: UTF-8 locale check and automatic LANG variable set if not UTF-8 +* Fixed: Filter out zero sized disks and added some psutil error checks + ## v0.9.4 * Fixed: Missing path for OSX df and correct swap usage reporting for OSX diff --git a/bashtop b/bashtop index 6cc416a..13bf8ce 100755 --- a/bashtop +++ b/bashtop @@ -81,7 +81,7 @@ banner=( "██╔══██╗██╔══██║╚════██║██╔══██║ ██║ ██║ ██║██╔═══╝ " "██████╔╝██║ ██║███████║██║ ██║ ██║ ╚██████╔╝██║ " "╚═════╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ") -declare version="0.9.4" +declare version="0.9.5" #* Get latest version of BashTOP from https://github.com/aristocratos/bashtop From 37c709c49d9d6583cc372328aa87a45b732857f0 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Tue, 26 May 2020 21:44:54 +0200 Subject: [PATCH 34/52] v0.9.6 Fix for UTF-8 locale check --- CHANGELOG.md | 4 ++++ bashtop | 8 ++++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index abff396..d1d5f95 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## v0.9.6 + +* Fixed: UTF-8 locale check + ## v0.9.5 * Added: UTF-8 locale check and automatic LANG variable set if not UTF-8 diff --git a/bashtop b/bashtop index 13bf8ce..9a30a24 100755 --- a/bashtop +++ b/bashtop @@ -58,10 +58,10 @@ shopt -qu failglob nullglob shopt -qs extglob globasciiranges globstar #* Check for UTF-8 locale and set LANG variable if not set -if [[ ! $LANG =~ UTF-8|utf-8 ]]; then +if [[ ! $LANG =~ UTF-8 ]]; then for set_lang in $(locale -a); do - if [[ $set_lang =~ UTF-8|utf-8 ]]; then - declare -x LANG="${set_lang}" + if [[ $set_lang =~ utf8|UTF-8 ]]; then + declare -x LANG="${set_lang/utf8/UTF-8}" set_lang="found" break fi @@ -81,7 +81,7 @@ banner=( "██╔══██╗██╔══██║╚════██║██╔══██║ ██║ ██║ ██║██╔═══╝ " "██████╔╝██║ ██║███████║██║ ██║ ██║ ╚██████╔╝██║ " "╚═════╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ") -declare version="0.9.5" +declare version="0.9.6" #* Get latest version of BashTOP from https://github.com/aristocratos/bashtop From ae9a066dc1e23a41a2ba68b5ddd59fb13c126d57 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Fri, 29 May 2020 16:41:19 +0200 Subject: [PATCH 35/52] Changes to UTF-8 detection function --- bashtop | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/bashtop b/bashtop index 9a30a24..ea56984 100755 --- a/bashtop +++ b/bashtop @@ -59,17 +59,27 @@ shopt -qs extglob globasciiranges globstar #* Check for UTF-8 locale and set LANG variable if not set if [[ ! $LANG =~ UTF-8 ]]; then + if [[ -n $LANG && ${LANG::1} != "C" ]]; then old_lang="${LANG%.*}"; fi for set_lang in $(locale -a); do if [[ $set_lang =~ utf8|UTF-8 ]]; then - declare -x LANG="${set_lang/utf8/UTF-8}" - set_lang="found" - break + if [[ -n $old_lang && $set_lang =~ ${old_lang} ]]; then + declare -x LANG="${set_lang/utf8/UTF-8}" + set_lang_search="found" + break + elif [[ -z $first_lang ]]; then + first_lang="${set_lang/utf8/UTF-8}" + set_lang_first="found" + fi + if [[ -z $old_lang ]]; then break; fi fi done - if [[ $set_lang != "found" ]]; then + if [[ $set_lang_search != "found" && $set_lang_first != "found" ]]; then echo "ERROR: No UTF-8 locale found!" exit 1 + elif [[ $set_lang_search != "found" ]]; then + declare -x LANG="${first_lang/utf8/UTF-8}" fi + unset old_lang set_lang first_lang set_lang_search set_lang_first fi declare -a banner banner_colors @@ -2701,7 +2711,7 @@ for p in sorted(psutil.process_iter(['pid', 'name', 'cmdline', 'num_threads', 'u EOF ) - if [[ -z ${proc_array[0]} ]]; then return; fi + if [[ -z ${proc_array[0]} ]]; then unset 'old_procs[@]'; return; fi proc_array[0]="${proc_array[0]/ ${selected}/${symbol}${selected}}" proc[pages]=$(( (${#proc_array[@]}-1)/(height-3)+1 )) if ((proc[page]>proc[pages])); then proc[page]=${proc[pages]}; fi From fe81a40fe7dc1e7dfbc0130b2bd0d6dcce4d484f Mon Sep 17 00:00:00 2001 From: aristocratos Date: Fri, 29 May 2020 23:36:00 +0200 Subject: [PATCH 36/52] v0.9.7 Fix for default language in UTF-8 locale check --- CHANGELOG.md | 4 ++++ bashtop | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d1d5f95..4f87d3c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## v0.9.7 + +* Changed: UTF-8 locale check, try to find UTF-8 for current language if LANG is set but not with "UTF-8" suffix + ## v0.9.6 * Fixed: UTF-8 locale check diff --git a/bashtop b/bashtop index ea56984..ee4c6fe 100755 --- a/bashtop +++ b/bashtop @@ -91,7 +91,7 @@ banner=( "██╔══██╗██╔══██║╚════██║██╔══██║ ██║ ██║ ██║██╔═══╝ " "██████╔╝██║ ██║███████║██║ ██║ ██║ ╚██████╔╝██║ " "╚═════╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ") -declare version="0.9.6" +declare version="0.9.7" #* Get latest version of BashTOP from https://github.com/aristocratos/bashtop From cd878c2cb551572f614b4feebeb0de01a3b1daf9 Mon Sep 17 00:00:00 2001 From: Maciek Swiech Date: Sun, 31 May 2020 19:50:36 -0600 Subject: [PATCH 37/52] added bats --- .gitmodules | 9 +++++++++ bashtop | 4 ++++ test/bats | 8 ++++++++ test/libs/bats | 1 + test/libs/bats-assert | 1 + test/libs/bats-support | 1 + 6 files changed, 24 insertions(+) create mode 100644 .gitmodules create mode 100644 test/bats create mode 160000 test/libs/bats create mode 160000 test/libs/bats-assert create mode 160000 test/libs/bats-support diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..dedb624 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,9 @@ +[submodule "test/libs/bats"] + path = test/libs/bats + url = https://github.com/sstephenson/bats +[submodule "test/libs/bats-assert"] + path = test/libs/bats-assert + url = https://github.com/ztombol/bats-assert +[submodule "test/libs/bats-support"] + path = test/libs/bats-support + url = https://github.com/ztombol/bats-support diff --git a/bashtop b/bashtop index ee4c6fe..2f07e3c 100755 --- a/bashtop +++ b/bashtop @@ -4822,6 +4822,10 @@ else exec 2>/dev/null fi + +#* if we have been sourced by another shell, quit. Allows sourcing only function definition. +[[ "${#BASH_SOURCE[@]}" -gt 1 ]] && { return 0; } + #* Call init function init_ diff --git a/test/bats b/test/bats new file mode 100644 index 0000000..fbb4b89 --- /dev/null +++ b/test/bats @@ -0,0 +1,8 @@ +#!/usr/bin/env bats + +source bashtop + +@test "im a toy" { + result=$(echo hello) + [ "$result" = "hello" ] +} diff --git a/test/libs/bats b/test/libs/bats new file mode 160000 index 0000000..0360811 --- /dev/null +++ b/test/libs/bats @@ -0,0 +1 @@ +Subproject commit 03608115df2071fff4eaaff1605768c275e5f81f diff --git a/test/libs/bats-assert b/test/libs/bats-assert new file mode 160000 index 0000000..9f88b42 --- /dev/null +++ b/test/libs/bats-assert @@ -0,0 +1 @@ +Subproject commit 9f88b4207da750093baabc4e3f41bf68f0dd3630 diff --git a/test/libs/bats-support b/test/libs/bats-support new file mode 160000 index 0000000..004e707 --- /dev/null +++ b/test/libs/bats-support @@ -0,0 +1 @@ +Subproject commit 004e707638eedd62e0481e8cdc9223ad471f12ee From 8f4a00f7271a1a10de2380b571cc68329802cfa2 Mon Sep 17 00:00:00 2001 From: Maciek Swiech Date: Sun, 31 May 2020 22:31:09 -0600 Subject: [PATCH 38/52] adding tests and travis yml --- .travis.yml | 10 ++++++++++ test.sh | 3 +++ test/basic_test.bats | 17 +++++++++++++++++ test/bats | 8 -------- test/test_helper.bash | 1 + 5 files changed, 31 insertions(+), 8 deletions(-) create mode 100644 .travis.yml create mode 100755 test.sh create mode 100644 test/basic_test.bats delete mode 100644 test/bats create mode 100644 test/test_helper.bash diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..07618fa --- /dev/null +++ b/.travis.yml @@ -0,0 +1,10 @@ +udo: false +language: bash +addons: + apt: + sources: + - sourceline: 'ppa:duggan/bats' + packages: + - bats + - bc +script: bats ./test/*.bats \ No newline at end of file diff --git a/test.sh b/test.sh new file mode 100755 index 0000000..6343258 --- /dev/null +++ b/test.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +./test/libs/bats/bin/bats test/*.bats \ No newline at end of file diff --git a/test/basic_test.bats b/test/basic_test.bats new file mode 100644 index 0000000..e6b95a4 --- /dev/null +++ b/test/basic_test.bats @@ -0,0 +1,17 @@ +#!/usr/bin/env bats + +load 'libs/bats-support/load' +load 'libs/bats-assert/load' + +load test_helper + +@test "sourcing works, by checking if $system is set" { + run echo $system + refute_output "" +} + +@test "#get_themes populates themes" { + get_themes + assert_success + assert [ ${#themes[@]} -gt 0 ] +} \ No newline at end of file diff --git a/test/bats b/test/bats deleted file mode 100644 index fbb4b89..0000000 --- a/test/bats +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env bats - -source bashtop - -@test "im a toy" { - result=$(echo hello) - [ "$result" = "hello" ] -} diff --git a/test/test_helper.bash b/test/test_helper.bash new file mode 100644 index 0000000..f0d1c88 --- /dev/null +++ b/test/test_helper.bash @@ -0,0 +1 @@ +source bashtop \ No newline at end of file From 0929c24f8ff9e009d44e468a8385cf5fb0a45ea8 Mon Sep 17 00:00:00 2001 From: Maciek Swiech Date: Mon, 1 Jun 2020 10:44:17 -0600 Subject: [PATCH 39/52] use test script --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 07618fa..3dd6bcd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,4 +7,4 @@ addons: packages: - bats - bc -script: bats ./test/*.bats \ No newline at end of file +script: ./test.sh \ No newline at end of file From eadc5435e6994c9e925c0f344e8c2d6d65e5704e Mon Sep 17 00:00:00 2001 From: Maciek Swiech Date: Mon, 1 Jun 2020 10:48:36 -0600 Subject: [PATCH 40/52] triggering travis build --- test/basic_test.bats | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/basic_test.bats b/test/basic_test.bats index e6b95a4..c00e185 100644 --- a/test/basic_test.bats +++ b/test/basic_test.bats @@ -5,7 +5,7 @@ load 'libs/bats-assert/load' load test_helper -@test "sourcing works, by checking if $system is set" { +@test "Sourcing works, by checking if $system is set" { run echo $system refute_output "" } From a537c1ea74a685422bf15a169b84d8d3b515da30 Mon Sep 17 00:00:00 2001 From: Maciek Swiech Date: Mon, 1 Jun 2020 10:54:28 -0600 Subject: [PATCH 41/52] pull bash from apt --- .travis.yml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 3dd6bcd..55eade3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,10 +1,11 @@ -udo: false +sudo: false language: bash addons: apt: sources: - - sourceline: 'ppa:duggan/bats' + - sourceline: 'ppa:duggan/bats' packages: - - bats - - bc + - bash + - bats + - bc script: ./test.sh \ No newline at end of file From fed9ca8624f83c6cbe05141b0286965930de20f9 Mon Sep 17 00:00:00 2001 From: Maciek Swiech Date: Mon, 1 Jun 2020 10:56:56 -0600 Subject: [PATCH 42/52] pull docker bash instead --- .travis.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 55eade3..05a00d4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,11 +1,14 @@ sudo: false language: bash +env: + - BASH=5.0.3 addons: apt: sources: - sourceline: 'ppa:duggan/bats' packages: - - bash - bats - bc +before_script: + - docker pull bash:$BASH script: ./test.sh \ No newline at end of file From c84c770047fb81eebb667a4f3f0bc032b82a8735 Mon Sep 17 00:00:00 2001 From: Maciek Swiech Date: Mon, 1 Jun 2020 11:04:51 -0600 Subject: [PATCH 43/52] move to newer ubuntu container base --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 05a00d4..deb4a91 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,6 @@ sudo: false language: bash +dist: bionic env: - BASH=5.0.3 addons: @@ -9,6 +10,4 @@ addons: packages: - bats - bc -before_script: - - docker pull bash:$BASH script: ./test.sh \ No newline at end of file From 0e2243f7bb4afc7eb33c4e75f07897502359825b Mon Sep 17 00:00:00 2001 From: Maciek Swiech Date: Mon, 1 Jun 2020 11:05:04 -0600 Subject: [PATCH 44/52] rm --- .travis.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index deb4a91..1b2d8cd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,6 @@ sudo: false language: bash dist: bionic -env: - - BASH=5.0.3 addons: apt: sources: From e58e56446d8f9ded68da6f31253a126de47cdb75 Mon Sep 17 00:00:00 2001 From: Maciek Swiech Date: Mon, 1 Jun 2020 11:20:15 -0600 Subject: [PATCH 45/52] moving to python container --- .travis.yml | 7 ++++++- requirements.txt | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 requirements.txt diff --git a/.travis.yml b/.travis.yml index 1b2d8cd..bf35fb2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,7 @@ sudo: false -language: bash +language: python +python: + - "3.6" dist: bionic addons: apt: @@ -8,4 +10,7 @@ addons: packages: - bats - bc +# command to install dependencies +install: + - pip install -r requirements.txt script: ./test.sh \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..a87aaef --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +psutil==5.7.0 \ No newline at end of file From 4f19d627d67f04c709905e24e9590c559cd1af4d Mon Sep 17 00:00:00 2001 From: Maciek Swiech Date: Mon, 1 Jun 2020 11:28:25 -0600 Subject: [PATCH 46/52] test test failure for travis --- test/basic_test.bats | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/basic_test.bats b/test/basic_test.bats index c00e185..9a263b9 100644 --- a/test/basic_test.bats +++ b/test/basic_test.bats @@ -5,9 +5,9 @@ load 'libs/bats-assert/load' load test_helper -@test "Sourcing works, by checking if $system is set" { +@test "Sourcing works, by checking if \$system is set" { run echo $system - refute_output "" + refute_output "MacOS" } @test "#get_themes populates themes" { From 93d5ad4e6b1869e5cb34b0aacd2539fcda4b692f Mon Sep 17 00:00:00 2001 From: Maciek Swiech Date: Mon, 1 Jun 2020 11:30:53 -0600 Subject: [PATCH 47/52] but do it correctly --- test/basic_test.bats | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/basic_test.bats b/test/basic_test.bats index 9a263b9..5ea4006 100644 --- a/test/basic_test.bats +++ b/test/basic_test.bats @@ -7,7 +7,7 @@ load test_helper @test "Sourcing works, by checking if \$system is set" { run echo $system - refute_output "MacOS" + assert_output "" } @test "#get_themes populates themes" { From 9c2a25f248a240742b354760531d9942c7a7398f Mon Sep 17 00:00:00 2001 From: Maciek Swiech Date: Mon, 1 Jun 2020 11:33:05 -0600 Subject: [PATCH 48/52] back to good state --- test/basic_test.bats | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/basic_test.bats b/test/basic_test.bats index 5ea4006..2b157d9 100644 --- a/test/basic_test.bats +++ b/test/basic_test.bats @@ -7,7 +7,7 @@ load test_helper @test "Sourcing works, by checking if \$system is set" { run echo $system - assert_output "" + refute_output "" } @test "#get_themes populates themes" { From 3a35afdb4f1b49d1e635c5275c18c1ebbb7b35a3 Mon Sep 17 00:00:00 2001 From: Maciek Swiech Date: Mon, 1 Jun 2020 11:37:44 -0600 Subject: [PATCH 49/52] dont install bats, use one from submodules --- .travis.yml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/.travis.yml b/.travis.yml index bf35fb2..3912c12 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,14 +3,6 @@ language: python python: - "3.6" dist: bionic -addons: - apt: - sources: - - sourceline: 'ppa:duggan/bats' - packages: - - bats - - bc -# command to install dependencies install: - pip install -r requirements.txt script: ./test.sh \ No newline at end of file From b658b8cf232c1c04830bcd6a3dd6a40486da8fb2 Mon Sep 17 00:00:00 2001 From: Maciek Swiech Date: Mon, 1 Jun 2020 11:40:43 -0600 Subject: [PATCH 50/52] dont use deprecated sudo flag, specify os --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 3912c12..e762dde 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,5 @@ -sudo: false +# travis does not offer python container for OSX or Windows, not sure if we can get automated testing? +os: linux language: python python: - "3.6" From a7acb014689ae9007dfb2e046c47cfa0232d2205 Mon Sep 17 00:00:00 2001 From: Maciek Swiech Date: Mon, 1 Jun 2020 11:45:11 -0600 Subject: [PATCH 51/52] newline at EOF --- .travis.yml | 2 +- requirements.txt | 2 +- test.sh | 2 +- test/basic_test.bats | 2 +- test/test_helper.bash | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index e762dde..b589ccf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,4 +6,4 @@ python: dist: bionic install: - pip install -r requirements.txt -script: ./test.sh \ No newline at end of file +script: ./test.sh diff --git a/requirements.txt b/requirements.txt index a87aaef..24156d6 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1 @@ -psutil==5.7.0 \ No newline at end of file +psutil==5.7.0 diff --git a/test.sh b/test.sh index 6343258..958110a 100755 --- a/test.sh +++ b/test.sh @@ -1,3 +1,3 @@ #!/usr/bin/env bash -./test/libs/bats/bin/bats test/*.bats \ No newline at end of file +./test/libs/bats/bin/bats test/*.bats diff --git a/test/basic_test.bats b/test/basic_test.bats index 2b157d9..e159b6f 100644 --- a/test/basic_test.bats +++ b/test/basic_test.bats @@ -14,4 +14,4 @@ load test_helper get_themes assert_success assert [ ${#themes[@]} -gt 0 ] -} \ No newline at end of file +} diff --git a/test/test_helper.bash b/test/test_helper.bash index f0d1c88..d173159 100644 --- a/test/test_helper.bash +++ b/test/test_helper.bash @@ -1 +1 @@ -source bashtop \ No newline at end of file +source bashtop From 201baa23edb472debf7d1da18791ebc65f227d43 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Mon, 1 Jun 2020 20:14:57 +0200 Subject: [PATCH 52/52] Added travis-ci build status --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index dbf5d99..68c731f 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,7 @@ ![Bash](https://img.shields.io/badge/Bash-v4.4%5E-green?logo=GNU%20bash) ![Python](https://img.shields.io/badge/Python-v3.6%5E-orange?logo=python) ![bashtop_version](https://img.shields.io/github/v/tag/aristocratos/bashtop?label=version) +[![Build Status](https://travis-ci.com/aristocratos/bashtop.svg?branch=master)](https://travis-ci.com/aristocratos/bashtop) [![Donate](https://img.shields.io/badge/-Donate-yellow?logo=paypal)](https://paypal.me/aristocratos) [![Sponsor](https://img.shields.io/badge/-Sponsor-red?logo=github)](https://github.com/sponsors/aristocratos) [![Coffee](https://img.shields.io/badge/-Buy%20me%20a%20Coffee-grey?logo=Ko-fi)](https://ko-fi.com/aristocratos)