Troubleshooting

sudo: command not found? Install it the right way

sudo is not installed. Become root with su -, run apt install sudo, then usermod -aG sudo USERNAME and log in again. Docker, Alpine, macOS and Windows too.

Published · Updated ~10 min read
On this page

Short answer: sudo: command not found means the sudo program is not installed, or your shell can no longer see /usr/bin. On Debian, in Docker images and on Alpine it is almost always the first: sudo is an optional package there. Become root with su - (it asks for the root password, not yours), install sudo, put your account in the admin group and log in again:

Debian · Ubuntu
su -
Debian · Ubuntu (as root)
apt update && apt install -y sudo
Debian · Ubuntu (as root)
usermod -aG sudo USERNAME

Replace USERNAME with your login name. Then type exit to leave the root shell, log out completely, log back in, and sudo whoami prints root. Is your prompt already a #? Then you are root and do not need sudo at all: run the same command without it.

Seeing -sh: sudo: not found instead, with no number in it? That is BusyBox on Alpine, OpenWrt or a similar device. They ship no sudo and you are normally logged in as root, so leave sudo out; for a normal user, Alpine uses doas (see Alpine and BusyBox). With a number, as in -sh: 1: sudo: not found, your account’s shell is dash: accounts made with useradd.

Which error do you see?

The exact wording tells you which shell printed it, and that usually tells you where you are. The Linux lines below are what bash 5.2, dash 0.5.12, zsh 5.9 and BusyBox 1.35 ash print when we run sudo on a system without it; the PowerShell wording comes from PowerShell’s own source.

MessageWhere you see itGo to
bash: sudo: command not foundbash in a terminal, a container, or Git Bash on Windows; a script names itself and the line instead, as in ./install.sh: line 3: sudo: command not foundInstall sudo
-bash: sudo: command not foundbash as a login shell: SSH or the consoleInstall sudo
-sh: sudo: not foundBusyBox ash as login shell: Alpine, embedded devices (OpenWrt prints -ash:)Alpine and BusyBox
-sh: 1: sudo: not founddash as login shell: an account made with useradd on Debian or Ubuntu. The number counts the lines typed in that sessionuseradd accounts
/bin/sh: 1: sudo: not founda RUN line in a Dockerfile on a Debian or Ubuntu imageDocker
/bin/sh: sudo: not founda RUN line on an Alpine imageDocker
zsh: command not found: sudozsh, the macOS default: on a Mac PATH is broken (on Linux, sudo is missing)macOS
'sudo' is not recognized as an internal or external command,Windows cmdWindows
The term 'sudo' is not recognized as a name of a cmdlet, function, script file, or executable program.PowerShell 7 (5.1 says "as the name of a cmdlet, function, script file, or operable program")Windows
Sudo is disabled on this machine.Windows 11 24H2 or later, sudo not switched onWindows
sudo: npm: command not foundsudo works; the command after it is not on sudo’s own PATH. Ubuntu 26.04 prints sudo: 'npm': command not foundsecure_path
alice is not in the sudoers file.sudo is installed; your account may not use it. Ubuntu 26.04 says sudo: I'm sorry alice. I'm afraid I can't do thatAdd your user

Become root, then install sudo

Why it is missing: the Debian installer sets up sudo only when you leave the root password empty. It then installs the package and lets the first user run it. Give root a password instead and the first user gets no sudo rights. On a server install, without a desktop, the package is missing too: sudo has the priority “optional” and only the desktop task pulls it in. Docker base images leave it out as well, since containers run as root by default.

So the way in is root itself. su - asks for root’s password; the dash starts a full root login with root’s PATH. On Debian, plain su keeps your own PATH, which has no /usr/sbin, so usermod answers “command not found” too. If su answers su: Authentication failure, the password is wrong or root has none (Ubuntu locks it by default); the note at the end covers that case. Then install the package for your distribution:

Debian · Ubuntu
apt update && apt install -y sudo
Rocky · Alma · RHEL · Fedora
dnf install -y sudo
Arch
pacman -S --noconfirm sudo
openSUSE
zypper install -y sudo

Alpine works differently; see Alpine and BusyBox below. After su, by the way, you are root: if all you wanted was to run one command with sudo in front of it, run it without the sudo and you are done.

-sh: 1: sudo: not found: an account made with useradd

A bare $ prompt, no tab completion, and errors of the form -sh: 1: sudo: not found mean your login shell is dash, not bash. The number is the line of the session dash is reading, so the third command you type fails with -sh: 3:. That is what useradd gives a new account on Debian 12 and 13 and Ubuntu 24.04 unless told otherwise: /etc/default/useradd sets SHELL=/bin/sh, and /bin/sh is dash. sudo is still simply missing, so install it as above, and while you are root, give the account bash:

Debian · Ubuntu (as root)
usermod -s /bin/bash USERNAME

adduser, Debian’s friendlier front end, uses /bin/bash by default, which is why accounts made with it never show this.

Let your user run sudo

The package alone is not enough: your account needs a rule in sudoers. Distributions ship one for an admin group, so adding the user to that group is usually all it takes. Still as root:

Debian · Ubuntu
usermod -aG sudo USERNAME
Rocky · Alma · RHEL · Fedora · Arch
usermod -aG wheel USERNAME

On Arch the %wheel line in /etc/sudoers ships commented out; enable it with EDITOR=nano visudo. Without a matching rule, sudo answers alice is not in the sudoers file. On a system that can send mail a second line follows, This incident has been reported to the administrator. Older sudo versions put This incident will be reported. on the same line, and Ubuntu 26.04, whose sudo is the Rust rewrite sudo-rs, says sudo: I'm sorry alice. I'm afraid I can't do that.

Group membership is read at login, so a shell that was open before the change does not have it. Log out completely (with SSH, close the connection) and log in again. For a brand-new admin account rather than an existing one, create a sudo user with adduser first.

Verify it worked

Linux
command -v sudo
id
sudo whoami

The first line should print /usr/bin/sudo, id should list 27(sudo) among the groups (10(wheel) on the RHEL family), and the last one prints root after asking for your password, not root’s. If id lacks the group, you are still in a session from before the change. The rest of a new server’s first steps, from SSH keys to the firewall, are in initial server setup.

sudo in a Docker container or Dockerfile

Containers run as root unless the image or the docker run command says otherwise, and the official debian, ubuntu and alpine images do not contain sudo. A RUN line that starts with sudo stops the build with /bin/sh: 1: sudo: not found on a Debian or Ubuntu base (whose /bin/sh is dash) or /bin/sh: sudo: not found on Alpine, and exit code 127. Leave sudo out:

Dockerfile · Debian or Ubuntu base
RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates curl \
 && rm -rf /var/lib/apt/lists/*
Dockerfile · Alpine base
RUN apk add --no-cache curl

If an earlier USER line switched to an unprivileged account (official node images ship a node user for this), switch back for the install and return afterwards:

Dockerfile
USER root
RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates curl \
 && rm -rf /var/lib/apt/lists/*
USER node

ca-certificates is in both lines because --no-install-recommends would otherwise leave curl unable to verify any HTTPS certificate.

In a running container that uses a non-root user, open a root shell from the host instead of reaching for sudo:

Docker host
docker exec -u root -it CONTAINER sh

Install sudo in an image only when a script you cannot change insists on calling it (apt-get install -y sudo). As root, sudo then simply runs the command.

-sh: sudo: not found on Alpine, BusyBox and OpenWrt

No line number between the colons means BusyBox ash printed it. Alpine’s root account logs in to /bin/sh, which is BusyBox ash, hence -sh:. OpenWrt sets root’s shell to /bin/ash, so the same error starts with -ash:. In an Alpine container opened with docker exec -it CONTAINER sh it reads sh: sudo: not found. None of these ship sudo, and you are normally root there, so leave sudo out of the command.

For a normal user, Alpine’s own answer is doas, a small tool from OpenBSD in the main repository. As root:

Alpine
apk add doas
echo 'permit persist :wheel' > /etc/doas.d/wheel.conf
adduser USERNAME wheel

Log in again as that user and type doas where a guide says sudo: doas apk update. The rule lets members of wheel run any command as root, and persist spares you the password prompt for a while after a successful one. Files in /etc/doas.d/ must end in .conf; Alpine’s doas reads them after /etc/doas.conf. If you would rather keep the familiar name, sudo is in Alpine’s community repository:

Alpine · sudo instead of doas
apk add sudo
echo '%wheel ALL=(ALL:ALL) ALL' > /etc/sudoers.d/wheel
chmod 0440 /etc/sudoers.d/wheel
adduser USERNAME wheel

sudo is installed, but the shell cannot find it

If the package is there and the error persists, PATH is broken. A startup file replaced it, for example export PATH=/opt/tool/bin without :$PATH at the end, and then ls, grep and most other commands fail as well. Check the file and the variable:

Linux
ls -lL /usr/bin/sudo
echo "$PATH"
/usr/bin/sudo whoami

A healthy sudo shows -rwsr-xr-x 1 root root; the s in place of the owner’s x is the setuid bit it needs, and -L follows the link that Ubuntu 26.04 puts at /usr/bin/sudo. If the full path works and plain sudo does not, PATH is the problem. Restore a working PATH for this shell, then find the line that broke it:

bash · zsh
export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$PATH"
bash · zsh
grep -n 'PATH=' ~/.bashrc ~/.profile ~/.bash_profile ~/.zshrc 2>/dev/null

Change the culprit so it keeps the old value: export PATH="/opt/tool/bin:$PATH". A different message, sudo: /usr/bin/sudo must be owned by uid 0 and have the setuid bit set, means the file lost its owner or mode, typically after a recursive chown; reinstall the package as root (apt install --reinstall sudo, or sudo-rs on Ubuntu 26.04, whose message lacks the path).

sudo: npm: command not found

Here sudo itself works; it is the command after it that is not found. sudo does not search your PATH. It uses secure_path from /etc/sudoers, which on Debian 12 and 13 is /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin; Ubuntu adds /snap/bin. Anything installed under your home directory is invisible to it: Node through nvm, pip install --user and pipx in ~/.local/bin, cargo in ~/.cargo/bin. Ubuntu 26.04’s sudo-rs reads the same setting and words the error sudo: 'npm': command not found. sudo -E does not help: classic sudo applies secure_path regardless, and sudo-rs ignores -E with a warning.

Often the right fix is to drop sudo: nvm, pipx and cargo install into directories you own, so they never needed root. When a command really must run as root, hand sudo your PATH through env:

Linux
sudo env "PATH=$PATH" COMMAND

Calling the full path instead, sudo ~/.nvm/versions/node/VERSION/bin/npm, still fails for Node tools: npm starts with #!/usr/bin/env node, and root’s PATH has no node, so you get /usr/bin/env: ‘node’: No such file or directory (with straight quotes when no UTF-8 locale is set). The npx case is covered in sudo: npx: command not found.

zsh: command not found: sudo on macOS

macOS always has sudo, at /usr/bin/sudo on the read-only system volume. On a Mac this message means PATH has lost /usr/bin, usually through a line in ~/.zshrc or ~/.zprofile that sets PATH without keeping $PATH; ls and git are gone too. Repair the open window first:

macOS · zsh
export PATH="/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:$PATH"
macOS · zsh
grep -n 'PATH' ~/.zshrc ~/.zprofile ~/.zshenv 2>/dev/null

Fix the line it finds so it ends in :$PATH. For Homebrew, the line its installer prints is all you need, on Apple Silicon eval "$(/opt/homebrew/bin/brew shellenv)". Open a new terminal and command -v sudo should print /usr/bin/sudo. sudo also requires an administrator account (System Settings, Users & Groups); a standard account is refused even with the right PATH.

Windows: ‘sudo’ is not recognized, or bash: sudo in Git Bash

Windows has its own sudo since Windows 11 version 24H2, and it is off until you enable it. Typed in that state, it answers Sudo is disabled on this machine. To enable it, go to the Developer Settings page in the Settings app. Turn it on under Settings, System, Advanced (called For developers on 24H2), Enable sudo, or from an administrator terminal:

Windows 11 24H2 · administrator terminal
sudo config --enable forceNewWindow

forceNewWindow, the default, runs the elevated command in a new window after the UAC prompt. normal runs it inline in the current window; Microsoft recommends the default unless you know the security trade-offs of the inline modes. On Windows 10 and older Windows 11 builds there is no sudo at all. cmd prints 'sudo' is not recognized as an internal or external command, with operable program or batch file. on the next line, and PowerShell the “The term ‘sudo’ is not recognized” line from the table. Right-click Terminal and choose Run as administrator instead.

Git Bash is bash, so it prints bash: sudo: command not found, and Git for Windows includes no sudo. Commands copied from a Linux guide usually belong somewhere else: commands for your server go into an SSH session on it (ssh USER@SERVER_IP), not into a shell on your PC. For a local Linux shell, wsl --install sets up Ubuntu, and the user it creates on first start can use sudo.

Need a clean environment to reproduce a minimal-image issue? A Debian VPS deploys from stock images in about a minute and bills monthly.

Another tool missing, or a directory to add to PATH for good in bash, zsh and fish? See command not found: the three causes and the fix for every tool.

Frequently asked

What does '-sh: sudo: not found' mean?

BusyBox ash printed it, the shell of Alpine Linux and of many routers and embedded devices; OpenWrt shows '-ash:' instead. Those systems ship no sudo and you normally log in as root, so run the command without sudo. On Alpine, give a normal user root rights with doas: apk add doas, put 'permit persist :wheel' in /etc/doas.d/wheel.conf and add the user to the wheel group.

Why is sudo not found after su?

su made you root, and sudo is simply not installed, which is normal on a Debian server installed with a root password. As root you do not need it: run the command without sudo, or install it now with apt install sudo. If usermod is not found either, you used su without the dash; su - loads root's full PATH.

Do I need sudo inside a Docker container?

No. Containers run as root unless the image sets another USER, and the debian, ubuntu and alpine images contain no sudo, so 'RUN sudo ...' fails with '/bin/sh: 1: sudo: not found' (or '/bin/sh: sudo: not found' on Alpine). Drop sudo; if the Dockerfile switched to a non-root user, put USER root before the install line.

Related articles

All troubleshooting