What Interviewers Are Actually Testing
Bash interview questions rarely test syntax memorization; they test whether you understand the shell's execution model well enough to predict behavior you haven't seen before, because bash's quirks (word splitting, subshells, exit code propagation) are exactly the kind of thing that separates someone who has written a few scripts from someone who has debugged production incidents caused by them. A strong candidate explains *why* $var without quotes is dangerous, not just that it 'should be quoted', and can reason through a pipeline's variable scoping without having memorized the specific example beforehand.
Cricket analogy: It's like a selector testing a batter against a genuinely unfamiliar left-arm wrist-spinner in the nets, not asking them to recite the textbook definition of googly — the goal is to see actual reasoning under novel conditions.
Common Categories: Quoting, Exit Codes, and Subshells
The most frequently asked category involves predicting output: given a script with unquoted variables, a for loop over $(ls *.txt), or a variable assignment inside a while read loop fed by a pipe, what actually happens? The pipe question specifically tests whether you know that cmd | while read line; do var=$line; done runs the loop in a subshell, so $var is unset again after the loop ends — a classic gotcha that trips up experienced engineers who haven't hit it before, and the fix (while read line; do ...; done < <(cmd) using process substitution) is a common follow-up question testing whether you know an alternative that avoids the subshell entirely.
Cricket analogy: The subshell variable-scoping gotcha is like a substitute fielder's brilliant tactical adjustment during a boundary-rope save not counting toward the official team strategy discussion, because they were never really part of the core XI's huddle.
# Classic interview gotcha: this prints 0, not the actual line count
count=0
cat file.txt | while read -r line; do
count=$((count + 1))
done
echo "$count" # => 0, because the while loop ran in a subshell
# Fix: process substitution avoids the pipe-induced subshell
count=0
while read -r line; do
count=$((count + 1))
done < <(cat file.txt)
echo "$count" # => correct count, loop ran in the current shellExit Codes, $? Timing, and Signal Handling
Interviewers frequently probe $? timing because it's a subtle trap: $? always refers to the exit status of the *most recently executed* command, so inserting even an echo for debugging between a command and its $? check silently breaks the check, since $? now reflects the echo, not the original command. Similarly, questions about exit codes above 128 test whether you know that a process killed by signal N typically exits with code 128 + N (a process killed by SIGKILL, signal 9, exits 137, and SIGTERM, signal 15, exits 143), which is directly useful for interpreting Docker container exit codes or kill-related script failures in production.
Cricket analogy: The $? timing trap is like a scorer recording the outcome of the *most recent* ball bowled, so if you ask about a wicket from three balls ago after two dot balls have since been bowled, the record no longer reflects the wicket you meant.
A reliable interview answer for capturing $? safely: assign it immediately, rc=$?, before running any other command (even echo), then use $rc for all subsequent logic — this is the pattern every production error-handling script should follow.
Watch for interviewers asking about local inside functions: forgetting local on a variable inside a bash function makes it global by default, which can silently clobber a caller's variable of the same name — a frequently asked 'spot the bug' question.
- Interviewers test execution-model understanding (why quoting matters, why subshells isolate variables) rather than syntax recall.
cmd | while read ...; doneruns the loop in a subshell, so variables set inside it don't persist afterward — a top interview gotcha.- Process substitution (
done < <(cmd)) is the standard fix that avoids the pipe-induced subshell entirely. $?reflects only the most recently executed command, so it must be captured immediately (rc=$?) before any other command runs.- Exit codes above 128 typically indicate death by signal: 128 + signal number (137 = SIGKILL, 143 = SIGTERM).
- Forgetting
localinside a bash function leaks the variable into global scope, a common 'spot the bug' interview question. - Strong answers explain the underlying shell behavior (subshells, expansion order, exit status propagation), not just the fix.
Practice what you learned
1. Why does `count=0; cat file | while read -r line; do count=$((count+1)); done; echo $count` print 0?
2. What bash construct fixes the pipe-induced subshell problem for a while-read loop without changing its logic?
3. What exit code would a process typically report if it was killed by SIGKILL (signal 9)?
4. Why must `rc=$?` be captured immediately after the command of interest, with nothing in between?
5. What happens if you forget the `local` keyword for a variable assigned inside a bash function?
Was this page helpful?
You May Also Like
Bash Script Debugging Techniques
Practical techniques for finding and fixing bugs in bash scripts, from tracing execution with set -x to using ShellCheck and traps for structured diagnostics.
Bash Strict Mode
An explanation of the `set -euo pipefail` pattern known as bash strict mode, what each flag actually does, and where its edge cases can still surprise you.
Defensive Bash Scripting
Techniques for writing bash scripts that fail safely, validate their inputs, and avoid the common footguns that turn a small bug into a production incident.
Related Reading
Related Study Notes in DevOps
Browse all study notesNginx Study Notes
DevOps · 30 topics
DevOpsAnsible Study Notes
DevOps · 30 topics
DevOpsAdvanced Kubernetes Study Notes
Kubernetes · 30 topics
DevOpsApache Kafka Study Notes
Kafka · 30 topics
DevOpsDocker & Kubernetes Study Notes
YAML · 40 topics
DevOpsCI/CD Tools & Pipelines Study Notes
YAML · 37 topics