Почему sudo пишет command not found — хотя без sudo команда работает

Странная картина:
npm -v
# 10.9.2
sudo npm -v
# sudo: npm: command not found
Только что npm был. Добавил одно слово — и его нет. Как будто sudo смотрит на другой компьютер.
Почти так и есть. sudo запускает команду не в твоём окружении, а в чистом и урезанном. Это защита, а не баг. Ниже пять причин, на которых чаще всего спотыкаются, — от самой частой к редкой.
Причина 1. У sudo свой PATH
Когда ты пишешь npm, оболочка ищет программу по папкам из переменной PATH. У тебя там есть, например, ~/.nvm/versions/node/v22/bin — туда поставил Node менеджер nvm.
А sudo твой PATH выбрасывает. Вместо него он подставляет secure_path — короткий список системных папок из настроек sudo. Твоей папки с nvm там нет. Отсюда command not found.
Как проверить:
sudo grep secure_path /etc/sudoers
# Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
which npm
# /home/me/.nvm/versions/node/v22.11.0/bin/npm
Если папки из which нет в secure_path — это оно.
Как починить:
- Лучший вариант — убрать sudo. С nvm, pyenv, Homebrew и подобными глобальные пакеты ставятся в твою домашнюю папку. Права root им не нужны.
npm install -gбез sudo — это правильно, а не ошибка. - Если root правда нужен — передай свой PATH явно:
sudo env "PATH=$PATH" npm install. - Полный путь
sudo "$(which npm)"тут не спасёт. npm внутри сам вызываетnode— и снова ищет его по урезанному PATH. Для обычных программ без таких зависимостей полный путь работает.
Редактировать secure_path в /etc/sudoers ради одной программы не стоит: ошибка в этом файле может оставить тебя совсем без sudo.
Причина 2. sudo сбрасывает переменные
Переменная задана, программа её не видит:
export API_KEY=abc123
sudo python deploy.py
# KeyError: 'API_KEY'
Это настройка env_reset: sudo по умолчанию очищает почти все переменные окружения. Иначе через них можно было бы подсунуть программе от root что-то опасное.
Как проверить:
X=hi sudo sh -c 'echo "[$X]"'
# []
Пустые скобки — переменная не дошла.
Как починить:
- Передать одну переменную:
sudo API_KEY="$API_KEY" python deploy.py. Самый аккуратный способ. - Сохранить всё окружение:
sudo -E python deploy.py. Работает, но тащит под root всё подряд — лучше по одной.
Причина 3. Permission denied при записи в файл
Здесь ошибка другая, но удивляет так же:
sudo echo "127.0.0.1 myapp.local" >> /etc/hosts
# bash: /etc/hosts: Permission denied
Ты же написал sudo! Но sudo получил только echo "...". А стрелку >> выполняет твоя оболочка, ещё до запуска sudo, с твоими обычными правами. Root напечатал строку, а записать её в файл пыталась не-root оболочка.
Как починить: отдай запись программе, которая работает от root.
echo "127.0.0.1 myapp.local" | sudo tee -a /etc/hosts
tee с флагом -a дописывает в конец файла, и он запущен через sudo. Если нужно записать много строк сразу — тот же sudo tee удобно сочетать с heredoc. Ещё вариант — завернуть всю команду: sudo sh -c 'echo "..." >> /etc/hosts'.
Причина 4. Алиасы не работают после sudo
У тебя есть алиас ll для ls -la. Пишешь sudo ll — и command not found.
Оболочка раскрывает алиас только у первого слова команды. Первое слово здесь — sudo, а ll она уже не проверяет. А сам sudo про твои алиасы ничего не знает: они живут в настройках оболочки, а не в системе.
Как починить: добавь в ~/.bashrc или ~/.zshrc одну строку:
alias sudo='sudo '
Пробел в конце — это и есть фокус. Если значение алиаса кончается пробелом, оболочка проверяет на алиас и следующее слово. Теперь sudo ll работает.
Причина 5. sudo cd и другие встроенные команды
sudo cd /root
# sudo: cd: command not found
cd, source, export, alias — это не программы на диске. Это команды внутри самой оболочки. Их нельзя найти ни в каком PATH, потому что отдельного файла нет. А sudo умеет запускать только файлы.
Свежие версии sudo даже подсказывают прямо в ошибке: «is a shell built-in command».
Как починить: если нужно поработать в закрытой папке, открой оболочку от root целиком — sudo -s — и выйди через exit, когда закончишь. Для одной команды хватит sudo sh -c 'cd /root && ls': здесь оболочка запускается от root и уже сама выполняет cd.
Быстрая диагностика
Сломалось что-то под sudo — пройди по списку:
command not found→ сравниwhich командас secure_path. Скорее всего, sudo тут вообще лишний.- Программа не видит переменную → передай её явно:
sudo VAR="$VAR" команда. Permission deniedпри>или>>→ замени на| sudo tee.- Не работает алиас →
alias sudo='sudo '. sudo cdилиsudo source→ это встроенные команды, нуженsudo -sилиsudo sh -c '...'.
Можно ли просто всё делать через sudo su?
Можно, но это как ходить по дому с ключами от всех дверей. Одна опечатка — и root удалит не то. Повышай права на одну команду, а не на всю сессию.
Почему на моём Mac такой проблемы нет?
На macOS sudo по умолчанию оставляет твой PATH, поэтому первая причина там почти не встречается. Остальные три — сброс переменных, перенаправление и алиасы — работают так же, как в Linux.
Короткие уроки-истории, симулятор агента и ежедневная практика — в нашем мобильном приложении. Бесплатно.





