skip to content

A normal user gets "command not found" for an administrative tool, but `ls /usr/sbin` shows the binary is right there and root runs it fine. On Linux, what does the /usr/bin versus /usr/sbin split mean, and why does the shell not find the program?

level: middleimportance: should knowfreq 45%

answer

  1. audience convention, not a permission fence
  2. the shell only searches what PATH lists
  3. root's default path differs from yours
  4. su without a dash keeps your environment
  5. sudo substitutes its own trusted path

basics

~20 s

The sbin directories hold system-administration programs, a convention about intended audience rather than a permission boundary. A normal user's default PATH usually omits them, so the shell never looks there — the file is executable, just not on the search path. Invoking it by absolute path works.

solid answer

~40 s

`sbin` means "system binaries": tools intended for system administration, historically useful only to root. The split is a **PATH convention, not an access control**. Nothing in the kernel or filesystem restricts who may execute a file because of the directory it sits in; permissions come from mode bits, ownership and capabilities. What happens is that on Debian-family systems a regular login gets a PATH without `/usr/sbin` and `/sbin`, while root's login PATH includes them — these defaults come from `ENV_PATH` and `ENV_SUPATH` in `/etc/login.defs` and from `/etc/profile`. So the shell searches four directories, none of them the one holding the file, and reports "command not found". Running it as `/usr/sbin/<name>` works, and many such tools do useful read-only work as a normal user. `sudo` sidesteps it by substituting its own `secure_path`.

code

bash · 4 lines
bash
# the file exists and is executable, but is not on the search path
ls -l /usr/sbin/useradd
command -v useradd || echo 'not in PATH'
echo "$PATH"

go deeper

for a junior

Know that sbin holds administrative tools and that they are usually missing from a regular user's PATH, so the fix is to run them with an absolute path or via sudo — not to conclude the file is unreadable.

for a middle

Explain that the split is a convention about audience with no enforcement behind it, and trace the symptom to PATH: where the defaults come from, why sudo differs through secure_path, and why su without a dash does not.

for a senior

Show that hiding a binary from PATH was never a security boundary, argue what actually gates execution (mode bits, ownership, capabilities, MAC policy), and know that current Debian and Fedora have merged the directories away.

for a principal

Decide fleet-wide how PATH is set for interactive users, service accounts and automation, and treat privilege as something enforced by the tool and by policy rather than inferred from where a binary happens to be installed.

## What the split actually encodes Unix separates executables by *intended audience*: - `/usr/bin` — commands for all users. - `/usr/sbin` — commands for system administration: programs that configure interfaces, create filesystems, manage users, control services. - `/usr/lib` (and `/usr/libexec`, which FHS 3.0 permits) — programs that are **not** meant to be typed at all: helpers invoked by other programs, never placed in a user's PATH. The crucial point, and the one interviewers are probing, is that this is documentation, not enforcement. The kernel decides whether you may execute a file from its mode bits and ownership, plus any file capabilities, plus whatever mandatory access control policy is in force. The directory name contributes nothing. A file mode 0755 in `/usr/sbin` is executable by anyone who names it. ## Why the shell does not find it When you type a bare command name, the shell searches the colon-separated directories in `PATH`, in order, and runs the first match. If no directory in `PATH` contains the name, you get "command not found" — a statement about the search, not about permissions. On Debian-family systems the default `PATH` for a regular login has traditionally been something like `/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games`, with no `sbin` directories, while root's login `PATH` includes `/usr/sbin` and `/sbin`. Those two defaults are configured as `ENV_PATH` and `ENV_SUPATH` in `/etc/login.defs`, and `/etc/profile` may set them too. RHEL-family systems have historically been more generous and put the sbin directories in every user's PATH, which is why the same command "works on one distro and not the other". Three ways the situation resolves in practice: 1. **Absolute path.** `/usr/sbin/<name>` runs the program with no search involved. If it only reads state, it often works fine unprivileged — plenty of administrative tools display configuration to any user and only require privilege to *change* it. 2. **`sudo`.** Debian, Ubuntu and RHEL all configure `secure_path` in `/etc/sudoers`, which *replaces* the invoking user's PATH with a fixed, trusted one that includes the sbin directories. This is a security measure — it stops a user's PATH from steering a privileged command at an attacker-controlled binary — and it has the side effect of making the command findable. 3. **`su -` versus `su`.** With `-` (or `--login`) you get a login shell and root's environment, including root's PATH. Without it, you keep your own environment: you are root, and the sbin directories are still missing from PATH. This is the single most common version of the confusion, because "I am root and it still says command not found" sounds impossible. ```sh ls -l /usr/sbin/<name> # the file is there and executable command -v <name> # nothing: not on the search path /usr/sbin/<name> --help # works, no privilege needed to ask ``` ## Why the split is dissolving The convention has been eroding for years. Modern administrative tools check privilege themselves and fail with a clear error rather than relying on being hidden, and hiding a binary from PATH was never a security boundary in the first place. Distributions have concluded the split costs more confusion than it buys, and have merged `/usr/sbin` into `/usr/bin`: Debian did so in Debian 13 (trixie), and Fedora has made the same change in recent releases. On such a system the whole question evaporates — there is one directory and one PATH entry. That merge follows the earlier `/usr` merge, which had already made `/sbin` a symbolic link to `usr/sbin`, so the top-level names still resolve. ## What to say in an interview The answer has three moves, and candidates usually only make the first: 1. `sbin` is administration tooling — the audience convention. 2. It is **not** a permission mechanism; the file's mode and the process's privileges decide execution, and the directory is irrelevant to that decision. 3. The symptom is a PATH symptom. Name where the defaults come from (`/etc/login.defs`, `/etc/profile`), why `sudo` behaves differently (`secure_path`), why `su` without `-` does not, and note that current Debian and Fedora have merged the directories away entirely. Making the second move is what separates someone who has read the directory list from someone who understands what the operating system is actually doing.

  • A user runs `su`, becomes root, and still gets "command not found". Why?
    Plain `su` starts a non-login shell and preserves the caller's environment, PATH included — so you have root's privileges with a regular user's search path that omits the sbin directories. `su -` (or `su --login`) starts a login shell and applies root's own environment, which includes them. The privilege change and the environment change are separate things.
  • Why does sudo replace PATH with secure_path instead of preserving the caller's?
    Because a user-controlled PATH is an attack on the privileged command: put a malicious `ip` early in PATH and the administrator runs it as root. `secure_path` in `/etc/sudoers` substitutes a fixed, trusted list of directories, so the resolved binary is the intended system one. That it also happens to include the sbin directories is a convenience side effect of a security control.
  • What lives in /usr/lib or /usr/libexec that would not go in /usr/bin?
    Programs that are never meant to be typed: helper binaries invoked by another program, per-package internal tools, and support executables. They stay off PATH deliberately, because they carry no stable command-line interface and are not a supported user surface. FHS 3.0 permits `/usr/libexec` for exactly this, and RHEL-family systems use it heavily.

saying these in an interview costs you the question

  • Says only root is permitted to execute files in /usr/sbin
  • Treats command not found as a permissions error
  • Assumes su alone gives you root's PATH
  • Adds sbin to a user's PATH and calls it a security fix
  • Thinks the sbin split is enforced by the kernel

context