exec
Wywołanie systemowe jądra Linux rozumie shebangs ( #!
) natywnie
Kiedy robisz na bash:
./something
w Linuksie wywołuje to wywołanie exec
systemowe ze ścieżką ./something
.
Ta linia jądra zostaje wywołana w pliku przekazanym do exec
: https://github.com/torvalds/linux/blob/v4.8/fs/binfmt_script.c#L25
if ((bprm->buf[0] != '#') || (bprm->buf[1] != '!'))
Odczytuje pierwsze bajty pliku i porównuje je #!
.
Jeśli porównanie jest prawdziwe, reszta linii jest analizowana przez jądro Linuksa, które wykonuje kolejne exec
wywołanie ze ścieżką /usr/bin/env python
i bieżącym plikiem jako pierwszym argumentem:
/usr/bin/env python /path/to/script.py
i działa to na każdy język skryptowy, który używa #
jako znaku komentarza.
I tak, możesz wykonać nieskończoną pętlę za pomocą:
printf '#!/a\n' | sudo tee /a
sudo chmod +x /a
/a
Bash rozpoznaje błąd:
-bash: /a: /a: bad interpreter: Too many levels of symbolic links
#!
akurat jest czytelny dla ludzi, ale nie jest to wymagane.
Jeśli plik zaczął się od różnych bajtów, exec
wywołanie systemowe użyłoby innej procedury obsługi. Innym najważniejszym wbudowanym modułem obsługi są pliki wykonywalne ELF: https://github.com/torvalds/linux/blob/v4.8/fs/binfmt_elf.c#L1305, który sprawdza bajty 7f 45 4c 46
(które również są ludźmi) czytelne dla .ELF
). Potwierdźmy to, czytając 4 pierwsze bajty /bin/ls
, czyli plik wykonywalny ELF:
head -c 4 "$(which ls)" | hd
wynik:
00000000 7f 45 4c 46 |.ELF|
00000004
Więc kiedy jądro zobaczy te bajty, pobiera plik ELF, poprawnie zapisuje go w pamięci i rozpoczyna z nim nowy proces. Zobacz także: https://stackoverflow.com/questions/8352535/how-does-kernel-get-an-executable-binary-file-running-under-linux/31394861#31394861
Na koniec możesz dodać własne binfmt_misc
mechanizmy shebang z mechanizmem. Na przykład możesz dodać niestandardowy moduł obsługi .jar
plików . Ten mechanizm obsługuje nawet programy obsługi według rozszerzeń plików. Inną aplikacją jest przezroczyste uruchamianie plików wykonywalnych o innej architekturze za pomocą QEMU .
Nie sądzę jednak, że POSIX określa shebangs: https://unix.stackexchange.com/a/346214/32558 , chociaż wspomina o tym w sekcjach uzasadnienia oraz w formie „jeśli skrypty wykonywalne są obsługiwane przez system, coś może się zdarzyć".
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