Skip to main content

Command Palette

Search for a command to run...

Day 42 - Using Bash Loops for Monitoring, SSH Key Exchange & Remote Execution

Automate DevOps Workflows: The Role of Bash Loops in Monitoring, SSH Key Exchange & Remote Execution

Published
4 min read
Day 42 -  Using Bash Loops for Monitoring, SSH Key Exchange & Remote Execution

Today I dove deep into loops in Bash scripting and used them to automate three practical tasks:

  1. Lightweight monitoring with threshold alerts

  2. Automated SSH key exchange to enable passwordless login

  3. Remote command execution across a fleet of servers

If you’re also early in your DevOps journey, these three scripts will instantly make your workflow more repeatable and scalable.


TL;DR

  • Loops (for, while, until) are the backbone of shell automation.

  • I built three scripts that leverage loops:

    • monitor.sh – checks CPU, memory, and disk usage in a loop and warns on thresholds

    • ssh_key_exchange.sh – copies your SSH public key to many servers (looping over a hosts.txt file)

    • remote_exec.sh – runs any command on multiple servers and aggregates the output

  • At the end you’ll also find a Sora video prompt I’m using to document Day 42 visually.


Quick Primer: Loops in Bash

for

Great for iterating over a list of items.

for host in server1 server2 server3; do
  echo "Pinging $host"
  ping -c1 "$host" >/dev/null && echo "✅ $host is up" || echo "❌ $host is down"
done

while

Perfect when reading from files, streams, or running infinite/polling loops.

while read -r user; do
  echo "Creating user: $user"
  # useradd "$user"
done < users.txt

until

Runs until a condition becomes true (i.e., loop continues while condition is false).

count=0
until [[ $count -ge 5 ]]; do
  echo "Count: $count"
  ((count++))
  sleep 1
done

1) monitor.sh — Mini Monitoring Script (CPU, Mem, Disk)

This script runs in a while loop, checks system vitals, and warns if thresholds are crossed. You can run it in the foreground or background (via nohup / systemd / screen / tmux).

File: monitor.sh

#!/usr/bin/env bash
set -euo pipefail

INTERVAL=${1:-5}              # seconds between checks
CPU_THR=${CPU_THR:-85}        # % CPU usage threshold
MEM_THR=${MEM_THR:-85}        # % Memory usage threshold
DISK_THR=${DISK_THR:-80}      # % Disk usage threshold
LOG_DIR=${LOG_DIR:-/var/log/devops}
mkdir -p "$LOG_DIR"
LOG_FILE="$LOG_DIR/monitor_$(date +%F).log"

log() { echo "$(date +'%F %T') | $*" | tee -a "$LOG_FILE"; }

get_cpu_usage() {
  # Quick-and-dirty estimation from /proc/stat (single snapshot)
  # For production-grade accuracy, compute deltas between two reads or use mpstat/vmstat.
  awk '/^cpu / {usage=($2+$3+$4)*100/($2+$3+$4+$5); printf "%.2f", usage}' /proc/stat
}

get_mem_usage() {
  free -m | awk '/Mem:/ {printf "%.2f", $3*100/$2}'
}

check_disk_usage() {
  df -P --output=pcent,target | tail -n +2 | while read -r pct mount; do
    pct=${pct%%%}
    echo "$pct $mount"
  done
}

while true; do
  CPU=$(get_cpu_usage)
  MEM=$(get_mem_usage)

  if (( ${CPU%.*} > CPU_THR )); then
    log "⚠️  High CPU usage: ${CPU}% (> ${CPU_THR}%)"
  else
    log "✅ CPU: ${CPU}%"
  fi

  if (( ${MEM%.*} > MEM_THR )); then
    log "⚠️  High Memory usage: ${MEM}% (> ${MEM_THR}%)"
  else
    log "✅ Memory: ${MEM}%"
  fi

  # Loop over all mount points
  while read -r PCT MNT; do
    if (( PCT > DISK_THR )); then
      log "⚠️  High Disk usage on $MNT: ${PCT}% (> ${DISK_THR}%)"
    else
      log "✅ Disk $MNT: ${PCT}%"
    fi
  done < <(check_disk_usage)

  sleep "$INTERVAL"
Done

Run it:

chmod +x monitor.sh
sudo ./monitor.sh 10  # check every 10 seconds

Optional: pipe alerts to email/Slack/Teams using curl/webhooks.


2) ssh_key_exchange.sh — Distribute Your SSH Key to Many Hosts

This script loops over hosts from hosts.txt, generates an SSH key if you don’t have one, and then runs ssh-copy-id to set up passwordless access.

File: ssh_key_exchange.sh

#!/usr/bin/env bash
set -euo pipefail

HOSTS_FILE=${1:-hosts.txt}
KEY_PATH="${HOME}/.ssh/id_ed25519"

if [[ ! -f "$KEY_PATH" ]]; then
  echo "[+] No key found. Generating $KEY_PATH"
  ssh-keygen -t ed25519 -N "" -f "$KEY_PATH"
fi

while IFS= read -r host; do
  [[ -z "$host" || "$host" =~ ^# ]] && continue
  echo "[+] Copying key to $host"
  ssh-copy-id -i "$KEY_PATH.pub" "$host"
Done < "$HOSTS_FILE"

Example hosts.txt:

ubuntu@10.0.0.11
root@192.168.1.100
admin@server.example.com

Run it:

chmod +x ssh_key_exchange.sh
./ssh_key_exchange.sh hosts.txt

3) remote_exec.sh — Run Commands on Multiple Servers

This script loops over the same hosts.txt and executes any command you pass. It’s intentionally simple; you can enhance it with parallel execution (parallel or xargs -P), timeouts, retry logic, JSON output, etc.

File: remote_exec.sh

#!/usr/bin/env bash
set -euo pipefail

if [[ $# -lt 1 ]]; then
  echo "Usage: $0 <hosts-file> [command...]"
  exit 1
fi

HOSTS_FILE=$1; shift || true
CMD=${*:-'hostname && uptime'}

while IFS= read -r host; do
  [[ -z "$host" || "$host" =~ ^# ]] && continue
  echo "\n====== $host ======"
  ssh -o BatchMode=yes -o ConnectTimeout=5 "$host" "$CMD" || echo "[!] Failed to run on $host"
Done < "$HOSTS_FILE"

Run it:

chmod +x remote_exec.sh
./remote_exec.sh hosts.txt "uname -a && df -h"

Bonus: Make Them Systemd Services or Cron Jobs

  • Cron example (run every 5 minutes):

      */5 * * * * /path/to/monitor.sh 5 >> /var/log/devops/monitor_cron.log 2>&1
    
  • Systemd unit (for monitor.sh):

      [Unit]
      Description=Simple DevOps Monitor
    
      [Service]
      ExecStart=/usr/local/bin/monitor.sh 5
      Restart=always
      User=root
    
      [Install]
      WantedBy=multi-user.target
    

What I Learned & Next Steps

  • Loops + files (while read -r) is the cleanest way to iterate over server lists.

  • Parameterization with env vars (CPU_THR, DISK_THR, etc.) makes scripts flexible.

  • Error handling with set -euo pipefail is a must.

DevOps overview as a beginner

Part 42 of 50

Sharing my journey of learning DevOps as a beginner — covering essential tools, cloud setup, CI/CD, Docker, monitoring, and more, step by step with practical examples.

Up next

Day 43 – Intro To Cloud Computing And AWS Global Infrastructure

Introduction to AWS Global Infrastructure and Cloud Computing Essentials