linuxlab.io
Tutorials▾
  • Linux & networking
    File system, processes, TCP/IP, BGP and OSPF
    →
  • Terraform & IaC
    HCL, state, plan/apply on a LocalStack sandbox
    →
  • Git & GitHub
    Object model, plumbing, branching, GitHub Actions
    →
All tutorials →
PricingAboutSign inCreate account
/
Intro
Lessons
Footer
linuxlab-TutorialsPricingAboutPrivacy & cookies
Copyright © 2026 LinuxLab. All rights reserved.
linuxlab.io
Tutorials▾
  • Linux & networking
    File system, processes, TCP/IP, BGP and OSPF
    →
  • Terraform & IaC
    HCL, state, plan/apply on a LocalStack sandbox
    →
  • Git & GitHub
    Object model, plumbing, branching, GitHub Actions
    →
All tutorials →
PricingAboutSign inCreate account
/
  • Introduction
  • Lessons
  • How it works
  • Simulator
  • Knowledge base
  • Interview prep
Cluster

← все кластеры

Bash and shell scripting

A core cluster for anyone who writes glue code on Linux. Questions about strict mode, argument handling, signals in bash, and the difference between a pipe and process substitution. It looks shallow, but this is where carelessness gets caught most often. One missing `IFS=` breaks a script on a file with a space in its name.

6 вопросов · ~18 мин чтения

Questions

На этой странице

  1. 01What does `set -euo pipefail` do and why put it on the first line?
  2. 02What is IFS and why is `for f in $(ls)` bad?
  3. 03What is the difference between `cmd1 | cmd2` and `cmd1 <(cmd2)`?
  4. 04How do you catch SIGTERM in a bash script and do cleanup?
  5. 05What is the difference between a heredoc (`<<EOF`) and a here-string (`<<<`)?
  6. 06How does `find ... -exec` differ from `find ... | xargs`?

#set-euo-pipefail

intermediateчасто

What does `set -euo pipefail` do and why put it on the first line?

Что отвечать

`-e` exits on any error (a non-zero exit code). `-u` exits when you use an unset variable. `-o pipefail` makes the pipeline's exit code the last NON-zero one rather than the last command's (without it, `false | true` counts as success). These three flags turn bash from a forgiving shell into strict mode that catches most silent bugs right away.

Что хотят услышать

A senior should: - name each flag on its own and give an example where it catches a bug (especially `-u`: without it a typo in a variable name raises no error) - say that `-e` has a catch: `cmd && other` or a command inside `if` will not exit when cmd fails, which is by design - mention `set -x` for tracing and `set -E` (errtrace) so traps are inherited inside functions - name `IFS=$'\n\t'` as the fourth piece of strict mode (protection against word splitting on spaces)

Подводные камни

  • ✗ Thinking `set -e` catches ALL errors. No, in conditionals and in a pipe without pipefail it stays quiet.
  • ✗ Using unset variables through `${VAR:-default}` without realizing it bypasses `-u`.
  • ✗ Leaving strict mode out of production scripts. The silent bug is waiting for its moment.

Follow-up

  • ? What does `${VAR:-default}` do, and why does it work under `set -u`?
  • ? How does `set -E` differ from `set -e` for trap inheritance?
  • ? How does `pipefail` affect the exit code of a multi-stage pipeline?

Глубина в базе знаний

  • Bash strict mode: set -euo pipefail
  • bash scripts: basics and idioms
tags: bash, strict-mode, error-handling

#ifs-and-word-splitting

juniorчасто

What is IFS and why is `for f in $(ls)` bad?

Что отвечать

IFS (Internal Field Separator) is the variable bash uses to split the result of a substitution into words. By default it is space, tab, and newline. So `for f in $(ls)` breaks on files with a space in the name: `my file.txt` becomes two 'words'. The right way: `for f in *.txt` (a glob) or `find ... -print0 | xargs -0` for arbitrary names.

Что хотят услышать

A candidate should: - explain word splitting: bash takes the result of `$(...)`, splits it on IFS, then expands each piece again (glob) - name quotes `"$var"` as protection against word splitting in most cases (but not in a for loop, where quotes will not help) - give the right patterns: - a glob (`for f in *.txt`) when all the files are in one directory - `find -print0 | xargs -0` when recursive - `while IFS= read -r line; do ...; done < file` for reading line by line - mention 'ParsingLs' as the canonical BashFAQ entry

Подводные камни

  • ✗ Using `for f in $(ls)`. It breaks on spaces, tabs, and newlines in names.
  • ✗ Forgetting `IFS=` before `read -r`. Leading and trailing spaces get eaten.
  • ✗ Thinking `"$var"` solves word splitting in a for loop.

Follow-up

  • ? Why is `while read line` without `-r` a bad idea?
  • ? What does `IFS=: read a b c <<< "x:y:z"` produce?
  • ? How does `find -print0` differ from `find -print` for xargs?

Глубина в базе знаний

  • Bash strict mode: set -euo pipefail
  • xargs and find -exec: bulk operations
tags: bash, ifs, gotchas

#pipe-vs-process-substitution

intermediateиногда

What is the difference between `cmd1 | cmd2` and `cmd1 <(cmd2)`?

Что отвечать

A pipe (`|`) has cmd1 write to stdout and cmd2 read from stdin, both running in parallel. Process substitution (`<(...)`) has bash run the command and put a path to a named pipe (`/dev/fd/N`) in place of `<(...)`, which cmd1 reads like an ordinary file. Use a pipe for linear streams; use process substitution when a command wants a file rather than stdin (like `diff <(cmd1) <(cmd2)`).

Что хотят услышать

A senior should: - explain that process substitution creates an fd through `pipe()` and passes a path like `/dev/fd/63` to the command - name the classic use case: `diff <(sort a.txt) <(sort b.txt)`, since diff wants two files, not two stdins - mention that process substitution does not work in a pure POSIX shell (only bash, ksh, zsh); in `/bin/sh` (dash on Debian) it breaks - give the difference from a named pipe (`mkfifo`): process substitution cleans up after itself, while a mkfifo you have to `rm` explicitly

Подводные камни

  • ✗ Using process substitution in a `/bin/sh` script. The syntax breaks.
  • ✗ Thinking `<(...)` returns the contents. No, it returns a path to an fd.
  • ✗ Forgetting that inside `<(...)` is a subshell, so variables are not exported back out.

Follow-up

  • ? What does `ls -la <(echo hello)` show?
  • ? Why does `cmd1 | while read; do COUNT=$((COUNT+1)); done; echo $COUNT` not work the way you expect?
  • ? How does `>(...)` differ from `<(...)`?

Глубина в базе знаний

  • Process substitution: <(cmd) and >(cmd)
  • Here-doc and here-string: data inside the script
tags: bash, pipes, advanced

#trap-signals-bash

intermediateиногда

How do you catch SIGTERM in a bash script and do cleanup?

Что отвечать

`trap 'cleanup_function' SIGTERM SIGINT EXIT`. When the script receives one of those signals, `cleanup_function` runs before exit. `EXIT` is a special pseudo-signal that fires on any exit (including an error from `set -e`). The typical pattern: a trap on EXIT to remove temp files, a trap on SIGTERM for the graceful shutdown of a daemon.

Что хотят услышать

A senior should: - note that bash holds off handling a signal until the syscall returns (so `sleep 100` in a script reacts to SIGTERM only after it finishes) - say that `trap '' SIGTERM` ignores the signal (an empty handler) - give the temp-cleanup idiom: ``` TMPDIR=$(mktemp -d) trap 'rm -rf "$TMPDIR"' EXIT ``` - mention that in a script under `set -e` an error can trigger the EXIT trap earlier than expected, so cleanup must be idempotent - name `trap -p` to view the current traps

Подводные камни

  • ✗ Thinking the trap runs instantly. bash waits for the current syscall to finish.
  • ✗ Not using an EXIT trap for temp files. You leave junk behind.
  • ✗ Using `trap 'rm -rf $TMPDIR' EXIT` without quotes. If TMPDIR is empty, that is `rm -rf` at the root.

Follow-up

  • ? What happens if the parent bash script is killed while its child processes are still running?
  • ? How do you make the child processes also receive SIGTERM when the script ends?
  • ? Why do some production scripts use `trap '' SIGINT`?

Глубина в базе знаний

  • bash scripts: basics and idioms
  • Signals (SIGTERM, SIGKILL, SIGHUP)
tags: bash, signals, cleanup

#heredoc-vs-herestring

juniorиногда

What is the difference between a heredoc (`<<EOF`) and a here-string (`<<<`)?

Что отвечать

A heredoc is multi-line stdin up to a delimiter marker. `<<EOF` expands variables, `<<'EOF'` (quoted) does not. A here-string `<<<` is a single line as stdin: `grep pattern <<< "$var"`. Use a heredoc for long text and SQL queries; use a here-string to feed one variable into a command that expects stdin.

Что хотят услышать

A candidate should: - tell apart `<<EOF` (expands `$var`, `$(cmd)`, backticks) and `<<'EOF'` (literal, expands nothing), a classic gotcha - say that `<<-EOF` (with the minus) ignores leading tabs, for clean indentation inside functions - give a here-string as a replacement for echo plus pipe: `bc <<< "1+1"` versus `echo "1+1" | bc`, shorter and with no extra process - note that a heredoc is a bash feature, but `<<EOF` exists in POSIX sh too

Подводные камни

  • ✗ Using `<<EOF` for a secret without knowing that `$var` inside it expands.
  • ✗ Forgetting the `-` in `<<-EOF` and getting the EOF in an unexpected column.
  • ✗ Using `<<<` in POSIX sh. It is not supported, you need bash.

Follow-up

  • ? What does `cat <<EOF\n\$HOME\nEOF` print?
  • ? How does `<<` differ from `<<-` in a practical use case?
  • ? How do you pass an SQL query with single quotes through a heredoc?

Глубина в базе знаний

  • Here-doc and here-string: data inside the script
  • bash scripts: basics and idioms
tags: bash, heredoc, gotchas

#xargs-vs-find-exec

intermediateиногда

How does `find ... -exec` differ from `find ... | xargs`?

Что отвечать

`find -exec cmd {} \;` runs cmd SEPARATELY for each file. `find -exec cmd {} +` is batch mode, like xargs, packing files into one command line. `find | xargs` is a separate process that works like `+` but is dangerous with spaces in names. The safe form: `find -print0 | xargs -0 cmd` (a NUL separator). On modern find, `-exec ... +` is usually enough; you need xargs when you want parallelism through `-P`.

Что хотят услышать

A senior should: - tell apart `\;` (one by one, slow) and `+` (batched, fast) - name `-print0 | xargs -0` as protection against spaces - say that `xargs -P $(nproc)` gives parallel processing without GNU parallel, which is often enough - mention `xargs -n 1` for one argument at a time when the command does not take several - name ARG_MAX (`getconf ARG_MAX`, usually 2M) as the command-line length limit; on large lists xargs splits into batches automatically

Подводные камни

  • ✗ Using `find | xargs cmd` without `-print0/-0`. It breaks on files with a space, tab, or newline.
  • ✗ Using `-exec ... \;` on thousands of files. Thousands of fork-execs, slow.
  • ✗ Not knowing `xargs -P` and reaching for GNU parallel.

Follow-up

  • ? How does `-exec ... \;` differ from `-exec ... +`?
  • ? What does `xargs -I {}` do, and when do you need it?
  • ? How does `xargs -P 8 -n 1` behave with respect to output order?

Глубина в базе знаний

  • find: search files by predicates
  • xargs and find -exec: bulk operations
tags: bash, find, xargs
Footer
linuxlab-
Copyright © 2026 LinuxLab. All rights reserved.
Tutorials
Pricing
About
Privacy & cookies