Это может быть глупый вопрос, но я все же задаю его. Если бы я объявил Шебанг
#!/bin/bash
в начале my_shell_script.sh
, так что я всегда должен вызывать этот скрипт с помощью Bash
[my@comp]$bash my_shell_script.sh
или я могу использовать, например,
[my@comp]$sh my_shell_script.sh
а мой скрипт определяет работающую оболочку с помощью шебанга? То же самое происходит с ksh
оболочкой? Я использую AIX.
scripting
executable
shebang
jrara
источник
источник
chmod +x my_shell_script.sh ; /path/to/my_shell_script.sh # or ./my_shell_script.sh if you happen to be in its directory
Ответы:
Притон
#!
является читаемым человеком экземпляр магического числа , состоящего из байтов строки0x23 0x21
, которая используется вexec()
семействе функций для определения , является ли файл , который будет выполняться сценарий или двоичным. Когда присутствуетexec()
shebang, вместо этого будет запускаться исполняемый файл, указанный после shebang.Обратите внимание, что это означает, что если вы вызываете сценарий, указав интерпретатор в командной строке, как это делается в обоих случаях, приведенных в вопросе,
exec()
он выполнит интерпретатор, указанный в командной строке, он даже не будет смотреть на сценарий.Итак, как уже отмечали другие, если вы хотите
exec()
вызвать интерпретатор, указанный в строке shebang, сценарий должен иметь установленный исполняемый бит и вызываться как./my_shell_script.sh
.Поведение легко продемонстрировать с помощью следующего скрипта:
Объяснение:
#!/bin/ksh
определяетksh
быть переводчиком.$$
содержит PID текущего процесса./proc/pid/exe
является символической ссылкой на исполняемый файл процесса (по крайней мере, в Linux; в AIX /proc/$$/object/a.out - ссылка на исполняемый файл).readlink
выведет значение символической ссылки.Пример:
Примечание : я показываю это на Ubuntu, где оболочка по умолчанию
/bin/sh
является символической ссылкой на тир ИЭ/bin/dash
и/bin/ksh
является символической ссылкой/etc/alternatives/ksh
, которая , в свою очередь , является символической ссылкой на/bin/pdksh
.источник
exec()
Упомянутый в этом ответе системный вызов, командаexec
- встроенная оболочка, поэтому вы не можете вызватьexec
программу из Node.js или Java. Однако любая команда оболочки, вызываемая, например,Runtime.exec()
в Java, в конечном итоге обрабатываетсяexec()
системным вызовом.child_process.{exec(),execFile(),spawn()
} все будет реализовано с помощью Cexec()
(черезprocess
).Да. Кстати это не глупый вопрос. Ссылка на мой ответ здесь . Начиная скрипт с #!
Это называется шебанг или линия "взрыва".
Это не что иное, как абсолютный путь к интерпретатору Bash.
Он состоит из знака числа и символа восклицательного знака (#!), За которым следует полный путь к интерпретатору, например / bin / bash.
Все сценарии в Linux выполняются с использованием интерпретатора, указанного в первой строке. Почти все сценарии bash часто начинаются с #! / Bin / bash (при условии, что Bash был установлен в / bin). Это гарантирует, что Bash будет использоваться для интерпретации сценария, даже если он выполняется под другой оболочкой. Шебанг был представлен Деннисом Ричи между версией 7 Unix и 8 в Bell Laboratories. Затем он был также добавлен к линии BSD в Беркли.
Игнорирование строки переводчика (шебанг)
Если вы не укажете строку интерпретатора, по умолчанию обычно используется / bin / sh. Но рекомендуется установить #! / Bin / bash line.
источник
#!/usr/bin/perl
#!/usr/local/bin/python
#!/usr/local/bin/ruby
другая распространенная запись в shebang, используемая для поддержки нескольких систем, - это использование env для поиска интерпретатора, который вы хотите использовать, например#!/usr/bin/env perl
#!/usr/bin/env python
env
, что на самом деле должно быть предпочтительнее? Python и Perl часто используютenv
, в то время как в сценариях оболочки это часто опускается, и shebang указывает на рассматриваемую оболочку.env
найти программу в $ PATH - это что-то вроде хака. Он не устанавливает переменные среды, как следует из названия. $ PATH может быть разным результатом для разных пользователей. Но это помогает сценариям работать без изменений в системах, которые помещают разумный интерпретатор perl в какое-то странное место.exec
Системный вызов ядра Linux понимает shebangs (#!
) изначальноКогда вы делаете на Bash:
в Linux это вызывает
exec
системный вызов с путем./something
.Эта строка ядра вызывается для файла, переданного по адресу
exec
: https://github.com/torvalds/linux/blob/v4.8/fs/binfmt_script.c#L25.Он читает самые первые байты файла и сравнивает их с
#!
.Если сравнение верно, то остальная часть строки анализируется ядром Linux, которое делает еще один
exec
вызов с путем/usr/bin/env python
и текущим файлом в качестве первого аргумента:и это работает для любого языка сценариев, который использует
#
в качестве символа комментария.И да, вы можете сделать бесконечный цикл с:
Bash распознает ошибку:
#!
бывает, что он читается человеком, но это не обязательно.Если файл начинается с разных байтов, то
exec
системный вызов будет использовать другой обработчик. Другой самый важный встроенный обработчик для исполняемых файлов ELF: https://github.com/torvalds/linux/blob/v4.8/fs/binfmt_elf.c#L1305, который проверяет байты7f 45 4c 46
(которые также являются человеческими для чтения.ELF
). Давайте подтвердим это, прочитав 4 первых байта/bin/ls
, который является исполняемым файлом ELF:выход:
Поэтому, когда ядро видит эти байты, оно берет файл ELF, правильно помещает его в память и запускает новый процесс с ним. Смотрите также: https://stackoverflow.com/questions/8352535/how-does-kernel-get-an-executable-binary-file-running-under-linux/31394861#31394861
Наконец, вы можете добавить свои собственные обработчики shebang с
binfmt_misc
механизмом. Например, вы можете добавить пользовательский обработчик для.jar
файлов . Этот механизм даже поддерживает обработчики по расширению файла. Другое приложение - для прозрачного запуска исполняемых файлов другой архитектуры с QEMU .Я не думаю, что POSIX определяет shebangs, однако: https://unix.stackexchange.com/a/346214/32558 , хотя он упоминает об этом в разделах обоснования и в форме «если исполняемые сценарии поддерживаются системой чем-то может случиться".
источник
./something
из оболочки не передаст полный путьexec
, но точно введенный путь. Вы можете исправить это в своем ответе? Сделайтеecho "$0"
в своем сценарии, и вы увидите, что это так.Фактически, если вы берете это, следовательно, исполняемый файл, отмеченный в строке shebang, является просто исполняемым файлом. Имеет смысл использовать некоторый текстовый интерпретатор как исполняемый, но это не обязательно. Просто для пояснения и демонстрации я сделал довольно бесполезный тест:
Названный файл test.txt и установить exectuable бит
chmod u+x test.txt
, то «под названием» это:./test.txt
. Как и ожидалось, содержимое файла выводится. В этом случае кошка не игнорирует линию Шебанга. Он просто выводит все строки. Таким образом, любой полезный интерпретатор должен игнорировать эту строку Шебанга. Для bash, perl и PHP это просто строка комментария. Так что да, они игнорируют линию Шебанга.источник
Из того, что я собрал, всякий раз, когда файл имеет установленный исполняемый бит и вызывается, ядро анализирует заголовок файла, чтобы определить, как поступить (насколько я знаю, вы можете добавить собственные обработчики для пользовательских форматов файлов через LKM). Если файл выглядит как текстовый файл с #! В начале в комбинации его выполнение отправляется другому исполняемому файлу (обычно это своего рода оболочка), путь к которому должен быть указан непосредственно после указанного шебанга в той же строке. Затем ядро переходит к выполнению оболочки и передает файл для обработки.
Короче говоря, не имеет значения, с какой оболочкой вы вызываете скрипт - ядро в любом случае отправит выполнение соответствующему.
источник
bash ./myscript.sh
и./myscript.sh
.