skrypty powłoki nadal działają bez #! (linia sha-bang)

10

Jestem nowy w skryptach powłoki i wiele książek napisało, że używają wiersza #! (Sha-bang) na początku skryptu do wywołania interpretera. A to wywoła nową powłokę dla skryptu i wykona interpretację linia po linii. mojego podstawowego skryptu nadal działa bez magicznej linii.

więc moje pytania to:

  • skąd mój podstawowy skrypt dostał interpretera.
  • jak skrypt zdołał zlokalizować tłumacza.

teraz powiem ci o moim podstawowym skrypcie, który zawiera tylko następujący wiersz:

echo „podstawowy skrypt bez magicznych linii”

użytkownik1678213
źródło
2
Zobacz stackoverflow.com/questions/7268437/…
jasonwryan 10.10.12

Odpowiedzi:

3

Jeśli nie podano magicznej linii, do uruchomienia skryptu używana jest domyślna powłoka. Ta domyślna powłoka może być albo powłoką Bourne'a (sh), co ma miejsce w niektórych smakach, jednak w niektórych innych smakach domyślna powłoka jest taka sama jak powłoka logowania do jej wykonania. Chodzi o to: nie pozostawiaj systemowi decydowania o powłoce, zawsze podaj powłokę, którą chcesz w pierwszym wierszu.

Guru
źródło
1
może moja obecna powłoka wywołuje domyślną powłokę dla skryptu powłoki, który nie ma magicznych liczb.
user1678213,
1
@ user1678213 Tak, to twoja powłoka (a nie jądro) to robi.
Gilles 'SO - przestań być zły'
1
Wierzę, że POSIX nakazuje użycie / bin / sh w tym przypadku.
vonbrand
2
@vonbrand Jest to powszechne nieporozumienie. POSIX nie nakazuje, aby powłoka POSIX była /bin/sh, tylko jako pierwszy shplik wykonywalny znaleziony podczas eksploracji zgodnej ŚCIEŻKI.
jlliagre
3
To niepoprawne, nigdy nie jest używana „powłoka logowania” do jej wykonania. Może się jednak zdarzyć, że wywołująca powłoka (jeśli skrypt jest wywoływany z powłoki) może mieć swoje dziecko interpretujące ją.
Stéphane Chazelas
8

Po uruchomieniu programu jądro sprawdza, czy zaczyna się od jakiejś sekwencji bajtów magicznych . Jeśli plik wykonywalny zaczyna się od #!, jądro interpretuje resztę wiersza jako nazwę interpretera. Jeśli plik wykonywalny zaczyna się od \177ELF(gdzie \177jest bajt 127), ładuje plik jako plik wykonywalny ELF ; jest to obecnie normalny rodzaj w większości systemów unixowych.

Jeśli jądro nie rozpoznaje formatu pliku, odmawia wykonania pliku i zwraca błąd ENOEXEC (błąd formatu wykonania). Gdy powłoka to zauważy, bierze na siebie wykonanie programu jako skrypt powłoki.

Aby zobaczyć to w akcji, dodaj do skryptu kilka poleceń:

ps l $$
ls -l /proc/$$/exe
echo hello

(Dotyczy to Linuksa, dostosuj do innych uników). Następnie spróbuj uruchomić ten skrypt z różnych powłok. Zobaczysz, że niektóre powłoki spawnują nowe instancje, aby wykonać skrypt (bash, ksh93), a inne spawn /bin/sh(dash, pdksh, zsh).

Gilles „SO- przestań być zły”
źródło
Czego szukam z twoim ls -lpoleceniem? To: lrwxrwxrwx 1 i 0 Oct 11 05:15 exe -> /bin/bash-? Jeśli tak, co to mówi? Zauważyłem też, że mam SHELL=/bin/bashwłączony env, ale zmiana nie wydawała się zmieniać zachowania. Może to nie ma związku?
Emanuel Berg,
wygląda na to, że zmieniasz zmienną powłoki „SHELL”. jeśli tak, to zmieniasz tylko wartość zmiennej powłoki SHELL. nie zmienisz powłoki. w celu zmiany powłoki edytuj plik / etc / passwd.
user1678213,
2
@EmanuelBerg Tak (właściwie powinienem był napisać ls -l /proc/$$/exe). Te exepunkty linki do powłoki, która jest wykonującego skryptu. Po uruchomieniu skryptu zobaczysz, że bash interpretuje skrypt. Jeśli uruchomisz go np. Z pdksh, uruchomi się /bin/sh. Nie znam żadnej powłoki, która SHELLw takich okolicznościach używa zmiennej środowiskowej lub powłoki logowania.
Gilles 'SO - przestań być zły'
2
@ user1678213 Zmiana powłoki w /etc/passwdzmienia, która powłoka jest wykonywana, gdy logujesz się przez SSH lub na konsoli tekstowej. Nie zmienia to, która powłoka może wykonywać skrypty.
Gilles „SO- przestań być zły”
2
@ user1678213 Sprawdziłem, co tu napisałem, przeprowadzając testy. Żadna z powłok, które testowałem, nie spojrzała, /etc/passwdaby zdecydować, której powłoki użyć, rozwidliły instancję samych siebie lub wykonały /bin/sh.
Gilles 'SO - przestań być zły'
-2

To prawdopodobnie jedna z następujących 3 możliwości:

  1. Wywołujesz skrypt bezpośrednio za pomocą interpretera, IE: bash script.sh

  2. Nazwa pliku skryptu ma rozszerzenie .sh, które powoduje, że system szuka domyślnego programu dla tego typu pliku

  3. Środowisko powłoki, którego używasz, samo wykonuje „echo”, ponieważ mogę tylko zgadywać, że plik skryptu jest wykonywalny. Jeśli, na przykład, będziesz używał powłoki bash i będziesz mieć w swoim poleceniu polecenie, które jest używane tylko przez ksh, to zobaczysz, że to nie zadziała.

Powodzenia!

bizna
źródło
3
nie nazwałam go bash ani żadnym rozszerzeniem.
user1678213,
1
a środowisko powłoki nie wykonuje go, ponieważ kiedy wywołuję polecenie ps po wywołaniu skryptu. polecenie ps pokazuje dwa procesy bash. co oznacza, że ​​działają dwa bash. jeden to moja powłoka bash do logowania, a drugi to bash dla mojego skryptu_podstawowego
user1678213,
1
2: jądro nic takiego nie zrobi. Zsh może to zrobić, a bash można do tego przekręcić. 3: Tak, ale różni się nieco między pociskami, patrz moja odpowiedź.
Gilles 'SO - przestań być zły'