You just logged into a server or opened a terminal, and every command you type comes back with bash: ls: command not found — even ls, sudo, or vi. You're not in a weird chroot, and the system isn't broken. The problem is almost always that your PATH environment variable has been emptied or overwritten. I've seen this happen after someone runs a script with a typo, sources a broken .bashrc, or installs a custom environment tool that clobbers PATH during login.
What's actually going on
PATH is just a list of directories where bash looks for executables. When you type ls, bash checks each directory in PATH in order. If PATH is empty or points to the wrong places, bash can't find anything — even commands that live in /usr/bin or /bin. The root cause is usually one of these:
- A
.bashrcor.profilefile that setsPATHwithout including the original value (likeexport PATH=/some/custom/dirinstead ofexport PATH=/some/custom/dir:$PATH). - A script that runs
export PATH=(empty) and never restores it. - An automation tool or container setup that sets a minimal environment for security, but forgets standard paths.
Last month I had a client whose backup script had a line export PATH="$BACKUP_DIR" — that wiped PATH every time they ran it. The scary part is that the damage persists after the script exits if it's sourced, not executed.
The fix: restore PATH and make it stick
Here's the exact sequence I use when a box is locked up this way.
- Get a usable shell without relying on PATH. If
sudois also missing, you'll need to use the full path to binaries. First, try the standard defaults:
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
This restores the normal system paths. Now ls and sudo work again. But this only fixes your current session — the next login will break again if the source issue isn't fixed.
- Check what's in your shell startup files. Look at
.bashrc,.profile, and.bash_profilein your home directory:
grep -n 'PATH' ~/.bashrc ~/.profile ~/.bash_profile
Look for lines that assign PATH without $PATH at the end. Anything like export PATH="/some/thing" is suspicious. The correct way is:
export PATH="/some/thing:$PATH"
- Fix the broken line. Edit the offending file. If it's
.bashrc, comment out the broken line and add the corrected version. Example:
# Bad:
# export PATH="/opt/weird/bin"
# Good:
export PATH="/opt/weird/bin:$PATH"
- Reload the file and verify.
source ~/.bashrc
echo $PATH
You should see the standard paths plus any custom ones. Test with which ls — it should return /usr/bin/ls or similar.
- If the damage is in a system-wide file like
/etc/profileor/etc/environment, fix it withsudo vi /etc/profile(now that sudo works). Same rule: never replacePATHentirely unless you know every directory you need.
Still broken? Here's what to check next
If you've restored PATH and echo $PATH looks fine, but commands still fail, check these:
- Are the binaries actually in those directories? Run
ls /usr/bin/ls. If it's missing, your system is more messed up — possibly a partial upgrade or a mount issue. Checkdf -hto see if/usris mounted. - Is something re-exporting PATH after you set it? Check for any code in
.bashrcafter your fix that could override it. Also check/etc/bash.bashrcon Debian/Ubuntu. - Are you using a login shell vs an interactive shell? If the issue only happens on SSH login, the culprit is likely in
.profileor.bash_profile. If it happens in a new terminal, it's.bashrc.
One more thing — if you're in a container or a minimal distro like Alpine, the default PATH might be shorter (like /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin but without /sbin if you're not root). Don't assume your distro includes everything. Test with command -v after fixing.
The real trick is to never let a script or config file overwrite PATH without appending. Make it a habit to always use $PATH in any export. Saves you a headache down the road — I've seen this exact thing take down a whole fleet of build servers because one deploy script had a typo.