DEV Community

Cover image for Make Your Tmux Status Bar 100% Better With Bash
brandon_wallace
brandon_wallace

Posted on • Edited on

Make Your Tmux Status Bar 100% Better With Bash

This article has been re-written

Make Your Status Line 100% Better With Bash

Did you know that you can easily have a Bash script display information on the Tmux status bar? Because of that the possibilities are almost endless. You can display all sorts of valuable information such as:

Included in this article:

  • Hostname
  • IP address
  • Netmask
  • Memory usage
  • Memory total
  • CPU temperature
  • System load
  • Battery meter
  • VPN status
  • Time
  • Date

Not included in article:

  • Weather report
  • Gateway
  • Git status

I will show you how to create a modular Bash script to display useful information in the status bar. There are a lot of plug-ins you could install for Tmux but engineering things yourself is a lot of fun. I will create a separate function for each status bar item to make the script modular, that way we will only call the functions that we need.

Here is the default status bar.

tmux-default-status-bar.png

Here is the status bar customized.

tmux-status-bar-improved.png

Requirments

  • lm-sensors
  • bc
  • acpi

Check your Tmux version. I am using version 3.1.

 $ tmux -V # Output tmux 3.1c 
Enter fullscreen mode Exit fullscreen mode

If you do not have a .tmux.conf create one in your home directory.

 $ touch .tmux.conf 
Enter fullscreen mode Exit fullscreen mode

In the .tmux.conf make sure you have the following lines.

 # Status bar set -g status on set -g status-interval 1 set -g status-justify centre # Careful! It is spelled centre not center. set -g status-style fg=white,bg=black # Highlight the current window. setw -g window-status-current-style fg=white,bg=red,bright # Status Bar Left side set -g status-left-length 50 set -g status-left-style default set -g status-left "#h #( ~/.tmux/left_status.sh )" # Status Bar Right side set -g status-right-length 40 set -g status-right-style default set -g status-right "#( ~/.tmux/right_status.sh )" 
Enter fullscreen mode Exit fullscreen mode

Make a hidden folder in your home directory to save your Bash scripts.

 $ mkdir .tmux 
Enter fullscreen mode Exit fullscreen mode

Make two Bash scripts, one for the left side, one for the right.

 $ touch ~/.tmux/right_status.sh $ touch ~/.tmux/left_status.sh 
Enter fullscreen mode Exit fullscreen mode

The scripts are currently not executable ( rw-r--r-- ).

 $ ls -lF ~/.tmux/*.sh -rw-r--r-- 1 bw bw 0 Feb 19 18:44 /home/bw/.tmux/right_status.sh -rw-r--r-- 1 bw bw 0 Feb 19 18:44 /home/bw/.tmux/left_status.sh 
Enter fullscreen mode Exit fullscreen mode

Make the scripts executable so they will run the chmod command.

 $ chmod +x ~/.tmux/right_status.sh $ chmod +x ~/.tmux/left_status.sh 
Enter fullscreen mode Exit fullscreen mode

The scripts are now executable ( rwxr-xr-x ).

 $ ls -lF ~/.tmux/*.sh -rwxr-xr-x 1 bw bw 0 Feb 19 18:44 /home/bw/.tmux/right_status.sh* -rwxr-xr-x 1 bw bw 0 Feb 19 18:44 /home/bw/.tmux/left_status.sh* 
Enter fullscreen mode Exit fullscreen mode

Status Bar Left Side

tmux-status-left-side.png

First edit the left_status.sh script. Add the following content. The ip_address function displays the IP address and netmask.

$ vim ~/.tmux/left_status.sh

 #!/bin/bash function ip_address() { # Loop through the interfaces and check for the interface that is up. for file in /sys/class/net/*; do iface=$(basename $file); read status < $file/operstate; [ "$status" == "up" ] && ip addr show $iface | awk '/inet /{printf $2" "}' done } 
Enter fullscreen mode Exit fullscreen mode

Underneath the IP address function add the CPU function. You must install lm-sensors for this to work. Run these two commands.

 $ sudo apt install lm-sensors $ sudo sensors-detect 
Enter fullscreen mode Exit fullscreen mode

Run the sensors command to see the output.

 # Celcius $ sensors # Output acpitz-acpi-0 Adapter: ACPI interface temp1: +27.8°C (crit = +105.0°C) temp2: +29.8°C (crit = +105.0°C) # Fahrenheit $ sensors -f # Output acpitz-acpi-0 Adapter: ACPI interface temp1: +82.0°F (crit = +221.0°F) temp2: +85.6°F (crit = +221.0°F) 
Enter fullscreen mode Exit fullscreen mode

Add the cpu_temperature function below the ip_address function.

 function cpu_temperature() { # Display the temperature of CPU core 0 and core 1. sensors -f | awk '/Core 0/{printf $3" "}/Core 1/{printf $3" "}' } 
Enter fullscreen mode Exit fullscreen mode

To see the memory usage we will add a memory_usage function. We need the bc command to calculate the percentage of memory used.

Install bc command.

 $ sudo apt install bc 
Enter fullscreen mode Exit fullscreen mode

Add the memory_usage function to the script.

 function memory_usage() { if [ "$(which bc)" ]; then # Display used, total, and percentage of memory using the free command. read used total <<< $(free -m | awk '/Mem/{printf $2" "$3}') # Calculate the percentage of memory used with bc. percent=$(bc -l <<< "100 * $total / $used") # Feed the variables into awk and print the values with formating. awk -v u=$used -v t=$total -v p=$percent 'BEGIN {printf "%sMi/%sMi %.1f% ", t, u, p}' fi } 
Enter fullscreen mode Exit fullscreen mode

The next function will display if the VPN is up by checking for the tun0 interface.

 function vpn_connection() { # Check for tun0 interface. [ -d /sys/class/net/tun0 ] && printf "%s " 'VPN*' } 
Enter fullscreen mode Exit fullscreen mode

To complete the left_status.sh script we will use a main function to call the other functions.

 function main() { # Comment out any function you do not need.  ip_address cpu_temperature memory_usage vpn_connection } # Calling the main function which will call the other functions. main 
Enter fullscreen mode Exit fullscreen mode

Status Bar Right Side

tmux-status-right-side.png

Now let’s configure the right side.

$ vim ~/.tmux/right_status.sh

The battery meter function displays the level of the battery and changes color depending on the battery level.
We need the acpi program for this.

 $ apt install acpi 
Enter fullscreen mode Exit fullscreen mode

Run acpi to see the output.

 $ acpi # Output Battery 0: Unknown, 96% 
Enter fullscreen mode Exit fullscreen mode

If your terminal supports emojis you can add an emoji to the status bar.

I will add the lighting bolt emoji to show when the battery is charging.

emoji-icon.png

Add the battery_meter function to the Bash script.

$ vim ~/.tmux/right_status.sh

 #!/bin/bash function battery_meter() { if [ "$(which acpi)" ]; then # Set the default color to the local variable fgdefault. local fgdefault='#[default]' if [ "$(cat /sys/class/power_supply/AC/online)" == 1 ] ; then local icon='🗲' local charging='+' else local icon='' local charging='-' fi # Check for existence of a battery. if [ -x /sys/class/power_supply/BAT0 ] ; then batt0=$(acpi -b 2> /dev/null | awk '/Battery 0/{print $4}' | cut -d, -f1) case $batt0 in # From 100% to 75% display color grey. 100%|9[0-9]%|8[0-9]%|7[5-9]%) fgcolor='#[fg=brightgrey]' ;; # From 74% to 50% display color green. 7[0-4]%|6[0-9]%|5[0-9]%) fgcolor='#[fg=brightgreen]' ;; # From 49% to 25% display color yellow. 4[0-9]%|3[0-9]%|2[5-9]%) fgcolor='#[fg=brightyellow]' ;; # From 24% to 0% display color red. 2[0-4]%|1[0-9]%|[0-9]%) fgcolor='#[fg=brightred]' ;; esac # Display the percentage of charge the battery has. printf "%s " "${fgcolor}${icon}${charging}${batt0}%${fgdefault}" fi fi } 
Enter fullscreen mode Exit fullscreen mode

The next function will add to the script is to get the load average using the uptime command.

 function load_average() { printf "%s " "$(uptime | awk -F: '{printf $NF}' | tr -d ',')" } 
Enter fullscreen mode Exit fullscreen mode

To see the time, date, and timezone add the date_time function to the Bash script.

 function date_time() { printf "%s " "$(date +'%Y-%m-%d %H:%M:%S %Z')" } 
Enter fullscreen mode Exit fullscreen mode

The last function is the main function which calls the other functions.

 function main() { battery_meter load_average date_time } # Calling the main function which will call the other functions. main 
Enter fullscreen mode Exit fullscreen mode

Complete Scripts

$ cat ~/.tmux/left_status.sh

 #!/bin/bash function ip_address() { # Loop through the interfaces and check for the interface that is up. for file in /sys/class/net/*; do iface=$(basename $file); read status < $file/operstate; [ "$status" == "up" ] && ip addr show $iface | awk '/inet /{printf $2" "}' done } function cpu_temperature() { # Display the temperature of CPU core 0 and core 1. sensors -f | awk '/Core 0/{printf $3" "}/Core 1/{printf $3" "}' } function memory_usage() { if [ "$(which bc)" ]; then # Display used, total, and percentage of memory using the free command. read used total <<< $(free -m | awk '/Mem/{printf $2" "$3}') # Calculate the percentage of memory used with bc. percent=$(bc -l <<< "100 * $total / $used") # Feed the variables into awk and print the values with formating. awk -v u=$used -v t=$total -v p=$percent 'BEGIN {printf "%sMi/%sMi %.1f% ", t, u, p}' fi } function vpn_connection() { # Check for tun0 interface. [ -d /sys/class/net/tun0 ] && printf "%s " 'VPN*' } function main() { # Comment out any function you do not need.  ip_address cpu_temperature memory_usage vpn_connection } # Calling the main function which will call the other functions. main 
Enter fullscreen mode Exit fullscreen mode

$ cat ~/.tmux/right_status.sh

 

#!/bin/bash

function battery_meter() {

<span class="k">if</span> <span class="o">[</span> <span class="s2">"</span><span class="si">$(</span>which acpi<span class="si">)</span><span class="s2">"</span> <span class="o">]</span><span class="p">;</span> <span class="k">then</span> <span class="c"># Set the default color to the local variable fgdefault.</span> <span class="nb">local </span><span class="nv">fgdefault</span><span class="o">=</span><span class="s1">'#[default]'</span> <span class="k">if</span> <span class="o">[</span> <span class="s2">"</span><span class="si">$(</span><span class="nb">cat</span> /sys/class/power_supply/AC/online<span class="si">)</span><span class="s2">"</span> <span class="o">==</span> 1 <span class="o">]</span> <span class="p">;</span> <span class="k">then </span><span class="nb">local </span><span class="nv">icon</span><span class="o">=</span><span class="s1">'🗲'</span> <span class="nb">local </span><span class="nv">charging</span><span class="o">=</span><span class="s1">'+'</span> <span class="k">else </span><span class="nb">local </span><span class="nv">icon</span><span class="o">=</span><span class="s1">''</span> <span class="nb">local </span><span class="nv">charging</span><span class="o">=</span><span class="s1">'-'</span> <span class="k">fi</span> <span class="c"># Check for existence of a battery.</span> <span class="k">if</span> <span class="o">[</span> <span class="nt">-x</span> /sys/class/power_supply/BAT0 <span class="o">]</span> <span class="p">;</span> <span class="k">then </span><span class="nb">local </span><span class="nv">batt0</span><span class="o">=</span><span class="si">$(</span>acpi <span class="nt">-b</span> 2&gt; /dev/null | <span class="nb">awk</span> <span class="s1">'/Battery 0/{print $4}'</span> | <span class="nb">cut</span> <span class="nt">-d</span>, <span class="nt">-f1</span><span class="si">)</span> <span class="k">case</span> <span class="nv">$batt0</span> <span class="k">in</span> <span class="c"># From 100% to 75% display color grey.</span> 100%|9[0-9]%|8[0-9]%|7[5-9]%<span class="p">)</span> <span class="nv">fgcolor</span><span class="o">=</span><span class="s1">'#[fg=brightgrey]'</span> <span class="p">;;</span> <span class="c"># From 74% to 50% display color green.</span> 7[0-4]%|6[0-9]%|5[0-9]%<span class="p">)</span> <span class="nv">fgcolor</span><span class="o">=</span><span class="s1">'#[fg=brightgreen]'</span> <span class="p">;;</span> <span class="c"># From 49% to 25% display color yellow.</span> 4[0-9]%|3[0-9]%|2[5-9]%<span class="p">)</span> <span class="nv">fgcolor</span><span class="o">=</span><span class="s1">'#[fg=brightyellow]'</span> <span class="p">;;</span> <span class="c"># From 24% to 0% display color red.</span> 2[0-4]%|1[0-9]%|[0-9]%<span class="p">)</span> <span class="nv">fgcolor</span><span class="o">=</span><span class="s1">'#[fg=brightred]'</span> <span class="p">;;</span> <span class="k">esac</span> <span class="c"># Display the percentage of charge the battery has.</span> <span class="nb">printf</span> <span class="s2">"%s "</span> <span class="s2">"</span><span class="k">${</span><span class="nv">fgcolor</span><span class="k">}${</span><span class="nv">charging</span><span class="k">}${</span><span class="nv">batt0</span><span class="k">}</span><span class="s2">%</span><span class="k">${</span><span class="nv">fgdefault</span><span class="k">}</span><span class="s2">"</span> <span class="k">fi fi</span> 
Enter fullscreen mode Exit fullscreen mode

}

function load_average() {

<span class="nb">printf</span> <span class="s2">"%s "</span> <span class="s2">"</span><span class="si">$(</span><span class="nb">uptime</span> | <span class="nb">awk</span> <span class="nt">-F</span>: <span class="s1">'{printf $NF}'</span> | <span class="nb">tr</span> <span class="nt">-d</span> <span class="s1">','</span><span class="si">)</span><span class="s2">"</span> 
Enter fullscreen mode Exit fullscreen mode

}

function date_time() {

<span class="nb">printf</span> <span class="s2">"%s"</span> <span class="s2">"</span><span class="si">$(</span><span class="nb">date</span> +<span class="s1">'%Y-%m-%d %H:%M:%S %Z'</span><span class="si">)</span><span class="s2">"</span> 
Enter fullscreen mode Exit fullscreen mode

}

function main() {

battery_meter load_average date_time 
Enter fullscreen mode Exit fullscreen mode

}

# Calling the main function which will call the other functions.
main

Enter fullscreen mode Exit fullscreen mode




Conclusion

You can now easily have a Bash script display useful information on the Tmux status bar. I hope you enjoyed reading this article.

Follow me on Dev.to and Github.

Feel free to leave comment, questions, and suggestions.

Top comments (8)

Collapse
 
vlasales profile image
Vlastimil Pospichal

~/.tmux/left_status.sh

for file in /sys/class/net/*; do iface=$(basename $file); read status <$file/operstate; test "$status" = "up" &&\ ip addr show $iface|\ awk '/inet /{print $2}' done 
Enter fullscreen mode Exit fullscreen mode
Collapse
 
brandonwallace profile image
brandon_wallace • Edited

@vlasales I refactored my code and came up with this.

# Loop through the interfaces and check for the one that is up. for iface in /sys/class/net/*/operstate; do if [ "$(echo $iface | awk -F'/' '{print $5}')" != "lo" ]; then if [ "$(cat $iface)" == "up" ] ; then interface=$(echo $iface | awk -F'/' '{print $5}') printf "%s " "$(ip addr show $interface | awk '/inet /{print $2}')" fi fi done 
Enter fullscreen mode Exit fullscreen mode

But the code you wrote is shorter so I added it to my article. The old code had two loops but one loop is better than two. Thanks.

Collapse
 
brandonwallace profile image
brandon_wallace

Thanks for the code example Vlastimil.

Collapse
 
stephenwhitmore profile image
Stephen Whitmore

I use a custom theme made by someone else but I love this article because it's perfect for people who enjoy ricing. Also, tmux is easily in my top 5 favorite applications. Saving this for later!

Collapse
 
brandonwallace profile image
brandon_wallace

Yes, Tmux is super useful. I thought that people unfamiliar with Bash shell would be able to learn a bit.

Collapse
 
brandonwallace profile image
brandon_wallace

I fixed some typos in the code.

Collapse
 
rubiin profile image
Rubin

you can get all that without the hassle of configuring anything with oh-my-tmux

Collapse
 
brandonwallace profile image
brandon_wallace • Edited

The goal of this article is to teach people how to configure the status bar themselves because it is fun and a good learning experience. They will also be able to customize things just the way they want.