Хижина определяет оболочку, которая запускает скрипт?

Модули, перечисленные в /etc/mkinitcpio.conf включены в intitrd, когда он сгенерирован с mkinitcpio -p linux. Это загружает временную файловую систему в память и должно включать модули, необходимые для создания этого успешно, в зависимости от установки.

Пример добавил бы raid1 к Вашей строке модулей в /etc/mkinitcpio.conf собрать массив Raid1.

В Вашей строке модулей в /etc/rc.conf необходимо было бы только включать модули, которые автоматически не загружаются udev но это, которого можно потребовать для запуска определенных приложений однажды файловые системы, смонтировано, такой как fuse или loop.

Примечание: в случае Массива RAID Вы также включали бы USEDMRAID="yes" в Вашем /etc/rc.conf

87
22.08.2013, 01:29
5 ответов

Хижина #! человекочитаемый экземпляр магического числа, состоящего из строки байтов 0x23 0x21, который используется exec() семейство функций, чтобы определить, является ли файл, который будет выполняться, сценарием или двоичным файлом. Когда хижина присутствует, exec() выполнит исполняемый файл, указанный после хижины вместо этого.

Обратите внимание, что это означает что при вызове сценария путем определения интерпретатора на командной строке как сделан в обоих случаях данный в вопросе, exec() выполнит интерпретатор, указанный на командной строке, он даже не посмотрит на сценарий.

Так, как другие отметили, если Вы хотите exec() для вызова интерпретатора, указанного на строку хижины, сценарий должен иметь исполняемый набор битов и вызванный как ./my_shell_script.sh.

Поведение легко продемонстрировать со следующим сценарием:

#!/bin/ksh
readlink /proc/$$/exe

Объяснение:

  • #!/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.

$ chmod +x getshell.sh
$ ./getshell.sh 
/bin/pdksh
$ bash getshell.sh 
/bin/bash
$ sh getshell.sh 
/bin/dash
119
27.01.2020, 19:30
  • 1
    благодарит Thomas за этот ответ. Притворитесь, что мы запускаем сценарий как дочерний процесс от Node.js или Java или что бы то ни было. Мы можем запустить "исполнительный" процесс, и затем должностное лицо выполнит сценарий оболочки? Я спрашиваю beause, я ищу ответы на этот вопрос: stackoverflow.com/questions/41067872 / … –  Alexander Mills 09.12.2016, 22:26
  • 2
    @AlexanderMills exec() упомянутый в этом ответе системный вызов, команда exec встроенная оболочка, который является, почему Вы не можете вызвать exec программа от Node.js или Java. Однако любая команда оболочки, вызванная, например. Runtime.exec() в Java в конечном счете обрабатывается exec() системный вызов. –  Thomas Nyman 11.12.2016, 18:02
  • 3
    Ха, да я действительно знаком с Java API, который Вы просто упомянули, интересно, существует ли способ вызвать более низкое должностное лицо уровня () вызов от Node.js так или иначе –  Alexander Mills 11.12.2016, 21:51
  • 4
    @AlexanderMills я вообразил бы child_process.{exec(),execFile(),spawn()} все были бы реализованы с помощью C exec() (через process). –  Thomas Nyman 12.12.2016, 05:02

Да это делает. По тому, как это не глупый вопрос. Ссылка для моего ответа здесь. Запуск Сценария С #!

  • Это называют хижиной или строкой "удара".

  • Это - только полный путь к интерпретатору Bash.

  • Это состоит из знака номера и символа восклицательного знака (#!), сопровождаемый полным путем к интерпретатору, такому как/bin/bash.

    Все сценарии в соответствии с Linux выполняют использование интерпретатора, указанного на первой строке, Почти все сценарии удара часто начинаются с #!/bin/bash (предполагающий, что Bash был установлен в / мусорном ведре), Это гарантирует, что Bash будет использоваться для интерпретации сценария, даже если это будет выполняться под другой оболочкой. Хижина была представлена Dennis Ritchie между Unix Версии 7 и 8 в Bell Laboratories. Это было затем также добавлено к строке BSD в Беркли.

Игнорирование строки интерпретатора (хижина)

Если Вы не указываете строку интерпретатора, значение по умолчанию обычно является/bin/sh. Но, рекомендуется установить #!/bin/bash строка.

10
27.01.2020, 19:30
  • 1
    Для разработки ядро только знает, как выполнить статически связанные двоичные файлы и где найти информацию об интерпретаторе для других (специальное поле в двоичном файле или строка хижины). Обычно выполнение сценария оболочки значит после строки хижины для оболочки, и затем после поля DT_INTERP в двоичном файле оболочки динамическому компоновщику. –  Simon Richter 21.08.2013, 09:37
  • 2
    Также обратите внимание, что это не ограничено сценариями оболочки. Все основанные на тексте файлы сценария используют это. например, #!/usr/bin/perl #!/usr/local/bin/python #!/usr/local/bin/ruby Другая общая запись хижины, используемая для поддержки нескольких систем, должна использовать ENV для определения местоположения интерпретатора, как который Вы хотите использовать, #!/usr/bin/env perl #!/usr/bin/env python –  sambler 21.08.2013, 10:31
  • 3
    @sambler о env, который должен быть на самом деле предпочтен? Python и Perl часто используют env, в то время как на сценариях оболочки, это часто опускается, и хижина указывает на рассматриваемую оболочку. –  polemon 21.08.2013, 13:22
  • 4
    @polemon, меньше которых предпочтено и больше на котором варьируются пути. Основные оболочки находятся в том же пути во всех системах. Актуальные версии жемчуга и Python могут быть установлены в различных местоположениях в различных системах, настолько использующий ENV позволяет той же хижине всегда работать, который является, почему ENV используется больше с жемчугом и сценариями Python, чем сценарии оболочки. –  sambler 22.08.2013, 11:23

Из того, что я собрался, каждый раз, когда файл имеет исполняемый набор битов и вызывается, ядро анализирует заголовок файла, чтобы определить, как продолжить двигаться (насколько я знаю, можно добавить пользовательские обработчики для пользовательских форматов файлов через LKMs). Если файл, кажется, текстовый файл с #! комбинация в начале, его выполнение отправлено другому исполняемому файлу (обычно своего рода оболочка), путь, к которому должен быть указан непосредственно после упомянутой хижины, в той же строке. Ядро затем продолжает выполнять оболочку и передавать файл для него для обработки.

Короче говоря, это не имеет значения, какая оболочка Вы вызываете сценарий с - ядро отправит выполнение соответствующему так или иначе.

-1
27.01.2020, 19:30
  • 1
    Существуют заметные различия между bash ./myscript.sh и ./myscript.sh. –  a CVn 21.08.2013, 12:35
  • 2
    Что Вы подразумеваете под этими "заметными различиями"? разговор –  jrara 21.08.2013, 12:59
  • 3
    @jrara Видит мой ответ, оператор, что "он не имеет значения, какая оболочка Вы вызываете сценарий с", просто не верен. спасибо –  Thomas Nyman 21.08.2013, 13:33

Фактически, если вы так понимаете, исполняемый файл, указанный в строке shebang, является просто исполняемым файлом. Имеет смысл использовать какой-нибудь текстовый интерпретатор в качестве исполняемого файла, но в этом нет необходимости. Просто для пояснения и демонстрации я провел довольно бесполезный тест:

#!/bin/cat
useless text
more useless text
still more useless text

Назвал файл test.txt и установил исполняемый бит chmod u + x test.txt , затем «назвал» его: ./test.txt . Как и ожидалось, выводится содержимое файла. В этом случае кошка не игнорирует линию шебанг. Он просто выводит все строки. Таким образом, любой полезный интерпретатор должен иметь возможность игнорировать эту строку shebang. Для bash, perl и PHP это просто строка комментария. Так что да, они игнорируют строку shebang.

5
27.01.2020, 19:30

Системный вызов execядра Linux изначально понимает шебанги(#!)

Я не заметил, что OP спрашивал об AIX, я собираюсь сказать, что я знаю о Linux, и держу пари, что есть сильные аналогии или, по крайней мере, удовлетворят большинство гуглеров, которые ищут Linux:-)

Когда вы делаете на bash:

./something

в Linux вызывает системный вызов execс путем ./something.

Эта строка ядра вызывается для файла, переданного вexec:https://github.com/torvalds/linux/blob/v4.8/fs/binfmt_script.c#L25

if ((bprm->buf[0] != '#') || (bprm->buf[1] != '!'))

Он читает самые первые байты файла и сравнивает их с #!.

Если сравнение верно, то оставшаяся часть строки анализируется ядром Linux, которое выполняет еще один execвызов с путем /usr/bin/env pythonи текущим файлом в качестве первого аргумента:

/usr/bin/env python /path/to/script.py

, и это работает для любого языка сценариев, который использует #в качестве символа комментария.

И да, вы можете сделать бесконечный цикл с помощью:

printf '#!/a\n' | sudo tee /a
sudo chmod +x /a
/a

Bash распознает ошибку:

-bash: /a: /a: bad interpreter: Too many levels of symbolic links

#!просто удобочитаемо для человека, но это не обязательно.

Если бы файл начинался с других байтов, то системный вызов execиспользовал бы другой обработчик. Другой наиболее важный встроенный -обработчик предназначен для исполняемых файлов ELF :https://github.com/torvalds/linux/blob/v4.8/fs/binfmt_elf.c#L1305, который проверяет байты 7f 45 4c 46(, которые также могут быть читаемы человеком для.ELF). Давайте подтвердим это, прочитав 4 первых байта /bin/ls, который является исполняемым файлом ELF:

head -c 4 "$(which ls)" | hd 

выход:

00000000  7f 45 4c 46                                       |.ELF|
00000004                                                                 

Таким образом, когда ядро ​​видит эти байты, оно берет файл 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 определяет шебанги :https://unix.stackexchange.com/a/346214/32558, хотя упоминает об этом в разделах обоснования и в форме "если исполняемые скрипты поддерживаются системой, что-то может произойти".

5
27.01.2020, 19:30

Теги

Похожие вопросы