← Interview Prep

Practical Bash & Ops Tasks — SRE

Hands-on SRE/DevOps screen tasks with reference solutions and the gotchas: backups, cron, disk-usage alerts, Nginx, SSH hardening, user creation, kill-by-port, logrotate, patching, iptables.

The hands-on half of an SRE/DevOps screen: write the script, schedule it, harden the box. Each task below is a common prompt with a clean reference solution and the gotcha an interviewer listens for.

Say your assumptions out loud (paths, idempotency, error handling) and prefer set -euo pipefail in real scripts. The snippets stay minimal for readability.

Scripting & automation

1 · Back up /etc with a timestamp

#!/bin/bash
set -euo pipefail
TIMESTAMP=$(date +%F_%H-%M-%S)
BACKUP_DIR="/backup/etc_$TIMESTAMP"
mkdir -p "$BACKUP_DIR"
cp -a /etc/. "$BACKUP_DIR"        # -a preserves perms/owners/symlinks
echo "Backup of /etc completed at $BACKUP_DIR"

Gotcha: use cp -a (archive) so permissions and symlinks survive; avoid : in the dir name (awkward on some tools) — hence %H-%M-%S.

2 · Schedule it every Sunday at 01:00 (cron)

# crontab -e, then:
0 1 * * Sun /usr/local/bin/backup_etc.sh
# fields: min hour day-of-month month day-of-week

3 · Alert when a partition exceeds 80%

#!/bin/bash
MAX=80
EMAIL="ops@example.com"
df -P | grep -vE '^Filesystem|tmpfs|cdrom' | awk '{ print $5" "$1 }' | while read use part; do
  use=${use%\%}
  if [ "$use" -ge "$MAX" ]; then
    echo "Low space on $part ($use%)" | mail -s "Disk alert: $part $use%" "$EMAIL"
  fi
done

Gotcha: df -P (POSIX) keeps each mount on one line so awk columns don't shift; strip the % before the numeric compare.

6 · Create user1..user10

#!/bin/bash
for i in $(seq 1 10); do
  useradd "user$i" && echo "created user$i"
done

9 · Patch packages and log it

#!/bin/bash
{ apt-get update && apt-get upgrade -y; } >> /var/log/system_update.log 2>&1
# RHEL: dnf -y upgrade >> /var/log/system_update.log 2>&1

Services & the box

4 · Install & serve a static site with Nginx

sudo apt update && sudo apt install -y nginx
sudo systemctl enable --now nginx
echo "Hello World" | sudo tee /var/www/html/index.html
# verify: curl -s localhost | head

7 · Find & kill whatever holds port 8080

#!/bin/bash
PID=$(lsof -t -i:8080 || true)     # or: fuser 8080/tcp ; ss -ltnp 'sport = :8080'
if [ -n "$PID" ]; then
  kill "$PID"                       # try graceful (SIGTERM) first
  sleep 2; kill -9 "$PID" 2>/dev/null || true
  echo "killed $PID on :8080"
else
  echo "nothing on :8080"
fi

Gotcha: reach for SIGTERM before SIGKILL so the process can flush and exit cleanly.

8 · Rotate a custom app log

# /etc/logrotate.d/myapp
/var/log/myapp.log {
    weekly
    rotate 5
    missingok
    notifempty
    compress
    delaycompress
    copytruncate      # or a postrotate that signals the app to reopen its log
}

Gotcha: if you don't copytruncate (or signal the daemon), it keeps writing to the old, now-unlinked fd — the (deleted)-file disk leak.

Security & firewall

5 · Harden SSH (no root login, port 2222)

# /etc/ssh/sshd_config
PermitRootLogin no
Port 2222
# then: sudo systemctl restart sshd
# open the port in the firewall FIRST, and keep an existing session open to avoid lockout

10 · iptables: allow only SSH on 2222

#!/bin/bash
iptables -F
iptables -A INPUT -i lo -j ACCEPT                                   # don't break loopback
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT    # keep replies flowing
iptables -A INPUT -p tcp --dport 2222 -j ACCEPT
iptables -P INPUT DROP                                              # default-deny policy
iptables-save > /etc/iptables/rules.v4

Gotcha: the two lines interviewers watch for — allow lo and ESTABLISHED,RELATED — without them you cut your own return traffic and loopback.

Bonus: passwords that never expire

chage -M -1 alice        # disable max-age password expiry for a user
chage -l alice           # show aging settings
passwd -S alice          # status
Related: Linux Fundamentals Q&A · Linux Basics & Troubleshooting.