Стандарт оболочки POSIX говорит на этом сайте
http://pubs.opengroup.org/onlinepubs/9699919799/
о том, как оболочки используют PATH
для поиска исполняемых файлов:
«Список следует искать от начала до конца, применяя имя файла к каждому префиксу, пока не будет найден исполняемый файл с указанным именем и соответствующими разрешениями на выполнение».
Ну, это не то, как это работает в реальной реализации POSIX:
man which
говорит:
"возвращает пути к файлам (или ссылкам), которые были бы выполнены в текущей среде, если бы его аргументы были заданы как команды в строго POSIX-совместимой оболочке. Это делается путем поиска в PATH исполняемых файлов, соответствующих именам аргументы. Он не следует за символическими ссылками. "
Хорошо, давайте посмотрим на эту ситуацию:
$ pwd
/home/mark
$ echo $PATH
/home/mark/bin:
...
$ ls -l bin/foobar
lrwxrwxrwx 1 mark mark 18 Dec 12 22:51 bin/foobar -> /home/mark/foobar1
$ touch foobar1
$ which foobar
$ chmod a+x foobar1
$ which foobar
/home/mark/bin/foobar
Хорошо, вот символическая ссылка PATH
с правильным именем, и она сообщается ls
как исполняемая.
which
не смотрит на это вообще, а интересуется только тем, на что он указывает.
Это несмотря на тот факт, что оба man which
явно говорят, что они не следуют по символическим ссылкам (а мы действительно видим, что это не так, потому which foobar
что не печатает foobar1
), а также что документация оболочки POSIX, приведенная выше, никогда не упоминает следующие символические ссылки в PATH
алгоритме.
Так, which
а существующие оболочки ошибочны, или я не понимаю документацию?
УТОЧНИТЬ:
Я знаю и могу объяснить существующее поведение. Мой вопрос не «как это работает?». Что я знаю.
Мой вопрос касается документации: где моя ошибка в следовании документации, которую я цитировал. Или документация неверна?
МОТИВАЦИЯ: Почему меня это волнует?
Ну, я реализатор. Различные исполнители предъявляют разные требования. Для меня требование состоит в том, чтобы слово текущего стандарта POSIX ДОЛЖНО сопровождаться ТОЧНО (или, точнее, лучшим, каким оно может быть, потому что сам стандарт несколько глючит). Как будто это было слово Божие.
Теперь стандартная формулировка довольно ясна - следующие символические ссылки не упоминаются, где во многих других местах упоминается, где это необходимо сделать. Так что в этом случае нет.
Однако я всегда дважды проверяю, как dash
и как bash
себя вести, просто чтобы убедиться. Теперь, конечно, здесь есть небольшая проблема, dash
даже несмотря на то, что она называется POSIX, имеет множество мелких ошибок, соответствующих POSIX. bash
Я еще не нашел никаких ошибок с POSIX, но ... bash на самом деле не POSIX, это намного больше, чем это.
Так что у вас есть это. Вот почему я забочусь
источник
$PATH
может содержит символические ссылки. Попробуйwhich sh
.$PATH
нет никаких символических ссылок.lstat(2)
), после них обычно не указывается. Например, в описанииopen(2)
упоминаются только символические ссылки, когда речь идет о поведенииO_CREAT | O_EXCL
. Не нужно указывать, что целевой файл будет открыт.Ответы:
Разрешения самой символической ссылки не имеют значения. Вы даже не могли бы изменить их, если бы попытались.
Что имеет значение, так это права доступа к базовому файлу.
Хорошо, чтобы в вашем PATH каталоги содержали символические ссылки на исполняемые файлы. Фактически, вполне вероятно, что многие исполняемые файлы в вашем PATH являются символическими ссылками. Например, в системах, подобных debian / ubuntu:
Документация
От
man chmod
:пример
В оболочке есть тест,
-x
чтобы определить, является ли файл исполняемым. Давайте попробуем это:Таким образом, как и в случае с
which
оболочкой, оболочка не считает исполняемый файл программной ссылки, если базовый файл не является исполняемым.Как работает
В системе Debian
which
это сценарий оболочки. Соответствующий раздел кода:Как видите, он использует
-x
тест, чтобы определить, является ли файл исполняемым.POSIX определяет
-x
тест следующим образом:Так, POSIX проверяет то , что имя пути рассасывается в. Другими словами, он принимает символические ссылки.
POSIX exec функция
Функция POSIX exec следует символическим ссылкам. Спецификация POSIX идет долго, чтобы указать условия ошибки, о которых она может сообщить, если символические ссылки имеют круглую или слишком глубокую форму, например:
источник
which
это скрипт оболочки. Таким образом, это скорее всего просто использование-x
теста, который я показал. Согласно POSIX,-x
тестирует, «разрешает» ли файл исполняемый файл. Если вы видите что-то другое, куда вы смотрите?which
работает», или это так,-x
или что-то еще. Мне интересно знать, где я неправильно следую документации, которую я цитировал.exec
функции следующим образом символьные ссылки. Кажется, это ясно показывает, что файлы с символическими ссылками могут быть исполняемыми файлами под POSIX.man which
который говорит: «Он не канонизирует имена путей». Это не значит, что он не следует по ссылкам. Это означает только то, что, как вы заметили, это не «канонизирует» имена.В этом случае символические ссылки следуют прозрачно, без канонизации окончательного пути. Другими словами,
which
не имеет значения,/home/mark/bin
является ли символическая ссылка или нет. Что его волнует, так это то,/home/mark/bin/foobar
существует файл или нет. Это не нужно вручную сплющивающихся симлинками по пути - ОС может сделать это только штраф по своей собственной.И действительно, когда
which
запрашивается информация о файле/home/mark/bin/foobar
, ОС замечает,/home/mark/bin
что является символической ссылкой, следует за ней и успешно находитfoobar
в целевом каталоге.Это поведение по умолчанию, если программа не использует
open(…, O_NOFOLLOW)
илиfstatat(…, AT_SYMLINK_NOFOLLOW)
для доступа к файлу.[комментарии объединены в]
В то время как вы говорите , что утилиты оболочки сделать это на индивидуальной основе случая, это не то же самое с ядром системных вызовов: все файлы, связанные вызовы делать следуют символические ссылки по умолчанию, если флаг «NOFOLLOW» не дается. (Даже lstat следует за символическими ссылками во всех компонентах пути, кроме последнего.)
Если в спецификации явно не указано, что делать с символическими ссылками, это означает, что будет использоваться поведение по умолчанию. Таким образом, оболочка, следующая за алгоритмом пути, не разрешает символические ссылки вручную и явно не отказывается от ОС, делая то же самое. (Он просто объединяет каждый компонент $ PATH с именем исполняемого файла.)
Когда на странице справки which (1) говорится, что она не следует символическим ссылкам, это может означать несколько вещей, но версия GNU coreutils утверждает это следующим образом:
Это намного уже по объему - это только означает, что
which
он не будет пытаться вручную канонизировать все пути для удаления дубликатов, но это не означает, что инструмент откажется от символьных ссылок, следующих за ОС в целом. Например, если/bin
это символическая ссылка/usr/bin
, запускwhich -a sh
вернет оба/bin/sh
и/usr/bin/sh
.источник
which
руководства GNU гласит это по-разному: «Который будет считать разные эквивалентные каталоги разными, если один из них содержит путь с символической ссылкой».execve("/home/mark/bin/foobar", …)
ее, все символические ссылки будут отслеживаться.execve
аргумент, на самом деле, в моей реализации, это тоexecl()
же самое. Пожалуйста, если вы включите это в свой ответ, я приму.Оболочка соответствует своей документации в том смысле, что она следует правилам разрешения пути.
which
соответствует своей документации. Два делают немного разные вещи.Выходные данные
which
- это имя файла и путь ссылки, а не путь, на который указывает символическая ссылка. Это прописано в справочной странице.Когда команда выполняется, ссылка «следует» согласно Разделу 4.13 «Разрешение имени пути» в том же разделе . Соответствующее условие для выполнения файла:
источник