Bash & the POSIX Shell Module 12
Processes, jobs and signals interview questions
Interview questions on processes, jobs and signals: short warm-ups, then what each harder question tests, the first step of a good answer and its follow-ups.
Warm-up questions
Short questions with short answers, each answered in full.
-
Fresher to mid
What does a subshell copy from its parent, and what can it change there?
Answered in the lesson Subshells and the execution environment
-
Fresher to mid
What does $! hold, and what do wait PID and a bare wait each return?
Answered in the lesson Background jobs, wait and parallel work
-
Fresher to mid
What blocks when you open a FIFO, and what does a reader see after the last writer closes?
-
Fresher to mid
Three jobs ended with statuses 130, 137 and 143. What does each number tell you, and what produced it?
-
Fresher to mid
What does Ctrl-Z send to a running command, and what do bg, fg and jobs do next?
Ctrl-Z makes the terminal send SIGTSTP to the foreground process group, which pauses the job and returns the prompt; the shell prints a line such as [1]+ Stopped with the job number. The job is paused, not ended, and stays in the shell's job table. jobs lists the table with each job's number, its state and its command line, and + and - mark the current and previous jobs. bg sends the paused job SIGCONT and lets it run in the background, as if it had been started with &, so the shell takes commands again. fg also continues the job but gives it the terminal, so the shell waits for it and keyboard input and Ctrl-C go to the job. With no argument, both act on the current job; %n or %name picks another.
From the lesson Job control: Ctrl-Z, fg, bg, jobs, disown
Questions with model answers
What each question tests, the first step of a good answer and the follow-ups to expect.
-
Mid to senior
A shared library has
die() { echo "FATAL: $*" >&2; exit 1; }. A script callssettings=$(load_settings)whereload_settingscallsdiewhen the file is missing. The script runs to completion with empty settings and deploys with defaults. What went wrong and how do you fix it?- What it tests
- Explain why exit did not end the script, list at least two fixes and say which works in a pipeline.
- First step
- The
$(...)ran in a subshell, soexit 1ended only that subshell. The parent continued with an emptysettingsand status 1 in$?. Add a check right after the assignment:settings=$(load_settings) || exit 1. - Follow-ups
-
- What if the same pattern is used inside a pipeline stage?
- Does
set -ecatch this automatically? - How does
shopt -s inherit_errexitchange the behaviour? - Could die signal the parent instead of calling exit?
From the lesson Subshells and the execution environment
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.
Passes can’t be bought right now, so the model answers can’t be opened at the moment. If you have a pass, enter your licence key.
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 5 minutes
-
Mid to senior
A deploy script starts rsync to 12 hosts, each with &, and ends with a bare wait. Two hosts failed, yet the script exited 0 and the release was marked done. The team now needs to run four at a time, on macOS laptops (Bash 3.2) as well as Linux CI. Redesign the loop.
- What it tests
- Whether you know a bare wait returns 0 and hides per-job failures, can collect each status by PID, can cap concurrency with a wait -n pool, and can fall back to a batch pool for Bash 3.2.
- First step
- Reproduce the false success first: a bare wait returns 0 whatever the jobs did, so two failed transfers never changed the exit status. The fix has two independent parts. For the statuses, save each PID as its host starts and wait on each one, recording the hosts that came back non-zero. For the limit and portability, decide between a wait -n pool and a batch pool before writing either.
- Follow-ups
-
- Why did the bare wait return 0 even though two of the rsync jobs failed?
- How do you cap the run at four at a time on Bash 5 but still run on a stock macOS Bash 3.2?
- How would you name exactly which hosts failed, rather than reporting one combined status?
- When would xargs -P be a better fit than a hand-written pool here, and when worse?
From the lesson Background jobs, wait and parallel work
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 4 minutes
-
Mid to senior
A CI step runs ./start-server.sh, which ends with server &, and the script exits 0. On a laptop the step returns at once, but in CI it hangs until the job times out ten minutes later. Explain why, and fix start-server.sh.
- What it tests
- Whether you know a background job inherits the step's standard output, that a pipe stays open until every writer closes it, and how redirecting the job's three streams, nohup or setsid frees the reader.
- First step
- The script exiting 0 is a red herring; the step waits on something else. CI usually reads the step's output through a pipe, and the backgrounded server inherited that pipe's write end, so the reader never sees end of file while the server lives. Reproduce it in the small with a backgrounded writer feeding a pipe into a reader, then ask which redirections hand the job a different output.
- Follow-ups
-
- Why does the same script return at once on a laptop terminal but hang in CI?
- Which redirections free the reader, and why does < /dev/null matter as well as the output ones?
- Does disown fix a job whose descriptor is already shared, and why or why not?
- When is nohup or setsid the right tool here instead of plain redirections?
From the lesson Background jobs, wait and parallel work
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 5 minutes
-
Mid to senior
A build server's logger reads a FIFO with while IFS= read -r line; do printf "[%s] %s\n" "$(date -u +%H%M%S)" "$line"; done < pipe. Five producers write progress to it. When the first finishes, the logger exits and later producers hang or get SIGPIPE. Fix the reader so it survives every producer, and say what each fix costs.
- What it tests
- Understanding that the kernel delivers EOF when the write-count goes to zero; knowing how to keep that count above zero from the reader's own side, or how to re-open after every EOF; and the trade-offs between the two.
- First step
- Trace the shape, not the code. One producer wrote one line and closed; "the last writer" was then that one, and the FIFO had no process open for writing. The reader read EOF and the while loop ended, as the fifo(7) rule says. Then ask what keeps the write count above zero when a producer leaves.
- Follow-ups
-
- Why does exec 3<>pipe keep the write-count above zero, and what does POSIX say about <> on a FIFO?
- A portable fix is an outer while true that re-opens pipe each time EOF arrives; which lines does that lose?
- A producer whose write hits a closed FIFO gets SIGPIPE; what status does the producer end with, and how do you tell it apart from a working run?
From the lesson Named pipes and coprocesses
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 5 minutes
-
Mid to senior
A script does coproc UPPER { tr a-z A-Z; }, then a for loop that writes 200,000 lines of input to UPPER[1], then a loop that reads 200,000 lines from UPPER[0]. On a Mac it hangs after a few thousand lines. Explain the deadlock from first principles, then give two shapes that handle this size of input safely.
- What it tests
- Reading the hang as a pipe-capacity block on both sides, naming the kernel limit the shell hit, and knowing which patterns (background reader, two tempfiles, a plain pipeline) remove the dependency between the two loops.
- First step
- Draw the two pipes and ask what blocks on each one. The shell writes to UPPER[1] and the kernel buffers; when the buffer fills, the next write blocks. tr reads the buffered input and writes uppercase lines to UPPER[0]; when that pipe's buffer fills, its next write blocks too. The shell is not reading UPPER[0] yet, so both ends stop at once. Measure the limit before you touch the script.
- Follow-ups
-
- What is the pipe capacity on this Mac, and how many lines of about 30 characters fit before the first write blocks?
- Why does a plain pipeline tr <<< "$input" > out dodge the deadlock, and when is a coprocess still the right choice?
- If the input must go through a coprocess (shared state across lines), how does a background reader on UPPER[0] break the symmetry?
From the lesson Named pipes and coprocesses
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 5 minutes
-
Mid to senior
Cron runs timeout 600 ./backup.sh every 15 minutes. The log shows status 124, written ten minutes after the limit, and the next run began while this one was still going. backup.sh traps TERM to delete temp files and starts rsync children. Explain what timeout did and why the run overran, then fix the setup.
- What it tests
- Whether you know whom timeout signals, why a TERM handler without an exit lets the script carry on, what 124 reports, and how -k, an exit, a status check and a lock fix it.
- First step
- Reproduce the overrun in the small first: a script with three short steps that traps TERM, removes its temp files and carries on, run under a timeout that lands in the second step. Read the time at which timeout returns and its status, then ask which processes received TERM and what the handler did next.
- Follow-ups
-
- Which processes does timeout send TERM to, and what changes with --foreground?
- Why does a handler that only removes temp files let the script carry on, and what must it do instead?
- What does -k add, and which status does it produce?
- How do you stop the next run from overlapping, and what should the caller do with 124 and 137?
From the lesson Signals, kill and timeout
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 5 minutes
-
Mid to senior
A service takes ten seconds to stop and logs no shutdown message. Its Dockerfile has ENTRYPOINT ./entrypoint.sh in shell form, and entrypoint.sh ends with python app.py. Explain why TERM never reaches the app, and fix both files.
- What it tests
- Whether you know what the stop command sends and when, what the shell form runs, the missing exec, PID 1's signal rule, and when a forwarding trap or an init process is the better fix.
- First step
- Draw the process tree inside the container: who is PID 1, who is its child, and which of them has a TERM handler. Then rebuild the shape with plain shell scripts, one that ends with the program and one that ends with exec, and send TERM to the first PID of each.
- Follow-ups
-
- What does docker stop send, when, and what follows if the container is still running?
- Why can the exec form plus exec still leave a ten-second stop for a Python app?
- When is a forwarding trap better than exec in an entrypoint script?
- What does an init process such as tini change?
From the lesson Signals, kill and timeout
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 5 minutes
-
Mid to senior
A 40-minute make runs in the foreground of an SSH session, and the Wi-Fi is about to drop. You cannot restart the build. What can you do right now, what does each step protect against and what does it leave exposed, and how would you start such a job next time?
- What it tests
- Whether you know what a hang-up does to a shell's jobs, what Ctrl-Z, bg and disown -h each change, what stays unprotected, and the durable fix.
- First step
- Reproduce the drop on a harmless job: an inner interactive shell on a pseudo-terminal runs a loop that writes a line to the terminal and notes each write in a log. Treat the loop three ways, close the terminal, then read the logs and ask which loops ran on and what their writes returned.
- Follow-ups
-
- What does Ctrl-Z do for the job, and what does it not do?
- How do disown and disown -h differ here?
- What happens to the job's output and input after the drop?
- How would you start the job next time so none of this matters?
From the lesson Job control: Ctrl-Z, fg, bg, jobs, disown
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 4 minutes
-
Mid to senior
A wrapper script turns on set -m so it can use kill %1. Since then, Ctrl-C ends the wrapper but leaves its workers running, and a worker that reads standard input shows as Stopped. Explain both symptoms, judge whether set -m is the right tool here and give an alternative.
- What it tests
- Whether you can explain process groups and the terminal's foreground group, connect both symptoms to them, and replace set -m with PIDs, a trap and kill.
- First step
- Build the smallest wrapper: set -m, two background sleeps, wait. Run it on a pseudo-terminal, press Ctrl-C, then check whether each sleep still exists. Repeat without set -m and compare which processes the key reached.
- Follow-ups
-
- Why does Ctrl-C reach the wrapper but not the workers?
- Why does a worker that reads the terminal stop?
- Is set -m the right tool for a script, and what would you use?
- What did you test, and what did you not?
From the lesson Job control: Ctrl-Z, fg, bg, jobs, disown
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
All Bash & the POSIX Shell interview questions · The Bash & the POSIX Shell track