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.
/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.
# crontab -e, then:
0 1 * * Sun /usr/local/bin/backup_etc.sh
# fields: min hour day-of-month month day-of-week
#!/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.
#!/bin/bash
for i in $(seq 1 10); do
useradd "user$i" && echo "created user$i"
done
#!/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
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
#!/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.
# /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.
# /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
#!/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.
chage -M -1 alice # disable max-age password expiry for a user
chage -l alice # show aging settings
passwd -S alice # status