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.
Readability – while 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.


