exec
Системний виклик ядра Linux розуміє shebangs ( #!
) спочатку
Коли ви робите баш:
./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
Нарешті, ви можете додати власні обробники шебанг із binfmt_misc
механізмом. Наприклад, ви можете додати спеціальний обробник .jar
файлів . Цей механізм навіть підтримує обробники за допомогою розширення файлу. Інша програма полягає у прозорому запуску виконуваних файлів іншої архітектури за допомогою QEMU .
Однак я не думаю, що POSIX не вказує shebangs: https://unix.stackexchange.com/a/346214/32558 , хоча це згадується в розділах обґрунтування та у формі "якщо виконувані сценарії підтримуються системою щось може статися ».
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