Вы используете Linux и увидели ошибку «Команда не найдена» при попытке выполнить команду? Пришло время узнать почему.

Давайте вместе рассмотрим эту ошибку и разберемся, как ее исправить.

В чем причина ошибки «команда не найдена»?

Ошибка «Команда не найдена» вызвана тем, что Linux не может найти в вашей системе команду, которую вы пытаетесь выполнить. При запуске команды Linux ищет двоичные файлы в списке каталогов, указанных в переменной среды PATH, что позволяет вам выполнить команду, не указывая ее полный путь.

В этой статье мы рассмотрим пример этой ошибки и покажем, как ее исправить.

Вы также поймете, как Linux (или Unix-подобные системы) ищут команды, когда пользователь их выполняет.

Начнем!

Переменная среды PATH

Системы Linux настроены с использованием предопределенного набора переменных среды, необходимых операционной системе для правильной работы.

Переменная окружения PATH — одна из важнейших переменных окружения в системе Linux. Она содержит список каталогов, используемых Linux для поиска команд, которые можно выполнить без указания их полного пути.

Вы можете использовать команду echo, чтобы увидеть значение переменной PATH:

[ec2-user@localhost ~]$ echo $PATH
/home/ec2-user/.local/bin:/home/ec2-user/bin:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin

В списке каталогов внутри PATH вы можете увидеть домашний каталог моего текущего пользователя (ec2-user), а также такие каталоги, как /usr/bin.

Давайте рассмотрим некоторые команды, присутствующие в каталоге /usr/bin. Чтобы ограничить список команд, возвращаемых ls, я просто ищу команды, начинающиеся с ch (для этого я использую подстановочный знак ch*):

[ec2-user@localhost]$ ls -al /usr/bin/ch*
-rwxr-xr-x. 1 root root  17488 May 11  2019 /usr/bin/chacl
-rwsr-xr-x. 1 root root 133928 Nov  8  2019 /usr/bin/chage
-rwxr-xr-x. 1 root root  19216 Nov  8  2019 /usr/bin/chattr
-rwxr-xr-x. 1 root root 150528 Apr  9 18:53 /usr/bin/chcon
-rwxr-xr-x. 1 root root 140232 Apr  9 18:53 /usr/bin/chgrp
-rwxr-xr-x. 1 root root  61920 Nov  8  2019 /usr/bin/chmem
-rwxr-xr-x. 1 root root 133952 Apr  9 18:53 /usr/bin/chmod
-rwxr-xr-x. 1 root root 146360 Apr  9 18:53 /usr/bin/chown
-rwxr-xr-x. 1 root root  47816 Nov  8  2019 /usr/bin/chrt
-rwxr-xr-x. 1 root root  14272 May 11  2019 /usr/bin/chvt

Давайте в качестве примера возьмем команду chmod.

Если я использую команду which для проверки полного пути команды chmod, я получаю следующее:

[ec2-user@localhost]$ which chmod
/usr/bin/chmod

Как вы видите, это точно такой же каталог в PATH, /usr/bin.

Тот факт, что /usr/bin/ находится в PATH, позволяет нам выполнять команду chmod без необходимости указывать полный путь.

Имеет ли это смысл?

Где определяется PATH в Linux?

Хотите узнать, где определена переменная среды PATH?

Давайте выясним…

Обычно он определяется где-то в вашем домашнем каталоге, а именно в одном из скрытых файлов, используемых в Linux для настройки пользовательской среды: файле .bashrc.

В Linux точка перед именем файла означает, что файл скрыт. Он не виден, если мы выполняем команду ls без флагов. Он виден, только если вы передадите флаг -a команде ls.

Файл .bashrc на самом деле является скриптом оболочки, который выполняется, когда Linux инициализирует интерактивную оболочку. Это позволяет вам настраивать среду так, как вам нужно, каждый раз, когда вы открываете оболочку.

Если я посмотрю на файл.bashrc в моей системе, то увижу следующие строки:

# User specific environment
PATH="$HOME/.local/bin:$HOME/bin:$PATH"
export PATH

Как вы можете видеть, переменная PATH определена, а затем она становится доступной для всех дочерних процессов этой оболочки с помощью команды export.

Если вы хотите добавить еще один каталог в PATH, вы можете просто обновить файл.bashrc.

Это обычное требование, если вы загружаете внешние инструменты, не являющиеся частью операционной системы Linux, и хотите иметь возможность запускать их из своей оболочки, не указывая полный путь к ним.

Одним из распространенных сценариев является добавление Java в PATH Linux после загрузки JDK (Java Development Kit) в вашу систему.

PATH настраивается на общесистемном уровне

Когда я вижу значение переменной PATH в моей системе, вот что я получаю:

/home/ec2-user/.local/bin:/home/ec2-user/bin:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin

Для меня есть что-то непонятное…

…в файле.bashrc в домашнем каталоге моего пользователя я вижу только:

PATH="$HOME/.local/bin:$HOME/bin:$PATH"

Итак, откуда взялись следующие каталоги, если их нет в файле.bashrc моего пользователя?

/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin

Они должны быть определены где-то на уровне системы, а не только на уровне пользователя.

В Linux общесистемные файлы конфигурации находятся в каталоге /etc. Например, в /etc/bashrc.

Давайте выясним, откуда берется это начальное значение PATH, используя рекурсивный grep от имени пользователя root в каталоге /etc.

[root@localhost]$ grep -r PATH /etc/* | grep "/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin"
/etc/ssh/sshd_config:# This sshd was compiled with PATH=/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin

Единственный результат находится в файле конфигурации для демона SSH. Согласно комментарию в этом файле, демон скомпилирован с PATH, установленным на значение, которое я вижу в своей системе.

Вот откуда берется ценность PATH!

Как исправить ошибку bash «command not found»?

До сих пор мы видели, что такое PATH…

…но как это поможет нам исправить ошибку «команда не найдена»?

Прежде всего, прежде чем рассматривать, как ошибка «команда не найдена» может быть связана с PATH, давайте рассмотрим простую причину.

Перед выполнением любых других проверок убедитесь, что вы не ошиблись в написании команды при ее выполнении.

Это может происходить в основном с теми, кто новичок в Linux и изучает команды.

Если вы правильно ввели команду, то продолжайте…

Следующая причина может заключаться в том, что каталог, в котором находится команда, отсутствует в PATH, и этому может быть две причины:

  1. Команда доступна в системе, но ее каталог отсутствует в PATH.
  2. Команда вообще недоступна в системе.

Сценарий 1 может возникнуть, если вы загрузили определенный инструмент в свою систему Linux и не добавили каталог, в котором находится двоичный файл, в переменную среды PATH.

Чтобы обновить значение PATH, вам необходимо изменить файл.bashrc.

Допустим, текущее значение PATH равно:

PATH="$HOME/.local/bin:$HOME/bin:$PATH"

И я хочу добавить в него каталог /opt/install, потому что именно там находится команда, которую я хочу выполнить. Эта строка станет:

PATH="$HOME/.local/bin:$HOME/bin:$PATH:/opt/install"

Порядок каталогов в PATH важен: первый каталог имеет более высокий приоритет, чем второй, и т. д.

Таким образом, если вы хотите, чтобы каталог /opt/install был первым, который будет просматриваться при выполнении команды, определение PATH будет выглядеть следующим образом:

PATH="/opt/install:$HOME/.local/bin:$HOME/bin:$PATH"

Обратите внимание на доллар $ перед PATH. Это ДЕЙСТВИТЕЛЬНО важно, потому что это относится к существующему значению переменной PATH.

Пропуск знака $ в этой строке может иметь катастрофические последствия для вашей системы. Это потому, что оболочка больше не будет знать, где найти основные команды, такие как ls, cd, vim и т. д.

В следующем разделе мы рассмотрим сценарий 2, когда команда недоступна в вашей системе Linux.

Выполнение команды, недоступной в системе

Теперь давайте посмотрим, что происходит, когда мы выполняем команду, которая недоступна в системе Linux.

Возьмем, к примеру, команду rsync:

[ec2-user@localhost ~]$ rsync
-bash: rsync: command not found

Как узнать, возникает ли ошибка «command not found» из-за того, что команда rsync отсутствует в PATH или ее вообще нет в системе?

Я могу использовать менеджер пакетов моего дистрибутива Linux. В этом случае я использую CentOS и поэтому я буду использовать команду yum, чтобы проверить, установлен ли пакет rsync:

yum list --installed | grep rsync

Эта команда не возвращает никаких результатов, это означает, что rsync недоступен в системе.

Другой вариант — использовать команду RPM для запроса RPM-пакетов, установленных в моей системе Linux:

rpm -qa | grep rsync

И снова никаких результатов по пакету rsync.

Итак, давайте установим его!

Команда поиска yum возвращает результат для rsync:

[ec2-user@localhost ~]$ yum search rsync
Last metadata expiration check: 1 day, 4:15:26 ago on Sun 19 Jul 2020 05:12:46 PM UTC.
=================================== Name Exactly Matched: rsync ===================================
rsync.x86_64: A program for synchronizing files over a network

И мы можем установить пакет rsync с помощью команды «yum install»:

[ec2-user@localhost ~]$ sudo yum install rsync
......
....

Installed:
  rsync-3.1.3-7.el8.x86_64

Complete!

И теперь, если я попытаюсь снова выполнить команду rsync, чтобы проверить ее версию:

[ec2-user@localhost ~]$ rsync --version
rsync  version 3.1.3  protocol version 31
Copyright (C) 1996-2018 by Andrew Tridgell, Wayne Davison, and others.
Web site: http://rsync.samba.org/

Команда работает хорошо!

Заключение

В этом руководстве мы рассмотрели три возможных сценария, в которых может возникнуть ошибка «command not found» в Linux при выполнении команды:

  1. Мы неправильно написали команду.
  2. Команда доступна в системе, но ее каталог отсутствует в PATH.
  3. Команда недоступна в системе.

Я также объяснил, как работает переменная среды PATH и насколько она важна для системы Linux.

Удалось ли вам найти причину этой ошибки в вашей системе?

Written by Иван Васильков

Системный администратор и DevOps с опытом 10+ лет.