Поиск в PATH является функцией стандартной библиотеки C в пользовательском пространстве, как и переменные среды в целом. Ядро не видит переменные окружения, за исключением случаев, когда оно переходит из окружения от вызывающего execveк новому процессу.
Ядро не выполняет никакой интерпретации пути в execve(это зависит от функций-оболочек, таких как execvpвыполнение поиска в PATH) или в шебанге (который более или менее перенаправляет execveвызов внутри). Так что вам нужно поставить абсолютный путь в шебанге. Оригинальная реализация притон была всего лишь несколько строк кода, и он не был значительно расширен с тех пор.
В первых версиях Unix оболочка вызывала себя сама, когда замечала, что вы запускаете скрипт. Шебанг был добавлен в ядро по нескольким причинам (резюмируя обоснование Денниса Ричи :
Вызывающему не нужно беспокоиться, является ли выполняемая программа сценарием оболочки или собственным двоичным файлом.
Сам скрипт указывает, какой интерпретатор использовать вместо вызывающего.
Ядро использует имя скрипта в логах.
Шебанги без путей потребовали бы либо дополнить ядро для доступа к переменным и процессам среды PATH, либо чтобы ядро выполнило программу пользовательского пространства, которая выполняет поиск по PATH. Первый метод требует добавления непропорциональной сложности ядра. Второй способ уже возможен с #!/usr/bin/envШебанг .
¹ Если вы укажете относительный путь, он будет интерпретирован относительно текущего каталога процесса (а не каталога, содержащего скрипт), что вряд ли полезно в шебанге.
Нет, ядро не требует абсолютного пути execveни в шебанге, хотя не имеет смысла иметь относительный путь в шебанге.
Стефан Шазелас
3
Для всех, кому интересно, как «shebang перенаправляет внутренний вызов execve»: на самом деле это часть общего механизма запуска интерпретаторов на исполняемых файлах, которые в них нуждаются. Динамически связанные исполняемые файлы ELF «интерпретируются» /lib64/ld-linux-x86-64.so.2(см. lddВывод). Linux делает его полностью универсальным: binfmtподдержка (начиная с 2.1.43) позволяет регистрировать пары интерпретатор-путь / магическое число или расширение файла. Вы можете .exeвызывать PE32 wineпри их запуске, вызывать классы Java и файлы jar javaи т. Д. И т. Д.
Питер Кордес,
#! / usr / bin / env -S [shebang] был необходим для того, чтобы я запустил узел, не зная его пути (используя nvm - который размещает его в другом месте, чем я изначально ожидал).
Там происходит больше, чем кажется на первый взгляд. #!строки интерпретируются ядром 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 аргументами.
Ответы:
Поиск в 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
вызывать PE32wine
при их запуске, вызывать классы Java и файлы jarjava
и т. Д. И т. Д.Там происходит больше, чем кажется на первый взгляд.
#!
строки интерпретируются ядром Unix или Linux,#!
не является аспектом оболочек. Это означает, что наPATH
самом деле не существует в то время, когда ядро решает, что выполнять.Наиболее распространенный способ справиться с незнанием того, какой исполняемый файл запустить, или вызвать
perl
переносным способом или подобным, - это использовать#!/usr/bin/env perl
. Выполняется ядро/usr/bin/env
, которое наследуетPATH
переменную окружения.env
Находки (в данном примере)perl
вPATH
и используетexecve(2)
системный вызов , чтобы получить ядро для запускаperl
исполняемого файла.источник
Преобразование в полный путь выполняется с помощью оболочки (более общего: в пользовательском пространстве). Ядро ожидает имя файла / путь, к которому оно может получить прямой доступ.
Если вы хотите, чтобы система нашла ваш исполняемый файл, просмотрев переменную PATH, вы можете переписать свой shebang как
#!/usr/bin/env EXEC
.Но и в этом случае поиск выполняет не ядро.
источник
strace
(преобразована/usr/bin/strace
в какой-то момент) с 2 аргументами.