Linux interview questions – practice quiz with real questions

Reviewed by Mark Dickie · Last updated

14 questions on this page you can answer and see marked on the spot. Go to the first one

Linux is a free, open-source kernel and operating system family built on POSIX standards, used everywhere from embedded devices to cloud servers. For a Linux interview you should know process management (signals, jobs, top, ps), file permissions and ownership (chmod, chown, ACLs), shell scripting fundamentals (bash variables, pipes, redirection), and core networking tools (ip, ss, netstat). Hiring managers also expect you to reason about disk and filesystem concepts: partitioning, mount points, inodes, LVM, and how to diagnose space or I/O issues.

What does a Linux interview typically test?

Most Linux interviews mix command-line recall with scenario-based debugging. You will likely be asked to explain what happens during boot (initramfs, systemd targets), how to inspect running processes, and how to trace a performance problem using tools like strace, ltrace, perf, or iostat. The questions below cover the range you should expect.

AreaCommon topicsKey commands / concepts
Process managementsignals, scheduling, cgroupskill, ps, top, htop, nice, systemctl
Filesystempermissions, inodes, mounts, LVMchmod, chown, df, du, lsblk, mount, lvm
Networkinginterfaces, sockets, routingip, ss, tcpdump, traceroute, nmcli
Shell & scriptingvariables, loops, text processingbash, grep, awk, sed, find, xargs
Troubleshootinglogs, tracing, performancejournalctl, strace, iostat, vmstat, dmesg

How should you prepare for Linux interview questions?

  1. Get comfortable reading and writing bash one-liners that combine find, grep, awk, and sed — text processing comes up constantly.
  2. Learn the difference between kill, killall, and pkill, and know the standard signal numbers (1, 9, 15) and when to use each.
  3. Understand the boot chain from firmware to initramfs to systemd, including how services are managed with systemctl and unit files.
  4. Practice filesystem diagnostics: what an inode is, how to spot when a disk is out of inodes vs. out of space, and how LVM snapshots work.
  5. Review networking basics — the difference between TCP and UDP, how ss replaces netstat, and how to read tcpdump output.

What are the most common Linux command-line interview patterns?

Interviewers love giving you a broken system or a messy log file and asking you to fix or parse it. Expect questions like: find all files modified in the last 7 days and larger than 10 MB, count the top 5 IP addresses in an Apache access log, or identify which process is holding a port open. Knowing your way around pipes, xargs, and awk field references is what separates a pass from a strong pass.

Key facts

  • Tarmac has 100 Linux interview questions on this topic, 25 of them on this page, at difficulty 1–5 of 5.
  • Tarmac tracked 2,330 job postings asking for Linux in September 2026.
  • Roles asking for Linux advertise a median base salary of £70,000, across 375 job postings as of September 2026.
  • Tarmac last reviewed these Linux interview questions on 20 October 2026.

At a glance

Questions25 shown · 100 in the bank
Difficulty1–5 of 5
FormatsMultiple choice, True / false, Fill in the blank, Short answer, Ordering, Multiple answer, Flashcard

What you'll review

  1. bash error handling and exit codes
  2. control flow and functions
  3. file and process inspection
  4. parameter expansion

Practice questions

Try one before you open the answer. Pick an option and press Check; it's marked on the spot.

In bash, what is the exit code of a command that completes successfully?#

Options

Show answer

A successful bash command returns exit code 0. By POSIX convention, zero means success and any non-zero value (1–255) signals failure, with the specific number sometimes indicating the type of error.

Why:

By POSIX convention, a command that succeeds returns an exit status of 0. Non-zero values (1–255) indicate failure, with the specific number sometimes carrying meaning.

What does the special variable $? hold in a bash script?#

Options

Show answer

$? holds the exit status of the most recently executed foreground command. It is typically read immediately after a command to check whether it succeeded (0) or failed (non-zero).

Why:

$? expands to the exit status of the most recently executed foreground command. It is typically checked immediately after a command to decide whether it succeeded (0) or failed (non-zero).

What does set -e do when placed at the top of a bash script?#

Options

Show answer

set -e makes a bash script exit immediately when any command returns a non-zero exit status, unless the command is part of a condition test. This provides fail-fast behavior so errors do not go unnoticed.

Why:

set -e (short for set -o errexit) makes the shell exit immediately if any command fails with a non-zero exit status, unless that command is part of an if or &&/|| test. This helps scripts fail fast instead of continuing after errors.

In a bash script, the keyword used to define a function is function only — bash does not allow defining a function by simply writing the function name followed by parentheses and a block of code (e.g., myfunc() { ... }).#

Options

Show answer

False. Bash supports both function myfunc { ... } and myfunc() { ... } syntax for defining functions. The parentheses form is entirely valid and very common in shell scripts.

Why:

Bash supports two syntaxes for defining a function: function myfunc { ... } and myfunc() { ... }. The parentheses form is fully valid and widely used, so the statement that function is the only allowed keyword is false.

In bash, an if statement must always end with the keyword fi (the reverse of if), regardless of whether an else or elif branch is present.#

Options

Show answer

True. Every bash if statement — whether it has no else, an else, or multiple elif branches — must be terminated with fi, which is simply if reversed. Omitting fi produces a syntax error.

Why:

Every if construct in bash is closed with fi, no matter how many elif or else branches it contains. This mirrors bash's convention of closing blocks with the reversed keyword (e.g., case/esac).

The Linux command ls -l displays a long listing of files. In the permission string drwxr-xr-x, the very first character indicates the file _____. Common values include d for directory and - for a regular file.#

Show answer

The Linux command ls -l displays a long listing of files. In the permission string drwxr-xr-x, the very first character indicates the file type. Common values include d for directory and - for a regular file.

Why:

In the long-format output of ls -l, the first character of each permission string encodes the file type: d for directory, - for regular file, l for symbolic link, c for character device, b for block device, and so on. The remaining nine characters represent read/write/execute permissions for owner, group, and others.

In a bash script, the following commands are run against a file that exists but contains no lines matching the pattern "error":#

Options

Show answer

grep exits with code 1 when no lines match the pattern. It uses 0 for a match, 1 for no match, and 2 for errors such as a missing file. Since the file exists but has no matching lines, $? holds 1.

Why:

grep returns exit code 0 when at least one line matches, 1 when no lines match, and 2 when an error occurs (e.g., file not found or invalid option). Since the file exists but contains no matching lines, grep exits with status 1, so $? is 1.

Fill in the blank: In a bash if/elif/else/fi construct, the keyword used to introduce each additional condition branch between the initial if and the final else (or fi) is __________.#

Show answer

elif

Why:

Bash uses elif (a contraction of 'else if') to chain additional conditional branches. Each elif is followed by a test in square brackets or double parentheses, then then. Using else if as two separate words does not work in bash — that would start a nested if inside the else block and require an extra fi.

Name the two bash loop-control keywords that respectively terminate a loop immediately and skip to the next iteration of a loop. (Give both keywords.)#

Show answer

break terminates the loop immediately; continue skips the rest of the loop body and jumps to the next iteration.

Why:

Inside for, while, and until loops, break exits the enclosing loop entirely (optionally with a numeric argument to break out of N nested loops), while continue stops the current iteration and re-evaluates the loop condition for the next one. Both are shell builtins and behave the same way regardless of the loop type.

According to the Bash manual (Section 3.5, Shell Expansions), Bash performs a series of expansion phases on each command line in a fixed order. Place these phases in the order Bash applies them, from first to last.#

Put these in order

Show answer

Bash applies shell expansions in this fixed order: brace expansion, tilde expansion, parameter/variable/command/arithmetic expansion, word splitting, pathname expansion (globbing), and finally quote removal. This sequence is defined in Section 3.5 of the Bash manual and explains why, for instance, glob patterns produced by parameter expansion are still expanded by pathname expansion.

Why:

The Bash manual defines the expansion order as: (1) brace expansion, (2) tilde expansion, (3) parameter/variable/command/arithmetic expansion, (4) word splitting, (5) pathname expansion, and (6) quote removal. This fixed sequence explains observable behaviors — for example, a glob pattern produced by parameter expansion is still expanded because parameter expansion (step 3) precedes pathname expansion (step 5), while the results of pathname expansion are never re-split because word splitting (step 4) has already completed.

Given this Bash session, where the current directory contains the files error.log and server.log:#

Put these in order

Show answer

Bash first expands $files to the string report *.log (parameter expansion), then splits the unquoted result into report and *.log (word splitting), and finally expands *.log to matching filenames like error.log and server.log (pathname expansion). Quoting $files as "$files" would suppress word splitting and globbing, passing the single string report *.log to echo.

Why:

Bash processes the unquoted $files through three relevant phases. First, parameter expansion replaces $files with its value, the literal string report *.log. Because the expansion is unquoted, word splitting then acts on that result, splitting on the default IFS (space) into report and *.log. Finally, pathname expansion treats *.log as a glob pattern and replaces it with matching filenames in the current directory (error.log and server.log). Quote removal would follow but has no visible effect since no quote characters remain. The echo command ultimately receives three arguments: report, error.log, and server.log.

In a bash function, the statement return 300 is executed. What integer value will $? hold immediately after the function call?#

Show answer

44 — bash function return values are interpreted modulo 256, so 300 % 256 = 44. Only values in the range 0–255 are valid exit statuses.

Why:

Bash functions use return to set an exit status, which is an unsigned 8-bit value (0–255). Any argument to return is reduced modulo 256, so return 300 produces 300 - 256 = 44.

In bash, if a function does not execute any explicit return statement, what determines the exit status ($?) returned by the function call?#

Show answer

The exit status of the last command executed in the function body. This mirrors how a script's exit status defaults to the last command's status.

Why:

When no return is issued, bash uses the exit status of the last command run inside the function as the function's own exit status, just as a script without an explicit exit returns the status of its final command.

Which of the following statements about bash exit codes and pipeline behavior are true? (Select all that apply.)#

Options

Pick every one that applies.

Show answer

Without set -o pipefail, a pipeline returns the exit status of its last command only, so set -e does not catch intermediate pipeline failures. Exit code 128+N means the process was terminated by signal N (e.g., 130 = SIGINT). $? holds the exit status of the most recently executed foreground pipeline.

Why:

By default a pipeline returns the status of its last command (without set -o pipefail, a pipeline's exit status is the exit status of the last command in the pipeline). Without pipefail, intermediate failures in a pipeline are invisible to set -e, so the claim that with set -e but without set -o pipefail, a bash script exits immediately if any command in a pipeline fails, even when the last command succeeds is false. Exit codes of 128+N conventionally mean the process was killed by signal N; SIGINT is signal 2, so 130 = 128+2 (an exit code of 130 (128 + 2) indicates the process was terminated by SIGINT (signal 2)). $? is defined as the exit status of the most recently executed foreground pipeline.

A bash script has set -e enabled (but NOT set -o pipefail). Which of the following failing commands will NOT cause the shell to exit immediately? (Select all that apply.)#

Options

Pick every one that applies.

Show answer

With set -e enabled, the shell does NOT exit for a failing command that appears in an if condition, that is the left operand of &&, or whose status is inverted with !. These are explicit exemptions in the bash manual. The last command in a pipeline with pipefail enabled, however, will trigger an exit on failure.

Why:

The bash manual lists several exemptions from set -e: commands in an if/elif test (a command whose return value is tested as the condition of an if statement), commands in a &&/|| list except the one after the final &&/|| (a command that is the left operand of && — the left operand of && is not after the final &&), and commands whose status is inverted with ! (a command whose exit status is inverted with !). The last command in a pipeline with pipefail enabled describes the last command in a pipeline with pipefail enabled; when it fails the pipeline's status is non-zero, so set -e does exit — making it incorrect.

In the Linux /proc filesystem, the file /proc/<pid>/_____ contains the full command-line arguments of the process as null-byte–separated strings, while /proc/<pid>/_____ lists the process's current memory-mapped regions (one per line, showing address ranges, permissions, offset, device, inode, and pathname).#

Show answer

In the Linux /proc filesystem, the file /proc/<pid>/**cmdline** contains the full command-line arguments of the process as null-byte–separated strings, while /proc/<pid>/**maps** lists the process's current memory-mapped regions (one per line, showing address ranges, permissions, offset, device, inode, and pathname).

Why:

Under /proc/<pid>/, the cmdline file holds the process's argv array with each argument separated by a null byte, and the maps file shows each virtual memory mapping the process currently holds — including shared libraries, the heap, the stack, and any file-backed mappings. These are kernel-provided pseudo-files, so they exist for any running process without needing external tools.

Consider the bash array arr=(a b c d e) and the expansion ${arr[@]:1:2}. Put the following steps in the order bash performs them to produce the final result.#

Put these in order

Show answer

The correct order is: enumerate all array elements in index order, apply the offset to select the starting element, apply the length to take that many elements, then emit each as a separate word. For ${arr[@]:1:2} on (a b c d e), this yields the two words b and c. The offset is always applied before the length because the length counts from the offset position.

Why:

Bash first enumerates all elements of the array in index order. The offset (1) is then applied, selecting the starting element at index 1 (i.e., b). Next, the length (2) determines how many elements to take from that point — b and c. Finally, because the [@] form is used, each selected element is emitted as a separate word, so the result is two words: b and c.

With set -e active in bash 4.4 or later, a function f is invoked as the condition of an if statement (e.g., if f; then ...). Inside f, a command fails that is NOT itself in a tested position. Does the script exit at that failing command, and why or why not?#

Show answer

In bash 4.4 and later, when a function is called in a context where set -e is ignored (the function call is itself the tested command), set -e is disabled for the ENTIRE body of that function — even commands that are NOT individually in a tested position. So f does not exit; the false inside f is tolerated because the caller tests f's status, and the script continues to echo after. IMPORTANT: This whole-function toggle is specific to bash 4.4+ (POSIX sh, dash, ksh, and bash ≤ 4.3 only exempt the function-call command itself, not every command in the body).

Why:

The question is explicitly pinned to bash 4.4+, where the behavior is well-defined: when a function's return value is tested by the caller (if/while/until condition, or the left side of ||/&&), bash 4.4+ disables set -e for the entire function body — not just the function-call command. This is a change from bash 4.3 and earlier, where only the function-call command itself was exempt and a failing non-tested command inside the function would still trigger set -e. The behavior also differs across shells: POSIX sh, dash, and ksh do not implement the whole-function toggle. Pinning to bash 4.4+ eliminates the ambiguity and makes the answer deterministic.

In bash, what range of values can the return statement convey from a function, and what happens to a value outside that range?#

Show answer

0–255. The return builtin sets the function's exit status, which is an unsigned 8-bit value. Values outside that range are taken modulo 256, so return 300 is observed as 44 by the caller (300 - 256 = 44), and return -1 is observed as 255. To convey richer data, use stdout (captured via $(...)) or write to a variable passed by name.

Why:

Bash exit statuses are 8-bit unsigned integers (0–255). return is functionally identical to exit for this purpose but only exits the function, not the script. Knowing this limit is essential for designing functions that need to signal distinct error categories — a common senior-level scripting pitfall when return codes are used as error enumerations.

You write local var=$(some_command) inside a bash function, and some_command fails (non-zero exit). What is the value of $? immediately after this line, and why?#

Show answer

The exit status of the command substitution is masked. local is a builtin that always returns 0, so $? after local var=$(failing_cmd) is 0 regardless of whether failing_cmd succeeded. To capture the real status, split it into two statements: local var; var=$(failing_cmd), then check $?.

Why:

This is one of the most insidious bash gotchas. When local (or declare) is combined with an assignment that includes a command substitution, the local builtin's own successful exit status (0) is what $? reports. Under set -e this also means the failure is silently swallowed because the overall command (local var=...) succeeds. Splitting the declaration and assignment is the standard fix and a hallmark of senior-level bash fluency.

A bash script begins with set -e (errexit). In which of the following situations will the shell NOT exit despite a simple command returning a non-zero status? (Select all that apply)#

Options

Pick every one that applies.

Show answer

Under set -e, the shell does not exit when a failing command appears in an if/elif/while/until condition, is a non-final command in a &&/|| list, is a non-last command in a pipeline (without pipefail), or has its status inverted with !. The last command in a pipeline without pipefail determines the pipeline's exit status, so if it fails, set -e does trigger.

Why:

Per the bash manual, set -e does not cause exit when the failing command is part of the test following if/elif/while/until (the failing command appears in the condition of an if statement), is any command in a &&/|| list except the one following the final &&/|| (the failing command is the first operand in a cmd1 && cmd2 list — the first operand of && is not the final command), is any command in a pipeline but the last (the failing command is a non-last command in a pipeline without pipefail set), or has its return value inverted with ! (the failing command's exit status is inverted with !). The failing command is the last command in a pipeline without pipefail set is NOT an exception: without pipefail, the pipeline's exit status equals the last command's status, so if the last command fails the pipeline fails and set -e triggers.

In bash, what scoping discipline does the local keyword implement, and what is its key observable consequence when function A declares a local variable and then calls function B?#

Show answer

Bash local creates dynamic scope, not lexical scope. A variable declared local in function A is visible inside any function B that A calls; B can read and modify it, and those modifications affect A's local copy. When A returns, the variable is restored to whatever value (global or unset) it held before the local declaration. There is no closure capture: an inner function cannot see an outer function's locals unless it is actually called while that outer frame is still active on the call stack.

Why:

Bash is one of the few widely-used languages that uses dynamic scoping rather than lexical scoping for local variables. This is a deep, often surprising behavior that affects how functions interact through shared variable names, and it is a key distinction at the staff level for shell scripting internals.

In bash, with set -e active and pipefail NOT set, the pipeline false | true will NOT cause the shell to exit, because the exit status of a pipeline defaults to the exit status of its last command.#

Options

Show answer

True. Without pipefail, bash reports a pipeline's exit status as that of its last command, so false | true yields exit status 0 and set -e does not fire. Enabling set -o pipefail would make the pipeline return 1 and trigger an exit under set -e.

Why:

By default (without pipefail), bash sets $? to the exit status of the last command in a pipeline. In false | true, the last command is true, which exits 0. Because the overall pipeline exit status is 0, set -e sees success and does not trigger shell exit. Enabling set -o pipefail would change this: the pipeline would return the rightmost non-zero exit status (1 from false), and set -e would then cause the shell to exit.

In bash, a trap set with trap 'handler' ERR is executed when a command inside the condition of an if statement returns a non-zero exit status.#

Options

Show answer

False. The ERR trap is suppressed in the same contexts as set -e: commands in if/while/until conditions, non-final commands in &&/|| lists, and commands inverted with !. A failing command in an if condition is consumed as a Boolean test, so neither set -e nor the ERR trap fires.

Why:

The bash manual states that the ERR trap is not executed if the failed command is part of the test in an if statement (or a while/until condition), part of a &&/|| list except the last command, or if the command's return value is inverted with !. These are the same contexts in which set -e is also suppressed, because the non-zero status is being consumed as a Boolean value rather than treated as an error. Therefore a failing command in an if condition does trigger neither set -e nor the ERR trap.

In Bash 5.x, trace the following script:#

Show answer

In Bash 5.x, trace the following script:

s="alpha:beta:gamma:delta"
echo "${s/*:/X} : ${s/%${s##*:}/X}"

The echo command prints exactly this line (including spaces):

Xdelta : alpha:beta:gamma:X

Why:

Three parameter-expansion operators combine here. First, ${s/*:/X}: the pattern *: is a glob where * is greedy, so it matches the longest prefix ending in : — alpha:beta:gamma: — and the single / replaces that one match with X, yielding Xdelta. Second, the nested ${s##*:} removes the longest *: from the front of s, leaving delta. Third, ${s/%delta/X} uses % to anchor the pattern to the end of the string; delta matches there and is replaced with X, yielding alpha:beta:gamma:X. The literal : sits between the two expansions, so the full output is Xdelta : alpha:beta:gamma:X.

Related interview questions

Job market

See linux salaries and hiring demand from live job postings.

The other 75 questions

This page shows 25 and marks what you pick. That's as far as a page can go. A free account opens the other 75 and keeps every answer. What you miss comes back until it's right: after a day, then at longer gaps.

Start with this topic

Free · the whole bank · 100 marked answers per 30 days · written feedback on the paid plan

Interview booked? Practise the job ad instead

What moved, monthly

One email a month when the bulletin comes out: what moved in the markets we track, and the new question topics we published. Confirm your address to join. Unsubscribe any time.