Linux & Shell for SDET

29Linux & Shell for SDET

What you will master here

  • Filesystem layout + permissions
  • Navigating + searching files (find, grep, sed, awk)
  • Pipes, redirects, exit codes
  • Processes, jobs, signals
  • Networking basics (curl, netstat, ss, lsof)
  • Shell scripting for test infra
  • Environment variables, dotfiles
  • SSH + scp essentials

29.1 Filesystem & permissions

/etc      # system config
/var/log  # log files
/tmp      # temp (cleared on reboot)
/home/x   # user home (~/ shortcut)
/usr/bin  # standard programs
/opt      # third-party software

# Permissions: rwx for owner, group, others
ls -l file.txt        # -rw-r--r-- 1 yash staff 200 ...
chmod 755 script.sh   # rwxr-xr-x
chmod +x script.sh    # add execute
chown user:group f    # change owner
sudo cmd              # run as root

chmod numeric reference

DigitMeans
7 (rwx)read + write + execute
6 (rw-)read + write
5 (r-x)read + execute
4 (r--)read only
0 (---)none

29.2 Navigation & search

cd ~/work; cd -          # toggle to previous dir
ls -lah                  # long, hidden, human-readable sizes
tree -L 2                # 2 levels deep

# find — by name, type, size, mtime
find . -name "*.spec.ts"
find . -type f -size +1M           # files larger than 1MB
find . -mtime -1                   # modified in last 24h
find . -name "*.log" -delete

# grep — by content
grep -rni "TODO" src/              # recursive, case-insensitive, line numbers
grep -l "pattern" -r .             # only filenames
grep -E "fail|error" test.log      # extended regex (alt: egrep)
grep -v "debug"                    # invert match
grep -A 3 -B 2 "error" log.txt     # context lines

# sed — stream edit
sed -i 's/foo/bar/g' file.txt      # in-place replace
sed -n '10,20p' file.txt           # print lines 10-20

# awk — field-aware
awk '{print $1, $3}' file          # columns 1 and 3
awk -F',' '{sum += $2} END {print sum}' data.csv  # sum column 2

29.3 Pipes, redirects, exit codes

cmd1 | cmd2           # stdout of 1 → stdin of 2
cmd > file            # stdout → file (overwrite)
cmd >> file           # append
cmd 2> err.log        # stderr → file
cmd > out 2>&1        # both stdout + stderr → file
cmd < input.txt       # stdin from file
cmd1 && cmd2          # run cmd2 only if cmd1 succeeded
cmd1 || cmd2          # run cmd2 only if cmd1 failed
cmd1 ; cmd2           # run both regardless

# Exit code of the last command
echo $?               # 0 = success, nonzero = failure
# CI scripts rely on this — fail the build on nonzero

29.4 Processes, jobs, signals

ps aux | grep playwright    # list processes
top                          # interactive process viewer
htop                         # nicer alternative

kill 12345                   # SIGTERM (polite)
kill -9 12345                # SIGKILL (force)
pkill -f playwright          # kill by name pattern

# Background jobs
long-cmd &          # run in background
jobs                # list shell jobs
fg                  # bring last back to foreground
bg                  # resume in background
disown              # detach so it survives shell exit
nohup long-cmd &    # immune to SIGHUP, output → nohup.out

29.5 Networking

curl -i https://api.example.com/users          # show headers
curl -X POST -H 'Content-Type: application/json' -d '{"x":1}' url
curl -u user:pass url                          # basic auth
curl -o file.zip url                           # save to file
curl -w "%{http_code} %{time_total}s\n" url   # custom timing

# Port checks
nc -vz host 5432              # is port open?
ss -tlnp                      # listening TCP sockets (modern netstat)
lsof -i :3000                 # who's using port 3000?

# DNS
dig example.com               # query DNS
nslookup example.com
host example.com

# Network tools
ping example.com
traceroute example.com
mtr example.com               # combo ping + traceroute

29.6 Shell scripting essentials

#!/usr/bin/env bash
set -euo pipefail   # exit on error, undefined var, pipe failure

NAME="${1:-default}"           # first arg or 'default'
echo "Hi, $NAME"

# Conditions
if [[ -f config.yml ]]; then
  echo "config exists"
fi
if [[ "$ENV" == "prod" || "$ENV" == "staging" ]]; then
  echo "remote env"
fi

# Loops
for f in *.log; do
  gzip "$f"
done

# Functions
log() { echo "[$(date -Iseconds)] $*"; }
log "starting"

# Command substitution
COUNT=$(ls -1 | wc -l)
LATEST=$(ls -t | head -1)

# Arrays
files=(a.txt b.txt c.txt)
for f in "${files[@]}"; do echo "$f"; done

29.7 Environment variables & dotfiles

export DATABASE_URL=postgres://localhost/test
echo $DATABASE_URL
env                    # all env vars
unset DATABASE_URL

# Where envs live
~/.bashrc      # per-shell config (bash)
~/.zshrc       # zsh
~/.profile     # login shells
~/.bash_profile

# Project-local
.env           # loaded by dotenv libs (not the shell)
direnv         # auto-load .envrc when you cd into a dir

29.8 SSH + scp

# Generate key
ssh-keygen -t ed25519 -C "you@host"
cat ~/.ssh/id_ed25519.pub                  # add this to GitHub / server

# Connect
ssh user@host
ssh -i ~/.ssh/key.pem user@ec2-host
ssh -p 2222 user@host                       # custom port

# Run remote command + return
ssh user@host "ls /var/log"

# Copy files
scp file.txt user@host:/tmp/
scp -r dir/ user@host:~/

# Tunnel local → remote
ssh -L 5432:db.internal:5432 jump-host
# now local localhost:5432 → db.internal:5432 via jump-host

29.9 Useful SDET one-liners

# Count test failures in a JUnit XML
grep -c '<failure' results.xml

# Largest files
du -sh */ | sort -h | tail -10

# Tail logs from multiple files
tail -f app.log db.log | grep -i error

# Wait for a port to open before continuing (in CI)
until nc -z localhost 3000; do sleep 1; done

# Free disk per partition
df -h

# Memory + CPU snapshot
top -b -n 1 | head -20

# Find tests last modified in past day
find tests -name "*.spec.ts" -mtime -1

Module 51 — Linux Q&A

How do you check if a port is in use?
lsof -i :3000 shows the process. ss -tlnp lists all listening sockets. nc -vz host port tests reachability from another host.
What does set -euo pipefail do?
Defensive bash. -e: exit on any command failure. -u: error on undefined variable. -o pipefail: pipeline fails if ANY command in it fails (not just the last). Put at top of every script.
Difference between > and >>?
> overwrites the file. >> appends. Same for 2> vs 2>> with stderr.
How do you redirect stderr to stdout?
cmd 2>&1 — sends stderr to wherever stdout currently goes. Common pattern: cmd > all.log 2>&1 sends both to all.log.
How do you find files modified in the last hour?
find . -mmin -60 for minutes; find . -mtime -1 for the last day. Combine with -name and -size for tighter filters.
What's the difference between grep -l and grep -L?
-l prints only files that MATCH. -L prints only files that DON'T match. Useful with xargs for follow-up actions.
What's $??
Exit code of the previous command. 0 = success, nonzero = failure. CI scripts depend on it to know whether a step succeeded.
How do you wait for a service to be ready in CI?
Poll loop: until nc -z localhost 3000; do sleep 1; done. Or use a health endpoint: until curl -fs localhost:3000/health; do sleep 1; done. Add a timeout to avoid forever-waits.
What's nohup for?
"No hangup" — makes a command immune to the HUP signal when the shell exits. nohup long-task & survives SSH disconnect. Output goes to nohup.out by default.
SIGTERM vs SIGKILL?
SIGTERM (15): polite shutdown — process can catch it and clean up. SIGKILL (9): unconditional kill, kernel removes the process. Always try SIGTERM first.
How does an SSH tunnel work?
ssh -L localPort:targetHost:targetPort jumpHost forwards localhost:localPort over the SSH connection to jumpHost, which then forwards to targetHost:targetPort. Used to reach internal services from your laptop.
What's the difference between .bashrc and .bash_profile?
.bash_profile runs for LOGIN shells (SSH session, console). .bashrc runs for INTERACTIVE non-login shells (new terminal window after login). Most setups source .bashrc from .bash_profile so both work the same.