Your country

Tools that support it use your country for local currency, number formats, units and paper size. Your choice is saved only in this browser.

Type a name or a two-letter code. Use the up and down arrow keys to move through the countries, Enter to choose one and Escape to close.

Bash & the POSIX Shell Module 9

Robust scripts: errors, traps and debugging interview questions

Interview questions on “Robust scripts: errors, traps and debugging”: warm-ups, then what each harder question tests and how a good answer starts.

12 questions: 4 warm-ups and 8 with model answers · Levels: Fresher to senior

Warm-up questions

Short questions with short answers, each answered in full.

  1. Fresher to mid

    What does set -e not do?

    Answered in the lesson set -e, set -u and pipefail: what they really do

  2. Fresher to mid

    What does trap "commands" EXIT guarantee, and what does it not?

    It guarantees that Bash runs commands when the shell exits: at the end of the script, at an exit, when set -e stops it, and, in Bash 5.3, when an INT, TERM or HUP with no trap of its own ends it. It does not cover SIGKILL (kill -9, the Linux OOM killer), which signal(7) says cannot be caught, and it does not promise that commands finish: a power cut can stop them half-way. It is also not portable: dash runs no EXIT trap when a signal ends the script, so a script for sh traps INT and TERM as well. Write the cleanup so that it is safe to run twice and touches only what the script created.

    From the lesson Traps and cleanup: EXIT, ERR and signals

  3. Fresher to mid

    Why do errors go to stderr instead of stdout, and how is >&2 read?

    Answered in the lesson Error-handling patterns for scripts

  4. Fresher to mid

    What does bash -x script show that a plain bash script does not?

    Answered in the lesson Debugging: bash -x, PS4, trap DEBUG and logs

Questions with model answers

What each question tests, the first step of a good answer and the follow-ups to expect.

  1. Mid to senior

    A deploy script starts with set -e and runs rm -rf "$build_dir/old". A rename in the pipeline config left build_dir unset, and the script deleted /old and everything in it. Explain why set -e did not stop it, and write the preamble and the guard that would have.

    What it tests
    Knowing that set -e reads only exit statuses, that an unset variable expands to nothing unless something turns the expansion into an error, and how to guard a destructive command.
    First step
    Trace the expansion before blaming set -e. build_dir was unset, so "$build_dir/old" became "/old", and rm -rf /old succeeded: the shell saw a status of 0. Then ask which option or expansion form turns a missing value into an error before rm runs.
    Follow-ups

    From the lesson set -e, set -u and pipefail: what they really do

    Model answer, Pro. Model answers open with any pass; prices are in the notice on this page.

    Opening the model answers with your pass…

    Model answers open with any MySmartCoPilot pass.

    • Pro pass · 1 week₹79$2.99
    • 30 days₹179$5.99
    • 1 year₹1,699$45

    One payment; a pass never renews. The price shown is the total you pay: no fees or charges are added at checkout.

    It also opens every other in-depth part in Learn and every Pro tool. Sales are final, except where the law gives you a right to withdraw, for example in the EU and the UK (refund policy).

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 4 minutes
  2. Mid to senior

    A release script runs under set -euo pipefail and picks the newest build with ls -t builds/ | head -n 1. It passed for a year. Since builds/ grew past 3,000 entries, most runs stop with status 141 and a few still pass. Explain the 141 and why it flaps, then fix the line without turning pipefail off.

    What it tests
    Reading 141 as 128 + 13 (SIGPIPE), knowing which stage is killed when a reader exits early, seeing that output size and timing decide the race, and fixing it so that every other failure stays visible.
    First step
    Decode the number before touching the script: 141 is 128 + 13, and 13 is SIGPIPE, so a stage was killed while writing to a pipe whose reader had gone. head -n 1 leaves after one line, so the writer is ls. Then ask what changed: not the script but the size of the listing. Compare ls -t builds/ | wc -c with the size of a pipe.
    Follow-ups

    From the lesson set -e, set -u and pipefail: what they really do

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 5 minutes
  3. Mid to senior

    A service writes /var/run/import.lock when it starts and removes it in an EXIT trap. After the OOM killer ended it, the lock stayed, and every later start refused with "lock held". No trap can run after SIGKILL, so design a lock that recovers without one, and say what each design can still get wrong.

    What it tests
    Designing a lock that does not depend on cleanup code: a PID with a liveness check, or a kernel lock that is released when the holder's descriptors close, and knowing where each one fails.
    First step
    Stop trying to make the cleanup run; it cannot after SIGKILL. Ask instead what the next start can check for itself to tell a live holder from a dead one, and whether the operating system can do the releasing.
    Follow-ups

    From the lesson Traps and cleanup: EXIT, ERR and signals

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 4 minutes
  4. Mid to senior

    A build script sets workdir=./out at the top. A helper function declares local workdir, fills it with mktemp -d and sets trap 'rm -rf -- "$workdir"' EXIT, single-quoted as ShellCheck asks. When the script ended, ./out and its results were gone and the temporary folder was still there. Explain what ran, and fix it.

    What it tests
    Knowing that a single-quoted trap expands when it runs and in the scope it runs in, that a local variable is gone by then, and how to fix the value at set time safely.
    First step
    Ask when and where the action is expanded. The single quotes delay the expansion until the trap runs, so work out which workdir exists at that moment: the function's local one, or the script's own.
    Follow-ups

    From the lesson Traps and cleanup: EXIT, ERR and signals

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 4 minutes
  5. Mid to senior

    A nightly import reads records.csv with while IFS=, read -r id amount && [ -n "$id" ]; do import_one; done. It ran green for weeks. The night the export held a blank line after its third record, the job imported 3 records, skipped the 180 below it, and still exited 0. Explain why, and make such a shortfall impossible to miss.

    What it tests
    Knowing how a while loop ends and what status it returns, telling "skip this line" apart from "stop reading", and checking a batch's counts so that a silent shortfall fails the job.
    First step
    Separate "the loop ended" from "the records were imported". Ask what ends this loop, what status a while loop returns when its condition fails, and how many lines the file really holds compared with how many the job counted.
    Follow-ups

    From the lesson Error-handling patterns for scripts

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 4 minutes
  6. Mid to senior

    A deploy job runs cd build && make install from its checkout. On one CI runner it installed another project's files: the job log showed an unexpected absolute path just before make ran, every status was 0, and ShellCheck reports nothing. cd did not fail. What happened, and how do you make the script immune?

    What it tests
    Knowing that cd searches CDPATH for a name without a leading slash and prints the folder it chose, that a successful cd can still land in the wrong place, and how a script guards its folder.
    First step
    Start from the clue in the log: cd prints a path only in a few cases, so work out which one applied. Compare the environment of the odd runner with the others, and look for a variable that changes where cd looks.
    Follow-ups

    From the lesson Error-handling patterns for scripts

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 4 minutes
  7. Mid to senior

    A monitoring script reads a queue count and pages the on-call engineer when it is over 100. It works in testing. In production, about one run in three logs "[: : integer expected" and sends no page, even when the queue is over 100; a rerun by hand passes. Walk through narrowing the bug on that host, and fix it.

    What it tests
    Turning on a trace on a production host without flooding its logs, reading the test builtin's message and the trace line above it, and finding why a value read from outside is sometimes empty.
    First step
    Make a failing run show its values. Add a switch near the top, [ -n "${TRACE-}" ] && { exec 3>>trace.log; BASH_XTRACEFD=3; set -x; }, run the job with TRACE=1 until it fails once, and read the trace lines just above the error: they show the command and the values it really received.
    Follow-ups

    From the lesson Debugging: bash -x, PS4, trap DEBUG and logs

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 5 minutes
  8. Mid to senior

    A CI job runs its deploy script under set -x, and the job log, which a dozen engineers can read, holds a line "+ TOKEN=tok_9f3c…" and the same token again inside a curl -H argument. Walk through what leaked, how to stop it without giving up the trace, and the check that catches the next slip.

    What it tests
    Knowing that xtrace prints every expanded word, keeping secret-handling lines out of the trace, keeping secrets off command lines, and limiting who can read a trace.
    First step
    Count what leaked and where. Each trace line is a command as Bash was about to run it, so the token appears on the assignment and again in the curl argument. Then list everyone and everything that can read that log, including the copies the CI keeps, because the token has to be treated as known to all of them.
    Follow-ups

    From the lesson Debugging: bash -x, PS4, trap DEBUG and logs

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 5 minutes

All Bash & the POSIX Shell interview questions · The Bash & the POSIX Shell track

Quick answers and tool search

Type to search tools or to get a quick answer, for example 18% of 2500. Use the up and down arrow keys to move through the results, Enter to choose, and Escape to close.