Почему командная строка * nix разрешает выполнение по пути относительно текущего каталога? - PullRequest
0 голосов
/ 16 мая 2018

Долгое время у меня сложилось впечатление, что оболочки * NIX не поддерживают запуск исполняемых файлов по пути относительно текущего каталога. Также есть ряд постов, объясняющих, почему наличие рабочего каталога в пути - плохая практика. Тем не менее, легко увидеть, что работает следующий пример:

% cat<<EOF > temp/a
? #!/bin/sh
? echo "Hello looser!"
? EOF
% chmod 750 temp/a
% temp/a
Hello looser!

(я тестировал в CentOS и OSX).

Почему это работает?

Upd: это не чисто академический вопрос, у меня были случаи, когда двоичные файлы выполнялись по полному пути, и описанный выше способ работал иначе.

Upd 2: libc execv принимает как абсолютные, так и относительные пути без проблем. Следовательно, поддержка subpath/exe при невозможности запустить exe выглядит как функция оболочки, общая для bash и tcsh. Должна быть какая-то логика за этим ??

Ответы [ 3 ]

0 голосов
/ 16 мая 2018

Это как никак не связано с казнью. Это связано с тем, что вы можете назвать файл с абсолютным или относительным именем, а исполняемые файлы - это просто обычные файлы.

Почему это опасно? (. в PATH)

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

0 голосов
/ 16 мая 2018

Если вы пишете command без /, то оболочка ищет команду $PATH.

Если вы пишете dir/command с относительной директорией, есть /, а оболочка не ищет $PATH. Это интерпретирует это относительно текущего каталога. dir/command всегда разрешается до ./dir/command.

Ввод . в $PATH опасен, поскольку вы можете набрать command, намереваясь запустить /usr/bin/command, но на самом деле получить ./command, если он существует в текущем каталоге. Действительно, опасен не только .: опасен любой относительный путь. $PATH должен содержать только абсолютные пути.


Итак, вы говорите, что относительные пути должны неявно иметь префикс перед текущим каталогом, в исключительном случае, когда относительный путь пуст, что следует рассматривать как направление поиска в $PATH?

Да, вы могли бы сказать это. Но я предпочитаю переосмыслить это. Лучший способ думать об этом - понять, что делает shell по сравнению с kernel .

Интерпретация относительных путей обрабатывается ядром неявно. Когда оболочка выполняет системный вызов типа execve("dir/command", ...) для выполнения программы, ядро ​​знает текущий каталог родительского процесса и разрешает dir/command относительно него. Оболочка не должна сначала преобразовывать путь в абсолютный. Ядро может обрабатывать как абсолютные, так и относительные пути.

Однако ядро ​​ничего не знает о $PATH. Это конструкция оболочки. Имейте в виду, что оболочка является частью программного обеспечения более высокого уровня. Оболочка решает, что если вы введете простое имя команды без /, она не просто передаст эту команду ядру. Если это произойдет, то набрав cat, вы просто выполните ./cat. Никто не хочет этого.

Вместо этого оболочка решает, что отсутствие / означает, что она будет искать команду в $PATH. Он будет искать /bin, /usr/bin, $HOME/bin и т. Д. Если вы перечислили . в $PATH, он также будет искать в текущем каталоге & mdash; не делайте этого! Вы не хотите, чтобы он работал ./cat. Нет, сэр.

Если оболочка находит исполняемый файл в $PATH, она преобразует его в абсолютный путь и передает его ядру. Ядро видит execve("/usr/bin/cat", ...).


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

См. Справочную страницу bash :

Если имя команды не содержит косых черт, оболочка пытается найти его. ...

Если имя ... не содержит косых черт, bash ищет в каждом элементе PATH каталог, содержащий исполняемый файл с этим именем. …

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

0 голосов
/ 16 мая 2018

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...