Многие говорят, что по соображениям безопасности текущий каталог не находится в $PATH и Linux не просматривает текущий каталог, чтобы узнать, доступна ли конкретная команда из этого каталога. но я сделал cd /usr/bin затем ls и все заработало; также я сделал echo $PATH и вывод содержит /usr/bin .

Вы должны заметить, что по соображениям безопасности текущий каталог отсутствует в $PATH и Linux не просматривает текущий каталог, чтобы узнать, доступна ли конкретная команда из этого каталога.

Руководство по сертификации Red Hat® RHCSATM/RHCE® 7 от Сандер ван Вугт

Почему я могу запустить ls , находясь в /usr/bin?

2 ответа2

6

linux не просматривает текущий каталог, чтобы узнать, доступна ли конкретная команда из этого каталога

Это правда, но это выглядит во всех каталогах , указанных в переменной $PATH даже если вы могли бы быть в таком каталоге на данный момент.

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

0

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

Этот документ описывает, в какой последовательности POSIX-совместимая оболочка должна искать команды. Это очень общий, не самый простой способ понять. Вместо того, чтобы анализировать эту крайне абстрактную процедуру, давайте посмотрим, как действует реальная оболочка.

Если предположить,

  • ваш $PATH выглядит так: /usr/local/bin:/usr/bin:/bin ;
  • ты в Баш;
  • вы вводите ls и нажимаете Enter ;
  • псевдоним ls не изменил бы команду на что-то другое, кроме ls ;

тогда Bash запустит первый существующий объект ls из списка ниже. Именно этот список с учетом вашего случая.

  1. функция ls .
  2. ls (обычно ls не является встроенным в Bash; но поскольку Bash может динамически загружать новые встроенные команды, вы можете сделать ls встроенным).
  3. Исполняемый файл ls с полным путевым именем, хранящимся в хеш-таблице (это произойдет, если когда-то в прошлом исполняемый файл ls был найден в соответствии со следующим пунктом и все еще запоминается)
  4. ls исполняемого от $PATH В вашем случае последовательность:
    1. /usr/local/bin/ls
    2. /usr/bin/ls
    3. /bin/ls

Обратите внимание, что в процедуре нет ./ls ; ни в какой момент ваш текущий рабочий каталог не принимается во внимание, особенно если он не сопоставлен с записями в $PATH .

Теперь это утверждение

Linux не просматривает текущий каталог, чтобы узнать, доступна ли конкретная команда из этого каталога

только означает, что в приведенном выше списке нет ./ls в жестком коде . Он появится в списке, если ваш $PATH содержится . но

по соображениям безопасности текущий каталог не находится в $PATH

Я объясню эти причины позже в ответе. Тем не менее вы можете добавить . на ваш $PATH самостоятельно. В этом случае ./ls появится в списке как запись 4.x. Сравните это с Windows, которая будет искать ls в текущем рабочем каталоге независимо от того, находится он в $PATH или нет. Если бы Linux делал то же самое, то всегда была бы запись ./ls жестко закодированная где-то выше пункта 3 нашего списка.

Если текущим рабочим каталогом является /usr/bin а в списке написано, что ls должен разрешиться в /usr/bin/ls , то технически он исполняется так же, как ./ls

  • оболочка никогда не использует буквальный путь ./ls , процедура выдает /usr/bin/ls ;
  • тот факт, что вы находитесь в /usr/bin ничего не значит;
  • тот факт, что /usr/bin находится в $PATH очень много значит.

Но если бы вы имели . в качестве первой записи в вашем $PATH то

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

В обоих случаях это один и тот же исполняемый файл, который запускается в конце дня, но оболочка попадает к нему по-разному.

Стоит также отметить, что такие выражения, как «мой текущий рабочий каталог находится в моем $PATH » или «я нахожусь в каталоге, который находится в моем $PATH », не рассказывают всей истории. Они могут означать:

  • « /some/particular/directory находится в моем каталоге $PATH и в данный момент я нахожусь в /some/particular/directory »

или же

  • . запись в моем $PATH

Как показано, два случая различаются.


Похоже , что вы ожидали ls не будет найдено только потому , что вы оказались в его каталоге. Ну, это было бы неудобно, в то время как не было бы никакого преимущества безопасности вообще. Основной причиной безопасности не имея . как фиксированный шаг в общей последовательности поиска команд и за отсутствие . в $PATH описаны в этом FAQ по UNIX:

Рассмотрим, что происходит в случае, когда . это первая запись в PATH . Предположим, что ваш текущий каталог является общедоступным для записи, например, /tmp . Если какая-то другая программа оставила там программу с именем /tmp/ls и вы ls (намереваясь, конечно, запустить обычную программу /bin/ls ), вместо этого будет запущена ваша оболочка ./ls , программа другого пользователя. Излишне говорить, что результаты запуска неизвестной программы, как эта, могут вас удивить.

Нет смысла запрещать /usr/bin/ls только потому, что вы находитесь в /usr/bin . Если ls там злонамеренный, вы, вероятно, уже запустили его, работая в другом каталоге, или в конце концов запустите его, работая в другом каталоге.


ТЛ; др

Подводя итог, можно сказать, что ls в вашем примере работает, потому что найден /usr/bin/ls , а не ./ls . Тот факт, что последний путь переходит в первый, не имеет значения, потому что последний путь не используется в первую очередь. Он не используется, потому что «Linux не смотрит в текущий каталог…» (имеется в виду, что он не просматривается .). Тем не менее он выглядит в /usr/bin , потому что он находится в вашем $PATH .

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .