version change and readme update

pull/19/head
aristocratos 2020-04-05 20:29:12 +02:00
parent 1820d44dcc
commit 720d7edb92
2 changed files with 176 additions and 168 deletions

223
README.md
View File

@ -1,194 +1,93 @@
# bashtop # ![bashtop](logo-t.png)
**Version:** 0.6.2 **Usage:** Linux resource monitor
**Usage:** Tmp **Language:** Bash
**Language:** Bash & Python
## Description ## Description
Internet speeds are tested against random servers from speedtest.net at an timed interval (defined by user). Resource monitor that shows usage and stats for processor, memory, disks, network and processes.
If slow speed (defined by user) is detected, then runs a number of download and upload test with optional route tests to servers and writes to a logfile.
## Screenshots
Main UI with graph on.
![Screenshot 1]()
## Features ## Features
* Function for checking current bandwidth usage to block false positives. Can optionally collect bandwidth usage from a router running linux with a ssh server enabled. * Easy to use, with a game inspired menu system.
* Scrollable graph showing speeds over time. * Fast and responsive UI with UP, DOWN keys process selection.
* All output in the UI is also scrollabe with UP, DOWN, PAGE_UP, PAGE_DOWN, HOME, END keys working as you would expect. * Function for showing detailed stats for selected process.
* Option to have the timer reset on any mouse or keyboard activity in XServer. * Ability to filter processes.
* Option to have the timer auto pause when monitor is on and unpause when monitor is off. * Easy switching between sorting options.
* Unit used can be switched between Mbits and MB/s. * Send SIGTERM, SIGKILL, SIGINT to selected process.
* Function for splitting log files at a defined size, old log files can also be automatically compressed. * UI menu for changing all config file options.
* Auto scaling graph for network usage.
## Screenshots
Main UI showing details for a selected process.
![Screenshot 1](main.png)
Main menu.
![Screenshot 2](menu.png)
Options menu.
![Screenshot 3](options.png)
## Configurability ## Configurability
Config files stored in "$HOME/.config/spdtest" folder All options changeable from within UI.
Config files stored in "$HOME/.config/bashtop" folder
#### spdtest.cfg: (auto generated if not found) #### bashtop.cfg: (auto generated if not found)
```bash ```bash
net_device="auto" #* Network interface to get current speed from, set to "auto" to get default interface from "ip route" command #? Config file for bashtop v. 0.6.5
unit="megabit" #* Default speed value to use, valid values are "megabit" and "megabyte"
slowspeed="30" #* Download speed in unit defined above that triggers more tests, recommended set to 10%-40% of your max speed
numservers="30" #* How many of the closest servers to get from speedtest.net, used as random pool of servers to test against
slowretry="1" #* When speed is below slowspeed, how many retries of random servers before running full tests
max_err_retry="3" #* Max servers to test if an error is encountered in slowcheck
numslowservers="8" #* How many of the closest servers from list to test if slow speed has been detected, tests all if not set
precheck="true" #* Check current bandwidth usage before slowcheck, blocks if speed is higher then values set below
precheck_samplet="5" #* Time in seconds to sample bandwidth usage, defaults to 5 if not set
precheck_down="50" #* Download speed in unit defined above that blocks slowcheck
precheck_up="50" #* Upload speed in unit defined above that blocks slowcheck
precheck_ssh_host="192.168.1.1" #* If set, precheck will fetch data from /proc/net/dev over SSH, for example from a router running linux
#* remote machine needs to have: "/proc/net/dev" and be able to run commands "ip route" and "grep"
#* copy SSH keys to remote machine if you don't want to be asked for password at start, guide: https://www.ssh.com/ssh/copy-id
precheck_ssh_user="admin" #* Username for ssh connection
precheck_ssh_nd="auto" #* Network interface on remote machine to get speeds from, set to "auto" if unsure
waittime="00:20:00" #* Default wait timer between slowchecks, format: "HH:MM:SS"
slowwait="00:10:00" #* Time between tests when slow speed has been detected, uses wait timer if unset, format: "HH:MM:SS"
idle="false" #* If "true", resets timer if keyboard or mouse activity is detected in XServer
# idletimer="00:30:00" #* If set and idle="true", the script uses this timer until first test, then uses standard wait time,
#* any X Server activity resets back to idletimer, format: "HH:MM:SS"
displaypause="false" #* If "true" automatically pauses timer when display is on, unpauses when off, overrides idle="true" if set, needs xset to work
paused="false" #* If "true", the timer is paused at startup, ignored if displaypause="true"
startuptest="false" #* If "true" and paused="false", tests speed at startup before timer starts
main_menu_start="shown" #* The status of the main menu at start, possible values: "shown", "hidden"
graph_start="shown" #* The status of the speed graph at start, possible values: "shown", "hidden"
loglevel="2" #* 0 : No logging
#* 1 : Log only when slow speed has been detected
#* 2 : Also log slow speed check
#* 3 : Also log server updates
#* 4 : Log all including forced tests
logdir="$HOME/spdtest-logs" #* Logfile save directory
quiet_start="true" #* If "true", don't print serverlist and routelist at startup
maxlogsize="1024" #* Max logsize (in kilobytes) before log is split
logcompress="gzip" #* Command for compressing logs, only log splits beyond the last split is compressed, disabled if not set
# custom_log="" #* Custom logfile (full path), if a custom logfile is set log splitting is disabled
max_buffer="1000" #* Max number of lines to buffer in internal scroll buffer
buffer_save="true" #* Save buffer to disk on exit and restore on start
mtr="true" #* Set "false" to disable route testing with mtr, automatically set to "false" if mtr is not found in PATH
mtr_internal="true" #* Use hosts from full test with speeds below $slowspeed in mtr test
mtr_internal_ok="false" #* Use hosts from full test with speeds above $slowspeed in mtr test
# mtr_internal_max="" #* Set max hosts to add from full test
mtr_external="false" #* Use hosts from route.cfg, see route.cfg.sample for formatting
mtrpings="25" #* Number of pings sent with mtr
testonly="false" #* If "true", never enter UI mode, always run full tests and quit
testnum="1" #* Number of times to loop full tests in testonly mode
ookla_speedtest="speedtest" #* Command or full path to official speedtest client #* Update time in milliseconds, increases automatically if set below internal loops processing time, recommended 2000 ms or above for better sample times for graphs
update_ms="2500"
trace_errors="true" #* In event of error print line number of offending command to $HOME/.config/spdtest/errors #* Processes sorting, "pid" "program" "arguments" "threads" "user" "memory" "cpu lazy" "cpu responsive"
#* "cpu lazy" upates sorting over time, "cpu responsive" updates sorting directly at a cpu usage cost
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_temp="true"
#* Draw a clock at top of screen, formatting according to strftime, empty string to disable
draw_clock="%X"
#* Custom cpu model name, empty string to disable
custom_cpu_name=""
#* Enable error logging to "$HOME/.config/bashtop/error.log", "true" or "false"
error_logging="true"
``` ```
#### route.cfg.sample: (rename to route.cfg to use additional hosts in route test) #### Command line options: (not yet implemented)
```bash
#? List of routes to test with mtr
#? Format:
#? routelista+=("host")
#? routelistdesc["host"]=("Name")
#? routelistport["host"]=("port") 'Set port to "auto" if you don't want to set a custom port!'
routelista+=("google.com")
routelistdesc["google.com"]="Google"
routelistport["google.com"]="auto"
routelista+=("reddit.com")
routelistdesc["reddit.com"]="Reddit"
routelistport["reddit.com"]="auto"
routelista+=("twitch.tv")
routelistdesc["twitch.tv"]="Twitch"
routelistport["twitch.tv"]="auto"
routelista+=("amazon.com")
routelistdesc["amazon.com"]="Amazon"
routelistport["amazon.com"]="auto"
```
#### Command line options: (to be updated)
``` ```
USAGE: ./spdtest.sh [OPTIONS] USAGE: bashtop
OPTIONS:
-t, --test [num] Runs full test 1 or <x> number of times and quits
-u, --unit megabit/megabyte Which unit to show speed in, [default: megabit]
-s, --slow-speed speed Defines what speed in defined unit that will trigger more tests
-n, --num-servers num How many of the closest servers to get from speedtest.net
-i, --interface name Network interface being used [default: auto]
-l, --loglevel 0-3 0 No logging
1 Log only when slow speed has been detected
2 Also log slow speed check and server update
3 Log all including forced tests
-lf, --log-file file Full path to custom logfile, no log rotation is done on custom logfiles
-p, --paused Sets timer to paused state at startup
-wt, --wait-time HH:MM:SS Time between tests when NO slowdown is detected [default: 00:10:00]
-st, --slow-time HH:MM:SS Time between tests when slowdown has been detected, uses wait timer if unset
-x, --x-reset [HH:MM:SS] Reset timer if keyboard or mouse activity is detected in X Server
If HH:MM:SS is included, the script uses this timer until first test, then uses
standard wait time, any activity resets to idle timer [default: unset]
-d, --display-pause Automatically pauses timer when display is on, unpauses when off
-gs, --gen-server-cfg num Writes <x> number of the closest servers to "server.cfg" and quits
Servers aren't updated automatically at start if "server.cfg" exists
-sc, --server-config file Reads server config from <file> [default: server.cfg]
If used in combination with -gs a new file is created
-h, --help Shows help information
CONFIG:
Note: All config files are stored in: $HOME/.config/spdtest
spdtest.cfg Automatically created with default values if removed
[server.cfg] Stores server id's to use with speedtest, delete to refresh servers on start
[route.cfg] Additional hosts to test with mtr, see route.cfg.sample for formatting
LOG:
Logfile location can be changed in config file
Currently: $HOME/spdtest-logs
``` ```
## Compability
Should work on most modern linux distributions.
## Dependencies ## Dependencies
**bash** (v4.4 or later) Script functionality might brake with earlier versions. **bash** (v4.4 or later) Script functionality will most probably brake with earlier versions.
Bash version 5 is higly recommended for a
**[Python 3](https://www.python.org/downloads)** (v3.7 or later) Needed for speedtest-cli, grc and getIdle.
**[speedtest](https://www.speedtest.net/apps/cli)** Official speedtest client from Ookla, needs to be in path or defined in config.
**[jq](https://stedolan.github.io/jq/)** Needed for json parsing.
## Included
**[speedtest-cli](https://github.com/sivel/speedtest-cli)** Used to get serverlist, since official speedtest client from Ookla is limited to 10 servers.
Modified and heavily stripped down, based on version 2.1.2. Python code included in the script.
**[grc](https://github.com/garabik/grc)** For making text output in the UI pretty.
Modified version of grcat. Python code included in the script.
**getIdle** Get XServer idle time. Python code included in script.
## Optionals
**[mtr](https://github.com/traviscross/mtr)** Needed if you want to check routes to slow servers.
**[less](http://www.greenwoodsoftware.com/less/)** Needed if you want option to view logfile from UI.
## TODO ## TODO
- [ ] TODO Fix argument parsing and error messages - [ ] TODO Add command line argument parsing.
- [ ] TODO Change slowtest to multiple servers and compare results - [ ] TODO Miscellaneous optimizations and code cleanup
- [ ] TODO fix wrong keypress in inputwait, esc codes etc
- [ ] TODO fix up README.md
- [x] TODO extern config and save to config?
- [x] TODO ssh controlmaster, server, client for precheck_speed
- [ ] TODO buffer logview
- [ ] TODO route test menu, choose host to test
- [ ] TODO windows: help, options, route
- [x] TODO plot speedgraphs overtime in UI
- [ ] TODO stat file
- [ ] Everything else...
## LICENSE ## LICENSE
[Apache License 2.0](LICENSE) [Apache License 2.0](LICENSE)

119
bashtop
View File

@ -21,7 +21,7 @@ banner=(
"██╔══██╗██╔══██║╚════██║██╔══██║ ██║ ██║ ██║██╔═══╝ " "██╔══██╗██╔══██║╚════██║██╔══██║ ██║ ██║ ██║██╔═══╝ "
"██████╔╝██║ ██║███████║██║ ██║ ██║ ╚██████╔╝██║ " "██████╔╝██║ ██║███████║██║ ██║ ██║ ╚██████╔╝██║ "
"╚═════╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ") "╚═════╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ")
declare version="0.6.5" declare version="0.6.8"
declare banner_width=${#banner[0]} declare banner_width=${#banner[0]}
banner_colors=("#E62525" "#CD2121" "#B31D1D" "#9A1919" "#801414") banner_colors=("#E62525" "#CD2121" "#B31D1D" "#9A1919" "#801414")
@ -93,7 +93,7 @@ declare -a sorting=( "pid" "program" "arguments" "threads" "user" "memory" "cpu
declare -a pid_history detail_graph detail_history detail_mem_history declare -a pid_history detail_graph detail_history detail_mem_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 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 declare no_epoch proc_det proc_misc2 sleeping=0 detail_mem_graph proc_det2 proc_out
declare esc_character tab backspace update_sec sleepy late_update skip_process_draw winches declare esc_character tab backspace update_sec sleepy late_update skip_process_draw winches quitting
declare -a disks_free disks_total disks_name disks_free_percent saved_key declare -a disks_free disks_total disks_name disks_free_percent saved_key
printf -v esc_character "\u1b" printf -v esc_character "\u1b"
printf -v tab "\u09" printf -v tab "\u09"
@ -2878,9 +2878,110 @@ options_() { #? Shows the options overlay
elif [[ -n ${pause_screen} ]]; then unpause_; draw_update_string; fi elif [[ -n ${pause_screen} ]]; then unpause_; draw_update_string; fi
} }
killer_() { #? Kill process with selected signal
local kill_op="$1" kill_pid="$2" killer_out killer_box col line program keypress selected selected_int=0 sig confirmed=0 option killer_pause status status_fg msg
local -a options=("yes" "no")
if ! program="$(ps -o comm --no-header -p ${kill_pid})"; then return; fi
case $kill_op in
t|T) kill_op="terminate"; sig="SIGTERM" ;;
k|K) kill_op="kill"; sig="SIGKILL" ;;
i|I) kill_op="interrupt"; sig="SIGINT" ;;
esac
until false; do
#* Put program to sleep if caught ctrl-z
if ((sleepy==1)); then sleep_; fi
draw_clock
pause_ killer_pause
if [[ -z $killer_box ]]; then
col=$((tty_width/2-15)); line=$((tty_height/2-4)); y=1
unset redraw killer_box
create_box -v killer_box -w 40 -h 9 -l $line -c $((col++)) -fill -lc "#923535" -title "${kill_op}"
fi
if ((confirmed==0)); then
selected="${options[selected_int]}"
print -v killer_out -m $((line+2)) $col -fg ee -b -jc 38 -t "${kill_op^} ${program::20}?" -m $((line+4)) $((col+3))
for option in "${options[@]}"; do
if [[ $option == "${selected}" ]]; then print -v killer_out -bg "#923535"; fi
print -v killer_out -fg cc -b -r 5 -t "[ ${option^} ]" -rs
done
elif ((confirmed==1)); then
selected="ok"
print -v killer_out -m $((line+2)) $col -fg ee -b -jc 38 -t "Sending signal ${sig} to pid ${kill_pid}!"
print -v killer_out -m $((line+4)) $col -fg ${status_fg} -jc 38 -t "${status^}!" -m $((line+6)) $col
if [[ -n $msg ]]; then print -v killer_out -m $((line+5)) $col -fg ee -jc 38 -t "${msg}" -m $((line+7)) $col; fi
print -v killer_out -fg cc -bg "#923535" -b -r 15 -t "[ Ok ]" -rs
fi
echo -en "${killer_pause}${killer_box}${killer_out}"
unset killer_out draw_out
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
get_key -v keypress -w ${wait_string}
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
case "$keypress" in
right|shift_tab) if ((selected_int>0)); then ((selected_int--)); else selected_int=$((${#options[@]}-1)); fi ;;
left|tab) if ((selected_int<${#options[@]}-1)); then ((++selected_int)); else selected_int=0; fi ;;
enter)
case "$selected" in
yes) confirmed=1 ;;
no|ok) confirmed=-1 ;;
esac
;;
q|Q) quit_ ;;
esac
if ((confirmed<0)); then
unpause_
break
elif ((confirmed>0)) && [[ -z $status ]]; then
if kill -${sig} ${kill_pid} >/dev/null 2>&1; then
status="success"
status_fg="30ee20"
else
if ! ps -p ${kill_pid} >/dev/null 2>&1; then
msg="Process not running."
elif [[ $UID != 0 ]]; then
msg="Try restarting with sudo."
else
msg="Unknown error."
fi
status="failed"; status_fg="ee3020"; fi
fi
if ((time_left==0)); then get_ms timestamp_start; unset draw_out; collect_and_draw; fi
if ((resized>=5)); then resized=0; fi
done
}
get_key() { #? Get one key from standard input and translate key code to readable format get_key() { #? Get one key from standard input and translate key code to readable format
local key key_out wait_time esc ext_out save local key key_out wait_time esc ext_out save
if ((quitting==1)); then quit_; fi
until (($#==0)); do until (($#==0)); do
case "$1" in case "$1" in
-v|-variable) local -n key_out=$2; ext_out=1; shift;; #* Output variable -v|-variable) local -n key_out=$2; ext_out=1; shift;; #* Output variable
@ -3075,6 +3176,14 @@ process_input() { #? Process keypresses for main ui
unset input_to_filter filter unset input_to_filter filter
filter_change=1 filter_change=1
fi fi
;;
t|T|k|K|i|I)
if [[ ${proc[selected]} -gt 0 ]]; then
killer_ "$keypress" "${proc[selected_pid]}"
elif [[ ${proc[detailed]} -eq 1 && -z ${proc[detailed_killed]} ]]; then
killer_ "$keypress" "${proc[detailed_pid]}"
fi
;;
# *) # *)
# #if [[ $keypress == "" ]]; then keypress="enter"; fi # #if [[ $keypress == "" ]]; then keypress="enter"; fi
# printf -v letter_hex '%X\n' "'$keypress" # printf -v letter_hex '%X\n' "'$keypress"
@ -3253,8 +3362,8 @@ else
fi fi
#* Set up traps for ctrl-c, soft kill, window resize and resume from ctrl-z #* Set up traps for ctrl-c, soft kill, window resize and resume from ctrl-z
trap 'quit_' SIGINT SIGQUIT SIGTERM trap 'quitting=1; time_left=0' SIGINT SIGQUIT SIGTERM
trap 'resized=1' SIGWINCH trap 'resized=1; time_left=0' SIGWINCH
trap 'sleepy=1; time_left=0' SIGTSTP trap 'sleepy=1; time_left=0' SIGTSTP
trap 'resume_' SIGCONT trap 'resume_' SIGCONT
@ -3263,7 +3372,7 @@ trap 'resume_' SIGCONT
#* Set up error logging to file if enabled #* Set up error logging to file if enabled
if [[ $error_logging == true ]]; then if [[ $error_logging == true ]]; then
set -o errtrace set -o errtrace
trap traperr ERR trap 'traperr' ERR
( echo " " ; echo "New instance of $0 Pid: $$" ) >> "${config_dir}/error.log" ( echo " " ; echo "New instance of $0 Pid: $$" ) >> "${config_dir}/error.log"
exec 2>>"${config_dir}/error.log" exec 2>>"${config_dir}/error.log"
# exec 19>"${config_dir}/tracing.log" # exec 19>"${config_dir}/tracing.log"