Your First Script
#!/usr/bin/env bash
set -euo pipefail # exit on error, unset vars, pipe failures
echo "Deploying application..."The shebang (#!/usr/bin/env bash) tells the OS which interpreter to use. set -euo pipefail is a safety net that makes scripts fail fast.
Variables
APP_NAME="my-app"
VERSION="1.0.0"
TIMESTAMP=$(date +%Y%m%d-%H%M%S) # command substitution
echo "Deploying $APP_NAME v$VERSION at $TIMESTAMP"Conditionals
if [ -f "./dist/app.js" ]; then
echo "Build output found"
else
echo "ERROR: build failed" >&2
exit 1
fi
# One-liner
[ -d "/opt/app" ] || mkdir -p /opt/appLoops
# Iterate over files
for file in ./config/*.yml; do
echo "Validating $file"
yamllint "$file"
done
# While loop
RETRIES=0
while ! curl -sf http://localhost:3000/health; do
RETRIES=$((RETRIES + 1))
[ $RETRIES -ge 5 ] && { echo "Service failed to start"; exit 1; }
sleep 2
doneFunctions
log() {
echo "[$(date +%T)] $*"
}
wait_for_service() {
local url="$1"
local max_attempts="${2:-10}"
local attempt=0
until curl -sf "$url" > /dev/null; do
attempt=$((attempt + 1))
[ $attempt -ge $max_attempts ] && return 1
log "Waiting for $url (attempt $attempt)..."
sleep 3
done
log "$url is up"
}
wait_for_service "http://localhost:8080/health"A Real Deploy Script
#!/usr/bin/env bash
set -euo pipefail
APP="my-app"
DEPLOY_DIR="/opt/$APP"
ARTIFACT="${1:?Usage: deploy.sh <artifact.tar.gz>}"
log() { echo "[$(date +%T)] $*"; }
log "Starting deployment of $ARTIFACT"
tar -xzf "$ARTIFACT" -C "$DEPLOY_DIR"
systemctl restart "$APP"
log "Deployment complete"Always quote your variables ("$VAR") to handle filenames with spaces. Always set -euo pipefail at the top of scripts you run in CI.