Forem

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

Posted on • Edited on

15 7

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.

Image of Datadog

Create and maintain end-to-end frontend tests

Learn best practices on creating frontend tests, testing on-premise apps, integrating tests into your CI/CD pipeline, and using Datadog’s testing tunnel.

Download The Guide

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.

👋 Kindness is contagious

Discover a treasure trove of wisdom within this insightful piece, highly respected in the nurturing DEV Community enviroment. Developers, whether novice or expert, are encouraged to participate and add to our shared knowledge basin.

A simple "thank you" can illuminate someone's day. Express your appreciation in the comments section!

On DEV, sharing ideas smoothens our journey and strengthens our community ties. Learn something useful? Offering a quick thanks to the author is deeply appreciated.

Okay