Top Linux / Unix Interview Questions & Answers

Linux/Unix fundamentals show up constantly in DevOps and backend interviews — permissions, processes, and the everyday command-line tools.

Take Practice Interview Now
Improve your chances of getting selected — rehearse these answers out loud with an AI interviewer and get a scored report in minutes.
Start Free →

1. How does the Linux file permission system work, and what do rwx mean?

Every file and directory in Linux has three permission classes: owner, group, and others, and each class can have read, write, and execute permissions represented as rwx. Read lets you view a file's contents or list a directory, write lets you modify a file or add and remove entries in a directory, and execute lets you run a file as a program or `cd` into a directory. You can see these with `ls -l`, which shows a string like `-rwxr-xr--` where the first character indicates file type and the next nine characters are the three permission triads. Permissions are enforced by the kernel at the filesystem level, and even root can bypass them only because it has special capabilities, not because the permission bits don't apply. Understanding this triad is the foundation for everything else in Linux access control, including `chmod` and `chown`.

2. What's the difference between chmod using numeric mode versus symbolic mode, and how does chown fit in?

Numeric mode, like `chmod 755 file.sh`, represents permissions as an octal number where each digit is the sum of read (4), write (2), and execute (1) for owner, group, and others respectively, so 755 means rwx for the owner and r-x for group and others. Symbolic mode, like `chmod u+x,g-w,o=r file.sh`, lets you add, remove, or set permissions using letters u, g, o, a for the user classes and +, -, = as operators, which is handy when you want to change just one bit without recalculating the whole number. Numeric mode is quick once you're comfortable with the math and shows up a lot in scripts because it's deterministic, while symbolic mode reads more clearly for incremental changes. `chown` is a related but separate command since it changes ownership rather than permission bits, letting you set the user and group that owns a file, like `chown alice:developers file.sh`. Both commands usually require root privileges or existing ownership of the file to succeed.

3. What's the difference between a process and a thread at the OS level?

A process is an independent execution unit with its own memory address space, file descriptors, and OS-level resources, so one process crashing generally doesn't take down another. A thread is a lighter-weight unit of execution living inside a process that shares that process's memory space, heap, and file descriptors with other threads in the same process, though each thread keeps its own stack and register state. Because threads share memory, communication between them is cheap but requires synchronization primitives like mutexes to avoid race conditions, whereas separate processes need explicit IPC mechanisms like pipes, sockets, or shared memory to talk to each other. Context switching between threads is generally cheaper than between processes because the kernel doesn't have to swap out the whole memory mapping. In Linux specifically, both are represented as `task_struct` entries under the hood, and threads are essentially processes created with the `clone()` syscall configured to share a memory space with their parent.

4. How do you find and kill a running process in Linux?

You typically find a process with `ps aux` or `ps -ef` to list all running processes with their PIDs, piping that through `grep` to filter for the one you want, like `ps aux | grep nginx`. Tools like `pgrep` are more direct since they return just the PID for a process matching a name pattern, skipping the grep step entirely. Once you have the PID, `kill <PID>` sends it a signal, and by default that's `SIGTERM` (signal 15), which asks the process to shut down gracefully and clean up any open resources. If a process ignores `SIGTERM` or is hung, you can force it with `kill -9 <PID>`, which sends `SIGKILL` and is handled directly by the kernel, so the process itself can't intercept or ignore it. There's also `pkill` and `killall`, which let you kill processes by name instead of PID, convenient when multiple instances of the same program are running.

5. What's the difference between a hard link and a symbolic link?

A hard link is a second directory entry that points to the exact same inode as the original file, meaning both names reference identical data on disk with no real concept of an original versus a copy. Because of that, deleting one hard link doesn't remove the underlying data as long as another hard link still references that inode, since the kernel simply decrements the inode's link count. A symbolic link, or symlink, is a small separate file that just stores a path to another file, similar to a shortcut, so if you delete the target the symlink becomes a dangling reference. Hard links can't span filesystems or partitions because inodes are only unique within a single filesystem, while symlinks can point anywhere, including across filesystems or to directories. You create them with `ln target linkname` for a hard link and `ln -s target linkname` for a symbolic one.

6. Explain piping and redirection in the shell.

Redirection controls where a command's input or output goes: `>` sends stdout to a file and overwrites it, `>>` appends instead, `<` feeds a file in as stdin, and `2>` redirects stderr specifically, which is useful when you want to separate error messages from normal output. A pipe, written as `|`, connects the stdout of one command directly to the stdin of another without writing an intermediate file, so `ps aux | grep nginx | awk '{print $2}'` chains three commands together to filter and extract data in one line. Under the hood the shell sets up a pipe buffer in the kernel and both commands run concurrently, with the second command blocking on read until the first produces output. You can combine redirection and piping, like `command 2>&1 | tee log.txt`, which merges stderr into stdout before piping it, a very common pattern for capturing full command output including errors. This composability reflects the Unix philosophy of small tools that each do one thing well and can be chained together freely.

7. Describe the Linux file system hierarchy.

Linux follows the Filesystem Hierarchy Standard, starting from the root directory `/`, under which everything else is mounted regardless of how many physical disks or partitions are actually involved. `/bin` and `/usr/bin` hold essential user executables, `/sbin` holds system administration binaries typically run by root, and `/etc` stores system-wide configuration files. `/home` contains per-user directories, `/var` holds variable data that changes frequently such as logs in `/var/log` and spool files, and `/tmp` is for temporary files that are often cleared on reboot. `/proc` and `/sys` are virtual, kernel-generated filesystems that expose runtime information about processes and hardware rather than actual files stored on disk. Knowing this layout helps you predict where configs, logs, or binaries live without having to search the entire filesystem.

8. What are environment variables and how do you work with them?

Environment variables are key-value pairs held in a process's environment that configure behavior for that process and any child processes it spawns, things like `PATH`, `HOME`, and `USER`. You set one for the current shell session with `export VAR=value`, and you can view all of them with `env` or `printenv`, or a single one with `echo $VAR`. Because environment variables are inherited by child processes but not passed back up to the parent, a variable set inside a script or subshell won't affect the shell that launched it unless it was exported before that point. `PATH` specifically is a colon-separated list of directories the shell searches through in order whenever you type a command name without a full path. Environment variables are commonly used to inject configuration into applications, like database URLs or API keys, without hardcoding them into the codebase.

9. What tools do you use to monitor system resources in Linux?

`top` gives a real-time, refreshing view of CPU and memory usage broken down by process, including load average at the top, and `htop` is a more user-friendly, colorized alternative with scrolling and easier process management built in. `df -h` reports disk space usage per mounted filesystem in human-readable units, which is what you check when a disk-full error shows up, while `du -sh` sums up the actual disk usage of a directory or file tree, useful for hunting down what's eating space. For memory specifically, `free -h` shows total, used, and available RAM along with swap usage. Other useful tools include `iostat` for disk I/O statistics, `vmstat` for virtual memory and CPU stats over time, and `netstat` or its modern replacement `ss` for network connection monitoring. Together these give you a full picture of CPU, memory, disk, and network health on a box.

10. How does a shell script work, and what's the purpose of the shebang line and exit codes?

A shell script is just a text file containing a sequence of shell commands, and the shebang line at the very top, like `#!/bin/bash` or `#!/usr/bin/env python3`, tells the kernel which interpreter should execute the rest of the file when it's run directly as an executable. Without the shebang, the file would just be interpreted by whatever shell you happen to invoke it with, which can lead to inconsistent behavior if the syntax isn't portable across shells. Every command in Linux returns an exit code between 0 and 255 when it finishes, where 0 conventionally means success and any nonzero value indicates some kind of failure, and you can check the last command's exit code with `$?`. Scripts use this for control flow, like `if command; then ... fi`, which branches based on whether the command succeeded, and you can explicitly set your script's own exit code with `exit 1` at the end. Combined with `set -e`, which makes a script exit immediately on any failing command, exit codes are the backbone of reliable automation and CI pipelines.

11. What's the difference between a process and a daemon?

A process is simply any running instance of a program, whether it's interactive, in the foreground, or running in the background. A daemon is a specific kind of process designed to run in the background continuously, detached from any controlling terminal, typically started at boot and living for as long as the system is up, things like `sshd`, `cron`, or the `nginx` master process. Daemons conventionally have names ending in a d and are usually managed by an init system rather than launched manually from a shell. Because they're detached from a terminal, daemons redirect their stdin, stdout, and stderr elsewhere, often to log files, and they typically ignore signals like `SIGHUP` that would normally apply to a session's controlling process. The key distinction is really about lifecycle and attachment: any process can technically become daemon-like by forking and detaching itself, but daemons are specifically built and managed to run unattended and persistently.

12. What is systemd and how do you manage services with it?

systemd is the init system used by most modern Linux distributions, meaning it's the first process the kernel starts at boot, running as PID 1, and it brings up all other services and mounts filesystems based on dependency graphs rather than a strictly linear sequence like older SysV init. Services are defined by unit files, typically ending in `.service`, which specify things like the command to run, dependencies, and restart policy. You interact with it through `systemctl`, so `systemctl start nginx` starts a service, `systemctl stop nginx` stops it, `systemctl enable nginx` makes it start automatically on boot, and `systemctl status nginx` shows whether it's running along with recent log lines. `journalctl` is the companion tool for viewing logs collected by systemd's logging component, journald, and you can filter it by service with `journalctl -u nginx`. systemd also handles things like socket activation, timers as a cron alternative, and cgroup-based resource limits for services.

13. How does SSH and key-based authentication work?

SSH, or Secure Shell, is a protocol for securely logging into and executing commands on a remote machine over an encrypted channel, replacing older insecure protocols like telnet. Password authentication just checks a password against the remote system, but key-based authentication uses a public-private key pair, where you generate the pair locally with `ssh-keygen`, keep the private key secret on your machine, and copy the public key to the remote server's `~/.ssh/authorized_keys` file, often using `ssh-copy-id`. When you connect, the server issues a cryptographic challenge that can only be answered correctly if you hold the matching private key, so authentication happens without the private key or a password ever being transmitted over the network. This is more secure than passwords because private keys are much harder to brute-force and can be further protected with a passphrase, and it also enables passwordless automation for scripts and CI pipelines. It's worth knowing that file permissions matter here too, since SSH will refuse to use a private key or `authorized_keys` file if it's readable by anyone other than the owner.

14. How do cron jobs work?

Cron is a time-based job scheduler that runs commands automatically at specified intervals, and each user can have their own crontab, edited with `crontab -e`, plus there are system-wide cron directories like `/etc/cron.d`. Each line in a crontab follows a five-field time pattern for minute, hour, day of month, month, and day of week, followed by the command to run, so `0 2 * * *` means run at 2 AM every day. The cron daemon, `crond`, wakes up every minute and checks whether any scheduled jobs match the current time, then executes them under the environment of the user who owns that crontab, which is often much more minimal than an interactive shell, a common source of 'it works when I run it manually but not from cron' bugs. You can list your current jobs with `crontab -l`, and logs typically end up in the system log or a dedicated cron log depending on the distribution. On systemd-based systems, timers are increasingly used as an alternative to cron because they integrate with service dependencies and centralized logging.

15. What's the difference between TCP and UDP?

TCP, Transmission Control Protocol, is connection-oriented, meaning it establishes a session through a three-way handshake before any data is sent, and it guarantees reliable, in-order delivery by acknowledging packets and retransmitting lost ones. UDP, User Datagram Protocol, is connectionless, sending packets, called datagrams, without any handshake or delivery guarantee, so packets can arrive out of order, duplicated, or not at all, and it's up to the application to handle that if it matters. TCP's reliability comes with overhead in latency and header size, which makes it the right choice for things like web traffic, file transfers, or SSH where correctness matters more than raw speed. UDP is preferred for cases like video streaming, DNS lookups, or online gaming, where low latency matters more than a guarantee that every packet arrives, and retransmitting a stale packet would actually be worse than just dropping it. Both operate over IP and use port numbers to route traffic to the right application on a host, but they're implemented as completely different transport layer protocols with different header formats and guarantees.

16. What are file descriptors?

A file descriptor is a small non-negative integer that the kernel uses as a handle to reference an open file, socket, pipe, or other I/O resource within a process, so instead of working with a full file path every time you read or write, the process just references the integer. Every process starts with three standard descriptors already open: 0 for stdin, 1 for stdout, and 2 for stderr, which is why redirection syntax like `2>&1` refers to those numbers directly. When a process opens additional files or sockets, the kernel assigns the next available descriptor number, keeping a per-process table that maps descriptors to actual open file entries in the kernel. File descriptors are a limited resource per process, controlled by `ulimit -n`, and a common production bug is a 'too many open files' error caused by a process leaking descriptors by never closing what it opens. You can inspect a running process's open file descriptors with `lsof -p <PID>` or by looking directly at `/proc/<PID>/fd/`.

17. At a conceptual level, what are grep, awk, and sed used for?

`grep` is a pattern-matching and searching tool that scans input line by line and prints the lines matching a given regular expression, making it the go-to for searching log files or filtering command output, like `grep 'ERROR' app.log`. `sed`, short for stream editor, is built for performing transformations on text as it streams through, most commonly find-and-replace operations like `sed 's/foo/bar/g'`, and it can also delete lines, insert text, or apply changes in place with `-i`. `awk` is the most powerful of the three because it's a full pattern-scanning and text-processing language that understands fields and records, so it excels at extracting specific columns from structured text, like `awk '{print $2}'` to grab the second whitespace-separated field, and it supports conditionals, loops, and variables for more complex processing. In practice these three are often chained together in a pipeline, using `grep` to filter down to relevant lines, `awk` to pull out specific fields, and `sed` to clean up or reformat the final text. Being comfortable with all three is a strong signal in interviews because so much day-to-day sysadmin and DevOps work boils down to slicing and dicing text output from logs and commands.

18. What's the difference between a zombie process and an orphan process?

A zombie process is one that has finished executing and terminated but still has an entry in the process table because its parent hasn't yet called `wait()` to read its exit status, so its PID and a small amount of metadata linger until the parent reaps it. An orphan process is the opposite situation: the parent terminates first while the child is still running, and the kernel reassigns that child to be adopted by `init` or, on modern systems, whatever process is running as PID 1, which then takes responsibility for reaping it when it eventually exits. Zombies are essentially harmless individually since they consume almost no resources, but a process that spawns children and never reaps them can accumulate thousands of zombie entries and eventually exhaust the process table. You can spot zombies in `ps aux` output by the `Z` state flag in the STAT column. Fixing a zombie problem usually means fixing the parent code to properly call `wait()` or `waitpid()`, since you can't directly kill a zombie, it's already dead and just waiting to be reaped.

Take Practice Interview Now
Improve your chances of getting selected — rehearse these answers out loud with an AI interviewer and get a scored report in minutes.
Start Free →
Related topics
KubernetesDockerTerraformJenkins