Возможно ли иметь шебанг, который вместо указания пути к интерпретатору имеет имя интерпретатора и позволяет оболочке найти его через $ PATH?
Если нет, то есть ли причина?
Возможно ли иметь шебанг, который вместо указания пути к интерпретатору имеет имя интерпретатора и позволяет оболочке найти его через $ PATH?
Если нет, то есть ли причина?
Ответы:
Поиск в PATH является функцией стандартной библиотеки C в пользовательском пространстве, как и переменные среды в целом. Ядро не видит переменные окружения, за исключением случаев, когда оно переходит из окружения от вызывающего execveк новому процессу.
Ядро не выполняет никакой интерпретации пути в execve(это зависит от функций-оболочек, таких как execvpвыполнение поиска в PATH) или в шебанге (который более или менее перенаправляет execveвызов внутри). Так что вам нужно поставить абсолютный путь в шебанге. Оригинальная реализация притон была всего лишь несколько строк кода, и он не был значительно расширен с тех пор.
В первых версиях Unix оболочка вызывала себя сама, когда замечала, что вы запускаете скрипт. Шебанг был добавлен в ядро по нескольким причинам (резюмируя обоснование Денниса Ричи :
Шебанги без путей потребовали бы либо дополнить ядро для доступа к переменным и процессам среды PATH, либо чтобы ядро выполнило программу пользовательского пространства, которая выполняет поиск по PATH. Первый метод требует добавления непропорциональной сложности ядра. Второй способ уже возможен с #!/usr/bin/envШебанг .
¹ Если вы укажете относительный путь, он будет интерпретирован относительно текущего каталога процесса (а не каталога, содержащего скрипт), что вряд ли полезно в шебанге.
execveни в шебанге, хотя не имеет смысла иметь относительный путь в шебанге.
/lib64/ld-linux-x86-64.so.2(см. lddВывод). Linux делает его полностью универсальным: binfmtподдержка (начиная с 2.1.43) позволяет регистрировать пары интерпретатор-путь / магическое число или расширение файла. Вы можете .exeвызывать PE32 wineпри их запуске, вызывать классы Java и файлы jar javaи т. Д. И т. Д.
Там происходит больше, чем кажется на первый взгляд. #!строки интерпретируются ядром Unix или Linux, #!не является аспектом оболочек. Это означает, что на PATHсамом деле не существует в то время, когда ядро решает, что выполнять.
Наиболее распространенный способ справиться с незнанием того, какой исполняемый файл запустить, или вызвать perlпереносным способом или подобным, - это использовать #!/usr/bin/env perl. Выполняется ядро /usr/bin/env, которое наследует PATHпеременную окружения. envНаходки (в данном примере) perlв PATHи использует execve(2)системный вызов , чтобы получить ядро для запуска perlисполняемого файла.
$ strace sleep 1
execve("/usr/bin/sleep", ["sleep", "1"], [/* 99 vars */]) = 0
Преобразование в полный путь выполняется с помощью оболочки (более общего: в пользовательском пространстве). Ядро ожидает имя файла / путь, к которому оно может получить прямой доступ.
Если вы хотите, чтобы система нашла ваш исполняемый файл, просмотрев переменную PATH, вы можете переписать свой shebang как #!/usr/bin/env EXEC.
Но и в этом случае поиск выполняет не ядро.
strace(преобразована /usr/bin/straceв какой-то момент) с 2 аргументами.