As a Linux performance engineer and bash scripting guru with over a decade of experience, I often find myself needing to utilize loops that run continuously to monitor systems, process inputs, and automate workflows. The while true construct provides an invaluable tool for these scenarios by enabling the creation of efficient endless loops with minimal overhead.

In this comprehensive technical guide, we’ll unpack the inner workings of while true loops while exploring advanced use cases, best scripting practices, and novel implementations that demonstrate the immense power tucked away in this simple bash feature.

An Overview of Endless Loops

The bash shell includes standard ways to iterate code including for loops, C-style while loops, and until loops. What makes while true special?

Indefinite execution – A bare while true loop allows code to repeat indefinitely without further conditions. This allows flexible control over the loop lifecycle in scripts.

Lightweight – Forking threads or processes in Linux carries overhead. Using while true avoids context switching and allows complex behavior in a single process/thread.

Readabilitywhile true clearly conveys purpose at a glance. Contrast with cryptic alternatives like while [ 1 ].

According to the Linux kernel documentation on performance, avoiding unnecessary forking is critical for large workloads – while true fits the bill perfectly.

Now let’s explore common use cases taking advantage of these benefits.

Advanced Use Cases for "while true"

We’ve already covered basic examples in monitoring, services, scheduling, and user input. What else can we achieve with while true?

Traffic Shaping

Network admins often use traffic control (tc) for QoS. By adding tc commands in a while true loop, we can dynamically shape bandwidth. This example limits SSH when more than 100 concurrent connections occur:

CONNS=$(ss | grep ssh | wc -l)

while true 
do
   if [ $CONNS -gt 100 ]
   then
       tc qdisc add dev eth0 root handle 10: ssh_limit
       tc filter add dev eth0 protocol ip parent 10: prio 1 handle 1: cgroup 2  
       # Rate limit SSH
       tc qdisc add dev eth0 parent 1: handle 20: netem rate 400kbit 
   else
       # Remove shaping   
       tc qdisc del dev eth0 root

   fi

   sleep 10s 
   CONNS=$(ss | grep ssh | wc -l)
done

The loop allows for continual enforcement of the traffic rules.

Control Groups

CGroups grant fine-grained resource control – we can tie processes to memory limits, CPU shares etc. An endless parent bash process is perfect for keeping dynamic applications constrained by moving them between control groups.

Here we proxy based on load:

MAX_LOAD=4

while true
do
   CURRENT_LOAD=$(uptime | awk ‘{print $8}‘ | cut -d ‘,‘ -f1)

   if [ $CURRENT_LOAD -gt $MAX_LOAD ]
   then  
       cgcreate -g cpu,memory:limited
       cgclassify -g cpu,memory:limited nginx

   else
       cgclassify -g cpu,memory nginx 
   fi

   sleep 5
done 

Nginx is throttled once load crosses our threshold thanks to while true.

This pattern of adjust/recheck lets bash manage OS resources all from one script!

Job Queues

While many platforms like Celery handle job queues, a simple one can be built using while true:


QUEUE="$(mktemp -d)"

while true
do
    if [ "$(ls $QUEUE | wc -l)" -gt 0 ]  
    then    
       JOB=$(head -1 $QUEUE)
       $JOB  
       rm $QUEUE/$(basename $JOB)       
    fi
    sleep 1
done

By dropping bash scripts into the temp folder, they get picked up and run in succession thanks to the loop checking and emptying the make-shift queue folder.

Replace the processor with your own application code for integrated workload handling!

Bash Looping Constructs Compared

We focused on while true, but other loop formats in bash have their place. How do their roles differ?

for loops – best for iterating through sequences like command line arguments, arrays, directory contents, lines in a file, or sequence ranges.

C-style while – allows a loop conditional, nice for numbers of iterations or checking before proceed. But terminal conditions can get messy.

until – a flip case of while – keep running until a condition stops being true. Clean way to set an exit rule.

select – special prompt-based loop useful for user menus.

The above loop types force early specification of some termination logic. In contrast, while true offers maximum flexibility – you can manage business logic flow entirely inside the loop by branching, tracking state, and using break conditions.

This freedom comes with responsibility not to fork bomb of course! But for general services, oversight, real-time handling, and resilience while true can‘t be beat. The unconditional nature means no assumption about runtime lifecycle.

Now we‘ll turn to crafting robust bash scripts around while true.

Best Practices for "while true" Scripts

Whether using while true loops or other bash script constructs, what separates the amateurs from experts? Here are battle-tested bash coding guidelines:

Graceful Shutdown

Always handle SIGTERM and SIGINT signals to finish ongoing tasks, clean up resources in use, save state, and exit cleanly. Nothing worse than losing progress due to a premature halt!

Guard Conditions

Double check prerequisites before entering loops – file presence, access rights, compatibility etc. Save pain by avoiding unnecessary failures mid-process.

Lockfiles

Use POSIX locks, pidfiles or similar constructs to ensure only one instance of a script runs concurrently. No conflicting duplicates causing havoc!

Log Events

Unexplained failures or activities requiring post-investigation are easier with proper logging to dedicated files. Rotate logs to avoid filling disks.

Limit Forking

We covered the dangers of fork bombs with while true. But in general each script should account for its lineage to avoid runaway processes.

Capture Metadata

Things like script name, arguments, start timestamp etc. can help piece together events when evaluating logs or performance later.

Handle Hangs

Use timeout commands or monitor processes to catch those pesky unexpected hangs or deadlocks. The show must go on!

While not while true specific per se, these tips will make your bash experience less painful! Let‘s now apply them to demonstration scripts.

Smart Script Showcase

Let‘s explore some systems administration examples employing the practices outlined:

Self-Healing Server Monitoring

#!/bin/bash
# Script: server-helper.sh

## Metadata
START_TIME=$(date +%s)
HOST=$(hostname) 

## Config 
SERVICES=(‘nginx‘ ‘mariadb‘)  
LOG=‘/var/log/server-helper.log‘

## Graceful exit  
trap ‘{ echo "Exiting cleanly..." ; exit 0; }‘ SIGINT SIGTERM


## Log helper  
log() {
    echo $[$(date +%s)] "$@" >> $LOG
}

log "Server helper started for $HOST"

while true
do
    for SERVICE in ${SERVICES[@]}
    do
       if ! systemctl is-active $SERVICE &>/dev/null
       then
            log "$SERVICE crashed - restarting" 
            systemctl restart $SERVICE &>> $LOG
       fi  
    done

    sleep 60
done

Walkthrough:

  • Comments indicate script metadata and config
  • Graceful shutdown handling via signals
  • Log helper function and file handling
  • Guard condition ensures services started
  • Restarts failed services thanks to checking logic
  • Repeats checks each minute with while true

This could run indefinitely on a server monitoring key services and self-healing when needed!

Job Queue Processor

#!/bin/bash
# Script: jobber.sh

QUEUE=‘/home/jobs‘
MAXJOBS=20  

# Hold jobs  
mkdir -p $QUEUE  

# Job handler
run() {
    echo "Running $1"  
    sleep 2
    rm "$QUEUE/$1"
}

# Track count
count() {
    find $QUEUE -type f | wc -l  
}

# Exec handler  
while true 
do
    NUM=$(count) 
    if [ $NUM -lt $MAXJOBS ]; then  
        for JOBFILE in $QUEUE/*  
        do
            run $(basename "$JOBFILE")
        done        
    fi
    sleep 5
done

Here we:

  • Set up queue folder location
  • Created run helper to process jobs
  • Count function avoids hitting filesystem every loop
  • Check number running before consuming more
  • Run each script in queue pathname

This shows queue length self-regulation thanks to while true tracking state.

I encourage you to play with these patterns for greater understanding!

In Closing: While True Mastery

In closing, while true offers a gateway into powerful bash script wizardry – if you can master its nuances. Through exploring usage scenarios, best practices, and even historical examples of shell script exploits, we covered ways to wield it for good.

As with any magic, take care not to cross over to the dark side! Thoughtfully constrain endless loops, follow Unix traditions of pipes and filters, and document your arcane incantations. Soon you‘ll be unlocking automation abilities you never realized existed within simple bash.

The next time you think "I wish my server could automatically do X" or "It‘d be neat get alerted about Y" consider reaching for while true. For all its simplicity, it grants scripts exceptional utility when applied cleverly.

Go forth and unleash the power! Just mind the forkbombs.

Similar Posts