Reading — step 1 of 7
Learn
Bash's job control lets one shell juggle multiple processes — backgrounding, suspending, resuming. Critical for production scripts that run parallel work or manage long-lived children.
Background processes — &
#!/bin/bash
long_running & # runs in background
echo "PID is $!" # $! is the last backgrounded PID
wait # wait for ALL background jobs
Background processes get their own PID. The script continues. wait blocks until all background work finishes.
Parallel work
for host in alpha beta gamma delta; do
ping -c1 "$host" > "/tmp/ping_$host.log" &
done
wait # wait for all 4 pings
echo "all done"
Far faster than serial — pings happen concurrently. Wait collects them.
Capturing PIDs of background jobs
pids=()
for host in "${hosts[@]}"; do
process_host "$host" &
pids+=($!)
done
for pid in "${pids[@]}"; do
wait "$pid"
echo "job $pid finished with exit $?"
done
Wait for SPECIFIC PIDs — capture their individual exit statuses.
kill — sending signals
kill 1234 # SIGTERM (15) — polite shutdown
kill -9 1234 # SIGKILL — uninterruptible
kill -INT 1234 # SIGINT (2) — Ctrl+C equivalent
kill -HUP 1234 # SIGHUP — reload config (convention)
kill -0 1234 # signal 0 — just CHECK if process is alive
Common signals:
- SIGTERM (15) — default; "please exit cleanly"
- SIGKILL (9) — uninterruptible; can't be trapped; last resort
- SIGINT (2) — Ctrl+C
- SIGHUP (1) — terminal closed
- SIGSTOP (19) — pause; can't be trapped
- SIGCONT (18) — resume after stop
Job control commands (interactive shells)
./long & # start in background
jobs # list jobs
jobs -l # list with PIDs
fg # bring most-recent to foreground
fg %1 # foreground job number 1
bg # resume most-recent in background
Ctrl+Z suspends the foreground job (sends SIGTSTP). bg resumes in background. fg brings to foreground.
These mostly matter in interactive shells — scripts use & and wait directly.
Timeouts
timeout 5 long_command # kill after 5 seconds
timeout --kill-after=10 5 long_command # SIGTERM after 5s, SIGKILL after 15
Returns 124 if the timeout fired. Useful for CI scripts that shouldn't hang.
disown — let process outlive shell
long_running &
disown # detach from this shell — survives logout
exit
Alternative to nohup long_running &. Both detach from the controlling terminal.
Common mistakes
- Forgetting
wait— script exits before background jobs finish. kill -9as first reflex — doesn't run trap handlers, can leave files corrupted. Try SIGTERM first.- No timeout on external commands — script hangs forever waiting for a network operation.
$!after multiple&— only captures the LAST one. Save each to a variable:cmd1 & pid1=$!; cmd2 & pid2=$!.- Not checking exit status of
wait— by defaultwaitsucceeds even if children failed. Loop:for pid in ...; do wait $pid || handle_error; done.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…