To może być głupie pytanie, ale wciąż je zadaję. Jeśli zadeklarowałem shebang
#!/bin/bash
na początku my_shell_script.sh
, więc zawsze muszę wywoływać ten skrypt za pomocą bash
[my@comp]$bash my_shell_script.sh
czy mogę użyć np
[my@comp]$sh my_shell_script.sh
a mój skrypt określa działającą powłokę za pomocą shebang? Czy to samo dzieje się ze ksh
skorupą? Korzystam z systemu AIX.
scripting
executable
shebang
jrara
źródło
źródło
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
Odpowiedzi:
Shebang
#!
jest czytelny dla człowieka wystąpienie magicznym numerem składającym się z łańcucha bajtów0x23 0x21
, który jest wykorzystywany przezexec()
rodzinę funkcji, aby określić, czy plik należy wykonać jest skrypt lub binarnym. Gdy shebang jest obecny,exec()
zamiast tego uruchomi plik wykonywalny określony po shebang.Zauważ, że oznacza to, że jeśli wywołasz skrypt, podając interpreter w wierszu poleceń, jak ma to miejsce w obu przypadkach podanych w pytaniu,
exec()
wykona on interpreter określony w wierszu poleceń, nawet nie spojrzy na skrypt.Tak więc, jak zauważyli inni, jeśli chcesz
exec()
wywołać interpreter określony w linii shebang, skrypt musi mieć ustawiony bit wykonywalny i wywoływany jako./my_shell_script.sh
.Zachowanie można łatwo wykazać za pomocą następującego skryptu:
Wyjaśnienie:
#!/bin/ksh
definiujeksh
się jako tłumacz ustny.$$
przechowuje PID bieżącego procesu./proc/pid/exe
jest dowiązaniem symbolicznym do pliku wykonywalnego procesu (przynajmniej w Linuksie; w systemie AIX /proc/$$/object/a.out jest linkiem do pliku wykonywalnego).readlink
wyświetli wartość dowiązania symbolicznego.Przykład:
Uwaga : Mam demonstrując to na Ubuntu, gdzie domyślna powłoka
/bin/sh
jest dowiązaniem do kreska IE/bin/dash
i/bin/ksh
jest dowiązaniem do/etc/alternatives/ksh
, co z kolei jest dowiązaniem do/bin/pdksh
.źródło
exec()
w tej odpowiedzi jest wywołanie systemowe, polecenieexec
to wbudowana powłoka, dlatego nie można wywołaćexec
programu z Node.js lub Java. Jednak każde polecenie powłoki wywołane np.Runtime.exec()
W Javie jest ostatecznie przetwarzane przezexec()
wywołanie systemowe.child_process.{exec(),execFile(),spawn()
} wszystko byłoby zaimplementowane przy użyciu Cexec()
(poprzezprocess
).Tak. Nawiasem mówiąc, nie jest to głupie pytanie. Odniesienie do mojej odpowiedzi jest tutaj . Uruchamianie skryptu za pomocą #!
Nazywa się to shebang lub „hukiem”.
To nic innego jak absolutna ścieżka do tłumacza Bash.
Składa się ze znaku liczbowego i znaku wykrzyknika (#!), Po którym następuje pełna ścieżka do interpretera, takiego jak / bin / bash.
Wszystkie skrypty w Linuksie są uruchamiane przy użyciu interpretera określonego w pierwszym wierszu Prawie wszystkie skrypty bash często zaczynają się od #! / Bin / bash (przy założeniu, że Bash został zainstalowany w / bin) To gwarantuje, że Bash będzie używany do interpretacji skryptu, nawet jeśli jest wykonywany pod inną powłoką. Shebang został wprowadzony przez Dennisa Ritchiego między wersją 7 Unix a 8 w Bell Laboratories. Następnie został również dodany do linii BSD w Berkeley.
Ignoring An Interpreter Line (shebang)
Jeśli nie określisz linii interpretera, domyślnie jest to / bin / sh. Zalecane jest jednak ustawienie linii #! / Bin / bash.
źródło
#!/usr/bin/perl
#!/usr/local/bin/python
#!/usr/local/bin/ruby
Innym powszechnym wpisem shebang używanym do obsługi wielu systemów jest użycie env do zlokalizowania interpretera, którego chcesz użyć, na przykład#!/usr/bin/env perl
#!/usr/bin/env python
env
, które z nich powinny być preferowane? Python i Perl często używająenv
, podczas gdy w skryptach powłoki jest to często pomijane, a shebang wskazuje na daną powłokę.env
znalezienie programu w $ PATH to trochę hack. Nie ustawia zmiennych środowiskowych, jak sugeruje nazwa. $ PATH może być innym rezultatem dla różnych użytkowników. Ale pomaga skryptom uruchamiać się bez modyfikacji w systemach, które umieszczają rozsądny interpreter perla w dziwnym miejscu.exec
Wywołanie systemowe jądra Linux rozumie shebangs (#!
) natywnieKiedy robisz na bash:
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#L25Odczytuje 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: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ą:
Bash rozpoznaje błąd:
#!
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 bajty7f 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:wynik:
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ć".
źródło
./something
z powłoki nie przejdzie pełnej ścieżki doexec
, ale dokładnie ścieżkę wprowadzoną. Czy możesz to poprawić w swojej odpowiedzi? Zróbecho "$0"
w swoim skrypcie, a zobaczysz, że tak jest.W rzeczywistości, jeśli weźmiesz to konsekwentnie, plik wykonywalny zanotowany w linii shebang jest tylko plikiem wykonywalnym. Sensowne jest użycie interpretera tekstu jako pliku wykonywalnego, ale nie jest to konieczne. Dla wyjaśnienia i demonstracji zrobiłem raczej bezużyteczny test:
Nazwie Test.txt pliku i ustawić wykonywalne bit
chmod u+x test.txt
, a następnie „o nazwie” go:./test.txt
. Zgodnie z oczekiwaniami zawartość pliku jest wyprowadzana. W tym przypadku kot nie ignoruje linii shebang. Po prostu wyświetla wszystkie linie. Każdy przydatny tłumacz powinien zatem móc zignorować tę linię shebang. W przypadku bash, perl i PHP jest to po prostu wiersz komentarza. Więc tak, te ignorują linię shebang.źródło
Z tego, co zebrałem, za każdym razem, gdy plik ma ustawiony bit wykonywalny i jest wywoływany, jądro analizuje nagłówek pliku w celu ustalenia, jak kontynuować (o ile wiem, możesz dodać niestandardowe programy obsługi niestandardowych formatów plików za pomocą LKM). Jeśli plik wydaje się być plikiem tekstowym o numerze #! kombinacja na początku, jej wykonanie jest wysyłane do innego pliku wykonywalnego (zwykle rodzaju powłoki), którego ścieżkę należy określić bezpośrednio po tym shebang, w tym samym wierszu. Jądro następnie wykonuje powłokę i przekazuje plik do obsłużenia.
Krótko mówiąc, nie ma znaczenia, z której powłoki wywołujesz skrypt - jądro wyśle wykonanie w odpowiedni sposób.
źródło
bash ./myscript.sh
i./myscript.sh
.