Добавлены конфиги tmux и zsh

This commit is contained in:
eKa
2019-09-18 00:17:47 +05:00
commit 7d0a7691c6
882 changed files with 67305 additions and 0 deletions

View File

@@ -0,0 +1,21 @@
The MIT License
Copyright (c) 2017 Alexey Samoshkin
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -0,0 +1,372 @@
Tmux sysstat plugin
===================
Allow to print CPU usage, memory & swap, load average, net I/O metrics in Tmux status bar
![intro](/screenshots/intro.png)
You might checkout [tmux-config](https://github.com/samoshkin/tmux-config) repo to see this plugin in action.
Features
--------
- CPU usage
- Memory available/free, used, total (KiB,MiB,GiB), free/used %
- Swap used, free, total, free/used %
- load average for last 1,5,15 minutes
- configurable thresholds (low, medium, stress) with custom colors
- tweak each metric output using templates (e.g, 'used 10% out of 16G')
- configurable size scale (K,M,G)
- OSX, Linux support
- [ ] **TODO:** network I/O metric support
Tested on: OS X El Capitan 10.11.5, Ubuntu 14 LTS, CentOS 7, FreeBSD 11.1.
Installation
------------
Best installed through [Tmux Plugin Manager](https://github.com/tmux-plugins/tpm) (TMP). Add following line to your `.tmux.conf` file:
```
set -g @plugin 'samoshkin/tmux-plugin-sysstat'
```
Use `prefix + I` from inside tmux to install all plugins and source them. If you prefer, same effect can be achieved from [command line](https://github.com/tmux-plugins/tpm/blob/master/docs/managing_plugins_via_cmd_line.md):
```
$ ~.tmux/plugins/tpm/bin/install_plugins
```
Basic usage
-----------
Once plugged in, tmux `status-left` or `status-right` options can be configured with following placeholders. Each placeholder will be expanded to metric's default output.
- `#{sysstat_cpu}`, CPU usage - `CPU:40.2%`
- `#{sysstat_mem}`, memory usage - `MEM:73%`
- `#{sysstat_swap}`, swap usage - `SW:66%`
- `#{sysstat_loadavg}`, system load average - `0.25 0.04 0.34`
For example:
```
set -g status-right "#{sysstat_cpu} | #{sysstat_mem} | #{sysstat_swap} | #{sysstat_loadavg} | #[fg=cyan]#(echo $USER)#[default]@#H"
```
Changing default output
------------------------
You can change default output for CPU and memory metrics, if you need more fields to show, or you want to provide custom template. In your `.tmux.conf`:
For example, to get `Used 4.5G out of 16G` output for memory metric:
```
set -g @sysstat_mem_view_tmpl '#Used [fg=#{mem.color}]#{mem.used}#[default] out of #{mem.total}'
```
If you don't want `CPU:` prefix and don't like colored output for CPU metric:
```
set -g @sysstat_cpu_view_tmpl '#{cpu.pused}'
```
### Supported fields
As you can see, each metric can be configured with template, containing fixed text (`CPU:`), color placeholder (`#[fg=#{mem.color}]`) and field placeholder (`#{mem.used}`). This approach gives you the ultimate control over the output for each metric. Following field placeholders are supported:
<table>
<th>CPU</th>
<tr>
<td><code>#{cpu.color}</code></td>
<td>main metric color</td>
</tr>
<tr>
<td><code>#{cpu.pused}</code></td>
<td>CPU usage percentage</td>
</tr>
</table>
<table>
<th>Memory</th>
<tr>
<td><code>#{mem.color}</code></td>
<td>main metric color</td>
</tr>
<tr>
<td><code>#{mem.free}</code></td>
<td>free/available memory</td>
</tr>
<tr>
<td><code>#{mem.pfree}</code></td>
<td>free memory percentage against total</td>
</tr>
<tr>
<td><code>#{mem.used}</code></td>
<td>used memory</td>
</tr>
<tr>
<td><code>#{mem.pused}</code></td>
<td>used memory percentage against total</td>
</tr>
<tr>
<td><code>#{mem.total}</code></td>
<td>total installed memory</td>
</tr>
</table>
<table>
<th>Swap</th>
<tr>
<td><code>#{swap.color}</code></td>
<td>main swap metric color</td>
</tr>
<tr>
<td><code>#{swap.free}</code></td>
<td>free swap memory</td>
</tr>
<tr>
<td><code>#{swap.pfree}</code></td>
<td>free swap memory percentage against total swap space</td>
</tr>
<tr>
<td><code>#{swap.used}</code></td>
<td>used swap memory</td>
</tr>
<tr>
<td><code>#{swap.pused}</code></td>
<td>used swap memory percentage against total swap space</td>
</tr>
<tr>
<td><code>#{swap.total}</code></td>
<td>total swap space</td>
</tr>
</table>
### Change size scale
free/used/total memory can be shown both in absolute and relative units. When it comes to absolute units, you can choose *size scale factor* to choose between GiB, MiB, KiB. Default is GiB. If you have less than 3-4G memory installed, it makes sense to use MiB. KiB option is less practical, because it yields pretty lengthy output, which does not fit status bar limited estate.
```
set -g @sysstat_mem_size_unit "G"
```
If you choose `G` for size scale, output will have `%.1f` (1 digit after floating point), otherwise size is integer (4.5G, 1024M, 1232345K).
Thresholds and colored output
---------------
Each metric output is colored by default. Colors vary depending on metric value.
<table>
<tr>
<td><b>Threshold</b></td>
<td><b>CPU</b></td>
<td><b>Memory</b></td>
<td><b>Swap</b></td>
<td><b>Default color</b></td>
</tr>
<tr>
<td>low</td>
<td>x &lt; 30%</td>
<td>x &lt; 75%</td>
<td>x &lt; 25%</td>
<td>green</td>
</tr>
<tr>
<td>medium</td>
<td>30% &lt; x &lt; 80%</td>
<td>75% &lt; x &lt; 90%</td>
<td>25% &lt; x &lt; 75%</td>
<td>yellow</td>
</tr>
<tr>
<td>high</td>
<td>x &gt; 80%</td>
<td>x &gt; 90%</td>
<td>x &gt; 75%</td>
<td>red</td>
</tr>
</table>
You can change thresholds in your `.tmux.conf`:
```
set -g @sysstat_cpu_medium_threshold "75"
set -g @sysstat_cpu_stress_threshold "95"
set -g @sysstat_mem_medium_threshold "85"
set -g @sysstat_mem_stress_threshold "95"
set -g @sysstat_swap_medium_threshold "80"
set -g @sysstat_swap_stress_threshold "90"
```
You can change colors for each threshold individually. You can use ANSI basic colors (red, cyan, green) or if your terminal supports 256 colors (and most do nowadays), use `colourXXX` format.
```
set -g @sysstat_cpu_color_low "colour076"
set -g @sysstat_cpu_color_medium "colour220"
set -g @sysstat_cpu_color_stress "colour160"
set -g @sysstat_mem_color_low "green"
set -g @sysstat_mem_color_medium "blue"
set -g @sysstat_mem_color_stress "cyan"
```
`#{(mem|cpu|swap).color}` placeholder in your `@sysstat_(mem|cpu|swap)_view_tmpl` would be replaced by corresponding color, depending on whether metric value falls in particular threshold.
### 256 color palette support
For 256 color palette support, make sure that `tmux` and parent terminal are configured with correct terminal type. See [here](https://unix.stackexchange.com/questions/1045/getting-256-colors-to-work-in-tmux) and [there](https://github.com/tmux/tmux/wiki/FAQ)
```
# ~/.tmux.conf
set -g default-terminal "screen-256color"
```
```
# parent terminal
$ echo $TERM
xterm-256color
# jump into a tmux session
$ tmux new
$ echo $TERM
screen-256color
```
### Multiple colors for each threshold
You can have up to *3* colors configured for each threshold. To understand why you might need this, let tackle this task. Note, this is rather advanced use case.
> I want `CPU: #{cpu.pused}` metric output, have green and yellow text colors at "low" and "medium" threshold, and finally, for "high" threshold, I want to use red color, but reverse foreground and background, that is use red for background, and white for text. More over I want "CPU:" text colored apart in red
Like this:
![cpu threshold with custom colors](/screenshots/cpu_thresholds.png)
You can achieve the result using following configuration:
```
set -g @sysstat_cpu_view_tmpl '#[fg=#{cpu.color3}]CPU:#[default] #[fg=#{cpu.color},bg=#{cpu.color2}]#{cpu.pused}#[default]'
set -g @sysstat_cpu_color_low "$color_level_ok default default"
set -g @sysstat_cpu_color_medium "$color_level_warn default default"
set -g @sysstat_cpu_color_stress "white,bold $color_level_stress $color_level_stress"
```
Tmux status-interval setting
-----------------------------
You can configure status refresh interval, increasing or reducing frequency of `tmux-plugin-sysstat` command invocations.
```
set -g status-interval 5
```
It's adviced to set `status-interval` to some reasonable value, like 5-10 seconds. More frequent updates (1 second) are useless, because they distract, and results in extra resource stress spent on metrics calculation itself.
Internals: CPU calculation
--------------------------------------------------
<span style="color: blue">**NOTE:** Stop here if you want to just use this plugin without making your feet wet. If you're hardcore tmux user and are curious about internals, keep reading</span>
Internally, we use `iostat` and `top` on OSX, and `vmstat` and `top` on Linux to collect metric value. Neither requires you to install extra packages. These commands are run in sampling mode to report stats every N seconds M times. First sample include average values since the system start. Second one is the average CPU per second for last N seconds (exactly what we need)
For example:
```
$ iostat -c 2 -w 5
disk0 cpu load average
KB/t tps MB/s us sy id 1m 5m 15m
44.22 6 0.26 3 2 95 1.74 1.90 2.15
5.47 8 0.04 4 5 91 1.84 1.92 2.16 << use this row, 2nd sample
```
We align CPU calculation intervals (`-w`) with tmux status bar refresh interval (`status-interval` setting).
Internals: memory calculation
----------------------------
You might ask what we treat as `free` memory and how it's calculated.
### OSX
Let's start with OSX. We use `vm_stat` command (not same as `vmstat` on Linux), which reports following data (number of memory pages, not KB):
```
$ vm_stat
Pages free: 37279
Pages active: 1514200
Pages inactive: 1152997
Pages speculative: 6214
Pages throttled: 0
Pages wired down: 1174408
Pages purgeable: 15405
Pages stored in compressor: 1615663
Pages occupied by compressor: 306717
```
Total installed memory formula is:
```
Total = free + active + inactive + speculative + occupied by compressor + wired
```
where
- `free`, completely unused memory by the system
- `wired`, critical information stored in RAM by system, kernel and key applications. Never swapped to the hard drive, never replaced with user-level data.
- `active`, information currently in use or very recently used by applications. When this kind of memory is not used for long (or application is closed), it's move to inactive memory.
- `inactive`, like buffers/cached memory in Linux. Memory for applications, which recently exited, retained for faster start-up of same application in future.
So the question what constitutes `free` and `used` memory. It turns out, that various monitoring and system statistics tools on OSX each calculate it differently.
- htop: `used = active + wired`, `free` = `total - used`
- top. Used = `used = active + inactive + occupied by compressor + wired`; Free = `free + speculative` Resident set size (RSS) = `active`
- OSX activity Monitor. Used = `app memory + wired + compressor`. Note, it's not clear what is app memory.
In general, they either treat currently used memory, which can be reclaimed in case of need (cached, inactive, occupied by compressor), as `used` or `free`.
It makes sense to talk about `available` memory rather than `free` one. Available memory is unused memory + any used memory which can be reclaimed for application needs.
So, `tmux-plugin-sysstat`, uses following formula:
```
used = active + wired
available/free = free/unused + inactive + speculative + occupied by compressor
```
### Linux
Same thinking can be applied to Linux systems.
Usually commands like `free` report free/unused, used, buffers, cache memory kinds.
```
$ free
total used free shared buffers cached
Mem: 1016464 900236 116228 21048 93448 241544
-/+ buffers/cache: 565244 451220
Swap: 1046524 141712 904812
```
Second line indicates available memory (free + buffers + cache), with an assumption that buffers and cache can be 100% reclaimed in case of need.
However, we're not using free, because its output varies per system. For example on RHEL7, there is no `-/+ buffers/cache`, and `available` memory is reported in different way. We read directly from `/proc/meminfo`
```
$ cat /proc/meminfo
MemTotal: 1016232 kB
MemFree: 152672 kB
MemAvailable: 637832 kB
Buffers: 0 kB
Cached: 529040 kB
```
`tmux-plugin-sysstat` uses following formula:
```
free/available = MemAvailable; // if MemAvailable present
free/available = MemFree + Buffers + Cached;
used = MemTotal - free/avaialble
```
Using `MemAvailable` is more accurate way of getting available memory, rather than manual calculation `free + buffers + cache`, because the assumption that `buffers + cache` can be 100% reclaimed for new application needs might be wrong. When using `MemAvailable`, OS calculates available memory for you, which is apparently better and accurate approach.
See [this topic](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=34e431b0ae398fc54ea69ff85ec700722c9da773) on more reasoning about `MemAvailable` field.

View File

@@ -0,0 +1,78 @@
#!/usr/bin/env bash
set -u
set -e
LC_NUMERIC=C
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
source "$CURRENT_DIR/helpers.sh"
cpu_tmp_dir=$(tmux show-option -gqv "@sysstat_cpu_tmp_dir")
cpu_view_tmpl=$(get_tmux_option "@sysstat_cpu_view_tmpl" 'CPU:#[fg=#{cpu.color}]#{cpu.pused}#[default]')
cpu_medium_threshold=$(get_tmux_option "@sysstat_cpu_medium_threshold" "30")
cpu_stress_threshold=$(get_tmux_option "@sysstat_cpu_stress_threshold" "80")
cpu_color_low=$(get_tmux_option "@sysstat_cpu_color_low" "green")
cpu_color_medium=$(get_tmux_option "@sysstat_cpu_color_medium" "yellow")
cpu_color_stress=$(get_tmux_option "@sysstat_cpu_color_stress" "red")
get_cpu_color(){
local cpu_used=$1
if fcomp "$cpu_stress_threshold" "$cpu_used"; then
echo "$cpu_color_stress";
elif fcomp "$cpu_medium_threshold" "$cpu_used"; then
echo "$cpu_color_medium";
else
echo "$cpu_color_low";
fi
}
print_cpu_usage() {
local cpu_pused=$(get_cpu_usage_or_collect)
local cpu_color=$(get_cpu_color "$cpu_pused")
local cpu_view="$cpu_view_tmpl"
cpu_view="${cpu_view//'#{cpu.pused}'/$(printf "%.1f%%" "$cpu_pused")}"
cpu_view="${cpu_view//'#{cpu.color}'/$(echo "$cpu_color" | awk '{ print $1 }')}"
cpu_view="${cpu_view//'#{cpu.color2}'/$(echo "$cpu_color" | awk '{ print $2 }')}"
cpu_view="${cpu_view//'#{cpu.color3}'/$(echo "$cpu_color" | awk '{ print $3 }')}"
echo "$cpu_view"
}
get_cpu_usage_or_collect() {
local collect_cpu_metric="$cpu_tmp_dir/cpu_collect.metric"
# read cpu metric from file, otherwise 0 as a temporary null value, until first cpu metric is collected
[ -f "$collect_cpu_metric" ] && cat "$collect_cpu_metric" || echo "0.0"
start_cpu_collect_if_required >/dev/null 2>&1
}
start_cpu_collect_if_required() {
local collect_cpu_pidfile="$cpu_tmp_dir/cpu_collect.pid"
# check if cpu collect process is running, otherwise start it in background
if [ -f "$collect_cpu_pidfile" ] && ps -p "$(cat "$collect_cpu_pidfile")" > /dev/null 2>&1; then
return;
fi
jobs >/dev/null 2>&1
"$CURRENT_DIR/cpu_collect.sh" &>/dev/null &
if [ -n "$(jobs -n)" ]; then
echo "$!" > "${collect_cpu_pidfile}"
else
echo "Failed to start CPU collect job" >&2
exit 1
fi
}
main(){
print_cpu_usage
}
main

View File

@@ -0,0 +1,53 @@
#!/usr/bin/env bash
LC_NUMERIC=C
set -u
set -e
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
source "$CURRENT_DIR/helpers.sh"
refresh_interval=$(get_tmux_option "status-interval" "5")
samples_count="60"
cpu_metric_file="$(get_tmux_option "@sysstat_cpu_tmp_dir" "/dev/null")/cpu_collect.metric"
get_cpu_usage() {
if is_osx; then
if command_exists "iostat"; then
iostat -w "$refresh_interval" -c "$samples_count" \
| stdbuf -o0 awk 'NR > 2 { print 100-$(NF-3); }'
else
top -l "$samples_count" -s "$refresh_interval" -n 0 \
| sed -u -nr '/CPU usage/s/.*,[[:space:]]*([0-9]+[.,][0-9]*)%[[:space:]]*idle.*/\1/p' \
| stdbuf -o0 awk '{ print 100-$0 }'
fi
elif ! command_exists "vmstat"; then
if is_freebsd; then
vmstat -n "$refresh_interval" -c "$samples_count" \
| stdbuf -o0 awk 'NR>2 {print 100-$(NF-0)}'
else
vmstat -n "$refresh_interval" "$samples_count" \
| stdbuf -o0 awk 'NR>2 {print 100-$(NF-2)}'
fi
else
if is_freebsd; then
top -d"$samples_count" \
| sed -u -nr '/CPU:/s/.*,[[:space:]]*([0-9]+[.,][0-9]*)%[[:space:]]*id.*/\1/p' \
| stdbuf -o0 awk '{ print 100-$0 }'
else
top -b -n "$samples_count" -d "$refresh_interval" \
| sed -u -nr '/%Cpu/s/.*,[[:space:]]*([0-9]+[.,][0-9]*)[[:space:]]*id.*/\1/p' \
| stdbuf -o0 awk '{ print 100-$0 }'
fi
fi
}
main() {
get_cpu_usage | while read -r value; do
echo "$value" | tee "$cpu_metric_file"
done
}
main

View File

@@ -0,0 +1,76 @@
get_tmux_option() {
local option="$1"
local default_value="$2"
local option_value="$(tmux show-option -gqv "$option")"
if [ -z "$option_value" ]; then
echo "$default_value"
else
echo "$option_value"
fi
}
set_tmux_option() {
local option="$1"
local value="$2"
tmux set-option -gq "$option" "$value"
}
is_osx() {
[ $(uname) == "Darwin" ]
}
is_linux(){
[ $(uname -s) == "Linux" ]
}
is_freebsd() {
[ $(uname) == FreeBSD ]
}
command_exists() {
local command="$1"
type "$command" >/dev/null 2>&1
}
# because bash does not support floating-point math
# but awk does
calc() {
local stdin;
read -d '' -u 0 stdin;
awk "BEGIN { print $stdin }";
}
# "<" math operator which works with floats, once again based on awk
fcomp() {
awk -v n1="$1" -v n2="$2" 'BEGIN {if (n1<n2) exit 0; exit 1}'
}
# get_mem_usage* function returns values in KiB
# 1 - scale to KiB
# 1024 - scale to MiB
# 1048576 - scale to GiB
function get_size_scale_factor(){
local size_unit="$1"
case "$size_unit" in
G) echo 1048576;;
M) echo 1024;;
K) echo 1;;
esac
}
# Depending on scale factor, change precision
# 12612325K - no digits after floating point
# 1261M - no digits after floating point
# 1.1G - 1 digit after floating point
function get_size_format(){
local size_unit="$1"
case "$size_unit" in
G) echo '%.1f%s';;
M) echo '%.0f%s';;
K) echo '%.0f%s';;
esac
}

View File

@@ -0,0 +1,28 @@
#!/usr/bin/env bash
set -u
set -e
LC_NUMERIC=C
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
source "$CURRENT_DIR/helpers.sh"
loadavg_per_cpu_core=$(get_tmux_option "@sysstat_loadavg_per_cpu_core" "true")
get_num_of_cores(){
is_osx && sysctl -n hw.ncpu || nproc
}
main(){
local num_cores=$([ "$loadavg_per_cpu_core" == "true" ] && get_num_of_cores || echo 1)
uptime | awk -v num_cores="$num_cores" '{
sub(/,$/, "", $(NF-2));
sub(/,$/, "", $(NF-1));
sub(/,$/, "", $NF);
printf "%.2f %.2f %.2f", $(NF-2)/num_cores, $(NF-1)/num_cores, $NF/num_cores
}'
}
main

View File

@@ -0,0 +1,130 @@
#!/usr/bin/env bash
set -u
set -e
LC_NUMERIC=C
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
source "$CURRENT_DIR/helpers.sh"
mem_view_tmpl=$(get_tmux_option "@sysstat_mem_view_tmpl" 'MEM:#[fg=#{mem.color}]#{mem.pused}#[default]')
mem_medium_threshold=$(get_tmux_option "@sysstat_mem_medium_threshold" "75")
mem_stress_threshold=$(get_tmux_option "@sysstat_mem_stress_threshold" "90")
mem_color_low=$(get_tmux_option "@sysstat_mem_color_low" "green")
mem_color_medium=$(get_tmux_option "@sysstat_mem_color_medium" "yellow")
mem_color_stress=$(get_tmux_option "@sysstat_mem_color_stress" "red")
size_unit=$(get_tmux_option "@sysstat_mem_size_unit" "G")
get_mem_color() {
local mem_pused=$1
if fcomp "$mem_stress_threshold" "$mem_pused"; then
echo "$mem_color_stress";
elif fcomp "$mem_medium_threshold" "$mem_pused"; then
echo "$mem_color_medium";
else
echo "$mem_color_low";
fi
}
print_mem() {
local mem_usage
local scale
local size_format
if is_osx; then
mem_usage=$(get_mem_usage_osx)
elif is_linux; then
mem_usage=$(get_mem_usage_linux)
elif is_freebsd; then
mem_usage=$(get_mem_usage_freebsd)
fi
local size_scale="$(get_size_scale_factor "$size_unit")"
local size_format="$(get_size_format "$size_unit")"
# Extract free and used memory in MiB, calculate total and percentage
local mem_free=$(echo $mem_usage | awk -v scale="$size_scale" '{ print $1/scale }')
local mem_used=$(echo $mem_usage | awk -v scale="$size_scale" '{ print $2/scale }')
local mem_total=$(echo "$mem_free + $mem_used" | calc)
local mem_pused=$(echo "($mem_used / $mem_total) * 100" | calc)
local mem_pfree=$(echo "($mem_free / $mem_total) * 100" | calc)
# Calculate colors for mem and swap
local mem_color=$(get_mem_color "$mem_pused")
local mem_view="$mem_view_tmpl"
mem_view="${mem_view//'#{mem.used}'/$(printf "$size_format" "$mem_used" "$size_unit")}"
mem_view="${mem_view//'#{mem.pused}'/$(printf "%.0f%%" "$mem_pused")}"
mem_view="${mem_view//'#{mem.free}'/$(printf "$size_format" "$mem_free" "$size_unit")}"
mem_view="${mem_view//'#{mem.pfree}'/$(printf "%.0f%%" "$mem_pfree")}"
mem_view="${mem_view//'#{mem.total}'/$(printf "$size_format" "$mem_total" "$size_unit")}"
mem_view="${mem_view//'#{mem.color}'/$(echo "$mem_color" | awk '{ print $1 }')}"
mem_view="${mem_view//'#{mem.color2}'/$(echo "$mem_color" | awk '{ print $2 }')}"
mem_view="${mem_view//'#{mem.color3}'/$(echo "$mem_color" | awk '{ print $3 }')}"
echo "$mem_view"
}
# Report like it does htop on OSX:
# used = active + wired
# free = free + inactive + speculative + occupied by compressor
# see `vm_stat` command
get_mem_usage_osx(){
local page_size=$(sysctl -nq "vm.pagesize")
vm_stat | awk -v page_size=$page_size -F ':' '
BEGIN { free=0; used=0 }
/Pages active/ ||
/Pages wired/ {
gsub(/^[ \t]+|[ \t]+$/, "", $2); used+=$2;
}
/Pages free/ ||
/Pages inactive/ ||
/Pages speculative/ ||
/Pages occupied by compressor/ {
gsub(/^[ \t]+|[ \t]+$/, "", $2); free+=$2;
}
END { print (free * page_size)/1024, (used * page_size)/1024 }
'
}
# Relies on vmstat, but could also be done with top on FreeBSD
get_mem_usage_freebsd(){
vmstat -H | tail -n 1 | awk '{ print $5, $4 }'
}
# Method #1. Sum up free+buffers+cached, treat it as "available" memory, assuming buff+cache can be reclaimed. Note, that this assumption is not 100% correct, buff+cache most likely cannot be 100% reclaimed, but this is how memory calculation is used to be done on Linux
# Method #2. If "MemAvailable" is provided by system, use it. This is more correct method, because we're not relying on fragile "free+buffer+cache" equation.
# See: Interpreting /proc/meminfo and free output for Red Hat Enterprise Linux 5, 6 and 7 - Red Hat Customer Portal - https://access.redhat.com/solutions/406773
# See: kernel/git/torvalds/linux.git - /proc/meminfo: provide estimated available memory - https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=34e431b0ae398fc54ea69ff85ec700722c9da773
get_mem_usage_linux(){
</proc/meminfo awk '
BEGIN { total=0; free=0; }
/MemTotal:/ { total=$2; }
/MemFree:/ { free+=$2; }
/Buffers:/ { free+=$2; }
/Cached:/ { free+=$2; }
/MemAvailable:/ { free=$2; exit;}
END { print free, total-free }
'
}
main() {
print_mem
}
main

View File

@@ -0,0 +1,95 @@
#!/usr/bin/env bash
set -u
set -e
LC_NUMERIC=C
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
source "$CURRENT_DIR/helpers.sh"
swap_view_tmpl=$(get_tmux_option "@sysstat_swap_view_tmpl" 'SW:#[fg=#{swap.color}]#{swap.pused}#[default]')
swap_medium_threshold=$(get_tmux_option "@sysstat_swap_medium_threshold" "25")
swap_stress_threshold=$(get_tmux_option "@sysstat_swap_stress_threshold" "75")
swap_color_low=$(get_tmux_option "@sysstat_swap_color_low" "green")
swap_color_medium=$(get_tmux_option "@sysstat_swap_color_medium" "yellow")
swap_color_stress=$(get_tmux_option "@sysstat_swap_color_stress" "red")
size_unit=$(get_tmux_option "@sysstat_swap_size_unit" "G")
get_swap_color() {
local swap_pused=$1
if fcomp "$swap_stress_threshold" "$swap_pused"; then
echo "$swap_color_stress";
elif fcomp "$swap_medium_threshold" "$swap_pused"; then
echo "$swap_color_medium";
else
echo "$swap_color_low";
fi
}
print_swap() {
local swap_usage
if is_osx; then
swap_usage=$(get_swap_usage_osx)
elif is_linux; then
swap_usage=$(get_swap_usage_linux)
fi
local size_scale="$(get_size_scale_factor "$size_unit")"
local size_format="$(get_size_format "$size_unit")"
# Extract swap free and used in MiB, calculate total and percentage
local swap_free=$(echo $swap_usage | awk -v scale="$size_scale" '{ print $1/scale }')
local swap_used=$(echo $swap_usage | awk -v scale="$size_scale" '{ print $2/scale }')
local swap_total=$(echo "$swap_free + $swap_used" | calc)
local swap_pused=$(echo "($swap_used / $swap_total) * 100" | calc)
local swap_pfree=$(echo "($swap_free / $swap_total) * 100" | calc)
# Calculate colors for mem and swap
local swap_color=$(get_swap_color "$swap_pused")
local swap_view="$swap_view_tmpl"
swap_view="${swap_view//'#{swap.used}'/$(printf "$size_format" "$swap_used" "$size_unit")}"
swap_view="${swap_view//'#{swap.pused}'/$(printf "%.0f%%" "$swap_pused")}"
swap_view="${swap_view//'#{swap.free}'/$(printf "$size_format" "$swap_free" "$size_unit")}"
swap_view="${swap_view//'#{swap.pfree}'/$(printf "%.0f%%" "$swap_pfree")}"
swap_view="${swap_view//'#{swap.total}'/$(printf "$size_format" "$swap_total" "$size_unit")}"
swap_view="${swap_view//'#{swap.color}'/$(echo "$swap_color" | awk '{ print $1 }')}"
swap_view="${swap_view//'#{swap.color2}'/$(echo "$swap_color" | awk '{ print $2 }')}"
swap_view="${swap_view//'#{swap.color3}'/$(echo "$swap_color" | awk '{ print $3 }')}"
echo "$swap_view"
}
get_swap_usage_osx(){
# assume swap size in MB
local swap_used=$(sysctl -nq vm.swapusage | awk -F ' ' '{ print $2 }' | awk -F '=' '{gsub(/^[ ]|[M]$/, "", $2); printf "%d", $2 * 1024 }')
local swap_free=$(sysctl -nq vm.swapusage | awk -F ' ' '{ print $3 }' | awk -F '=' '{gsub(/^[ ]|[M]$/, "", $2); printf "%d", $2 * 1024 }')
printf "%s %s" "$swap_free" "$swap_used"
}
get_swap_usage_linux(){
</proc/meminfo awk '
BEGIN { total=0; free=0; }
/SwapTotal:/ { total=$2; }
/SwapFree:/ { free=$2; }
END { print free, total-free }
'
}
main() {
print_swap
}
main

View File

@@ -0,0 +1,43 @@
#!/usr/bin/env bash
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
source "$CURRENT_DIR/scripts/helpers.sh"
placeholders=(
"\#{sysstat_cpu}"
"\#{sysstat_mem}"
"\#{sysstat_swap}"
"\#{sysstat_loadavg}"
)
commands=(
"#($CURRENT_DIR/scripts/cpu.sh)"
"#($CURRENT_DIR/scripts/mem.sh)"
"#($CURRENT_DIR/scripts/swap.sh)"
"#($CURRENT_DIR/scripts/loadavg.sh)"
)
do_interpolation() {
local all_interpolated="$1"
for ((i=0; i<${#commands[@]}; i++)); do
all_interpolated=${all_interpolated//${placeholders[$i]}/${commands[$i]}}
done
echo "$all_interpolated"
}
update_tmux_option() {
local option="$1"
local option_value="$(get_tmux_option "$option")"
local new_option_value="$(do_interpolation "$option_value")"
set_tmux_option "$option" "$new_option_value"
}
main() {
cpu_tmp_dir=$(mktemp -d)
tmux set-option -gq "@sysstat_cpu_tmp_dir" "$cpu_tmp_dir"
update_tmux_option "status-right"
update_tmux_option "status-left"
}
main