← Back to blog

Bash REPL vs Scripts: When to Use Each

· 5 min read · Stew Team
bashreplscriptsautomation

Every DevOps engineer faces this choice: run commands interactively in the bash REPL or write a script? Both have their place, but choosing wrong wastes time.

This guide helps you decide when to use each approach. For turning REPL work into documentation, see how to save terminal commands.

The Fundamental Difference

Bash REPL: Interactive, exploratory, immediate feedback Scripts: Automated, repeatable, self-contained

# REPL: Run, see output, decide next step
$ kubectl get pods
$ kubectl logs problematic-pod
$ kubectl delete pod problematic-pod

# Script: All steps predetermined
#!/bin/bash
POD=$(kubectl get pods -o jsonpath='{...}')
kubectl logs $POD
kubectl delete pod $POD

When to Use the Bash REPL

Exploration and Discovery

You don’t know what you’ll find:

# Exploring an unfamiliar system
$ ls /etc/
$ cat /etc/nginx/nginx.conf
$ nginx -t
$ grep -r "upstream" /etc/nginx/

Each command informs the next. Scripts can’t adapt like this.

Debugging

Problems require investigation:

$ systemctl status app
$ journalctl -u app --since "10 minutes ago"
$ strace -p $(pgrep app) -f
$ lsof -p $(pgrep app)

You follow the trail wherever it leads.

One-Time Tasks

No point scripting what you’ll never repeat:

# One-time data migration
$ pg_dump old_db > backup.sql
$ createdb new_db
$ psql new_db < backup.sql

Learning and Experimentation

Test ideas interactively:

# Figuring out jq syntax
$ echo '{"a":1}' | jq '.a'
$ echo '{"a":1}' | jq '.a + 1'
$ cat data.json | jq '.items[].name'

Immediate feedback accelerates learning.

When to Write Scripts

Repeated Tasks

If you’ll do it again, script it:

#!/bin/bash
# deploy.sh - Used weekly

set -euo pipefail

echo "Pulling latest..."
git pull origin main

echo "Building..."
docker build -t app:latest .

echo "Deploying..."
kubectl apply -f k8s/

Complex Logic

Conditionals and loops need structure:

#!/bin/bash
# health-check.sh

for service in api worker scheduler; do
    status=$(curl -s "http://$service/health" | jq -r '.status')
    if [[ "$status" != "healthy" ]]; then
        echo "ALERT: $service is $status"
        notify-team "$service is unhealthy"
    fi
done

Scheduled Jobs

Cron needs scripts:

# /etc/cron.daily/backup
#!/bin/bash
pg_dump production > /backup/prod-$(date +%Y%m%d).sql
find /backup -mtime +7 -delete

Shared Procedures

Team members need consistent execution:

#!/bin/bash
# onboarding.sh - Used by every new team member

create_user "$1"
add_to_groups "$1" dev docker
setup_ssh_key "$1"
clone_repos "$1"

Error Handling Required

Production automation needs safety:

#!/bin/bash
set -euo pipefail
trap 'echo "Error on line $LINENO"; cleanup' ERR

# Safe to run automatically

The Gap Between REPL and Scripts

Neither is perfect:

REPL problems:

  • Commands are lost
  • Context isn’t documented
  • Can’t easily share
  • No error handling

Script problems:

  • Takes time to write
  • Rigid execution flow
  • Overhead for simple tasks
  • Must anticipate all cases

The Middle Ground: Executable Runbooks

Runbooks bridge REPL and scripts:

# Deploy Application

## Pre-flight checks
​```bash
kubectl get nodes
kubectl get pods -n production | grep -v Running
​```

## Deploy
​```bash
kubectl apply -f deployment.yaml
​```

## Verify
​```bash
kubectl rollout status deployment/app
​```

## Rollback (if needed)
​```bash
kubectl rollout undo deployment/app
​```

Like REPL:

  • Run commands step-by-step
  • See output, decide next action
  • Adapt to what you find

Like scripts:

  • Documented and shareable
  • Repeatable process
  • Version controlled

Decision Framework

SituationUse REPLUse ScriptUse Runbook
First time doing something
Debugging unknown issue
Repeated automation
Scheduled jobs
Operational procedures
Incident response
Team onboarding tasks
Complex with human decisions

Converting REPL to Script

When REPL exploration becomes repeated:

# REPL session that worked
$ docker build -t app .
$ docker tag app registry/app:v1.2
$ docker push registry/app:v1.2
$ kubectl set image deployment/app app=registry/app:v1.2

# Convert to script
#!/bin/bash
set -euo pipefail
VERSION=${1:?Usage: deploy.sh VERSION}
docker build -t app .
docker tag app "registry/app:$VERSION"
docker push "registry/app:$VERSION"
kubectl set image deployment/app "app=registry/app:$VERSION"

Converting Script to Runbook

When scripts need human judgment:

# Script that often needs intervention
#!/bin/bash
kubectl delete pods -l app=api
sleep 30
kubectl get pods -l app=api
# What if pods don't come back?
# API Pod Restart

## Delete current pods
​```bash
kubectl delete pods -l app=api
​```

## Wait for recreation
​```bash
sleep 30
​```

## Verify pods are running
​```bash
kubectl get pods -l app=api
​```

## If pods stuck in Pending
​```bash
kubectl describe pods -l app=api | grep -A5 Events
​```

## If resource issues, scale down other workloads
​```bash
kubectl scale deployment/batch-processor --replicas=0
​```

Stew: Best of Both Worlds

Stew gives you REPL-style interactivity with script-style documentation:

  • Write procedures in markdown
  • Run commands with a click
  • See output inline
  • Share with your team
  • Version control everything

Your bash REPL explorations become executable team knowledge.

Join the waitlist and stop choosing between interactive and automated.