W przypadku skryptu csh powinieneś użyć #!/bin/csh -f; -fmówi powłoce nie pozyskać użytkownika .logini .cshrc, co sprawia, że szybciej uruchomić skrypt i unika zależności od ustawień użytkownika. (Lub jeszcze lepiej, nie pisz skryptów csh.) Nie używaj -fdo skryptów sh lub bash; nie ma tego samego znaczenia.
@Kolob Canyon nie musisz, ale może pomóc niektórym redaktorom w podświetlaniu składni (chociaż zwykle są inne sposoby na osiągnięcie tego samego): unix.stackexchange.com/a/88730/193985
Braham Snyder
42
#!Linia informuje jądro (w szczególności realizacji execvewywołania systemowego), że ten program jest napisany w języku interpretowanym; bezwzględna nazwa ścieżki, która następuje, identyfikuje interpretera. Programy skompilowane do kodu maszynowego zaczynają się od innej sekwencji bajtów - w większości nowoczesnych Uniksów, 7f 45 4c 46( ^?ELF), która je identyfikuje.
Możesz umieścić bezwzględną ścieżkę do dowolnego programu po tagu #!, o ile sam ten program nie jest #!skryptem. Jądro przepisuje wywołanie
./script arg1 arg2 arg3 ...
gdzie ./scriptzaczyna się, powiedzmy, #! /usr/bin/perltak, jakby wiersz poleceń faktycznie istniał
/usr/bin/perl ./script arg1 arg2 arg3
Lub, jak widziałeś, możesz użyć #! /bin/shdo napisania skryptu, który ma być interpretowany przez sh.
#!Linii są przetwarzane tylko wtedy, gdy bezpośrednio wywołać skrypt ( ./scriptw linii poleceń); plik musi być również wykonywalny ( chmod +x script). Jeśli nie linia nie jest konieczne (i będą ignorowane, jeśli jest obecny), a plik nie musi być wykonywalny. Punkt z tej funkcji jest umożliwienie Ci bezpośrednio invoke programów interpretowany języków bez konieczności znać język, jakim są napisane. (Do - będzie można odkryć, że bardzo wiele programów akcji są w rzeczywistości przy użyciu tej funkcji.)sh ./script#!grep '^#!' /usr/bin/*
Oto kilka zasad korzystania z tej funkcji:
#!Muszą być dwie bardzo pierwsze bajty w pliku. W szczególności plik musi być kodowany zgodnie z ASCII (np. UTF-8 będzie działać, ale UTF-16 nie) i nie może zaczynać się od „znaku kolejności bajtów”, w przeciwnym razie jądro nie rozpozna go jako #!scenariusz.
Ścieżka po #!musi być ścieżką bezwzględną (zaczyna się od /). Nie może zawierać znaków spacji, tabulacji ani nowej linii.
Jest to dobry styl, ale nie jest to wymagane, aby wstawić spację między #!i /. Nie umieszczaj tam więcej niż jednej spacji.
Nie możesz umieścić zmiennych powłoki w #!linii, nie zostaną one rozwinięte.
Możesz umieścić jeden argument wiersza poleceń po ścieżce bezwzględnej, oddzielony od niej pojedynczą spacją. Podobnie jak ścieżka bezwzględna, ten argument nie może zawierać znaków spacji, tabulacji ani nowego wiersza. Czasami jest to konieczne, aby rzeczy działały ( #! /usr/bin/awk -f), czasami jest to po prostu przydatne ( #! /usr/bin/perl -Tw). Niestety nie możesz umieścić dwóch lub więcej argumentów po ścieżce bezwzględnej.
Niektórzy ludzie powiedzą ci, żebyś używał #! /usr/bin/env interpreterzamiast #! /absolute/path/to/interpreter. To prawie zawsze błąd. Sprawia, że zachowanie programu zależy od $PATHzmiennej użytkownika, który wywołuje skrypt. I nie wszystkie systemy są envna pierwszym miejscu.
Programy, które potrzebują setuidlub setgidprzywilejów, nie mogą ich używać #!; muszą być skompilowane do kodu maszynowego. (Jeśli nie wiesz, co to setuidjest, nie martw się tym).
Odnośnie csh, odnosi się to shmniej więcej do tego, co Nutrimat Advanced Tea Substitute ma do herbaty. Ma (a raczej miał; współczesne implementacje shdogoniły) szereg zalet w porównaniu shz interaktywnym użyciem, ale używanie go (lub jego następcy tcsh) do tworzenia skryptów jest prawie zawsze błędem . Jeśli nie znasz ogólnie skryptów powłoki, zdecydowanie zalecam zignorowanie tego i skupienie się na sh. Jeśli używasz cshkrewnego jako powłoki logowania, przełącz na bashlub zsh, aby interaktywny język poleceń był taki sam, jak język skryptowy, którego się uczysz.
Najnowsze wersje Linuksa pozwalają, aby określony interpreter był skryptem. Powszechną praktyką jest pomijanie spacji po #!; bez komentarza, czy to dobry styl. Zobacz to pytanie i moją odpowiedź, aby omówić zalety i wady #!/usr/bin/envwłamania.
Keith Thompson
@KeithThompson Mam wrażenie, że Linux jest jedynym powszechnym wariantem Uniksa, który pozwala interpreterowi być skryptem, więc nadal nie można na nim polegać. Odkąd to napisałem, sam spotkałem się z sytuacją, w której #!/usr/bin/envbyła Właściwa Rzecz, ale pozostaje moim zdaniem, że prawie zawsze jest to zły pomysł.
zwol
4
Określa, jakiej powłoki (interpretera poleceń) używasz do interpretowania / uruchamiania skryptu. Każda powłoka różni się nieco sposobem interakcji z użytkownikiem i wykonywania skryptów (programów).
Kiedy wpisujesz polecenie w linii poleceń systemu Unix, wchodzisz w interakcję z powłoką.
Np. #!/bin/cshOdnosi się do powłoki C, powłoki /bin/tcsht, powłoki /bin/bashbash itp.
Możesz powiedzieć, której powłoki interaktywnej używasz
echo$SHELL
polecenie lub alternatywnie
env | grep -i shell
Możesz zmienić powłokę poleceń za pomocą chshpolecenia.
Każdy ma nieco inny zestaw poleceń i sposób przypisywania zmiennych oraz własny zestaw konstrukcji programistycznych. Na przykład instrukcja if-else z bash wygląda inaczej niż ta w powłoce C.
Ta strona może być interesująca, ponieważ "tłumaczy" pomiędzy poleceniami / składnią bash i tcsh.
Użycie dyrektywy w skrypcie powłoki umożliwia uruchamianie programów przy użyciu innej powłoki. Na przykład używam tcshpowłoki interaktywnie, ale często uruchamiam skrypty bash za pomocą / bin / bash w pliku skryptu.
Na bok:
Ta koncepcja rozciąga się również na inne skrypty. Na przykład, jeśli programujesz w Pythonie, umieścisz
Czy jest to wymagane? Skąd mam wiedzieć, której powłoki naprawdę używam?
One Two Three
Więc jeśli piszę skrypty dla kogoś do użycia na ich komputerze i nie wiem, jakiej powłoki używają. (Ta osoba niestety nie ma pojęcia o tych rzeczach, więc jedyne, co może zrobić, to uruchomić skrypt bez zmiany rzeczy). Czy mogę zrobić coś takiego #! $SHELL? Czy to umieściłoby właściwą muszlę w Shebangu?
One Two Three
1
@OneTwoThree Większość systemów ma standardowe powłoki, jeśli napiszesz skrypt bash lub csh, wszystko będzie dobrze. Nie ma znaczenia, jakiej powłoki używają interaktywnie , to jest piękno np !#/bin/bash. Dyrektywy. Informuje system, jakiej powłoki należy użyć do wykonania skryptu powłoki.
Levon
Wartość $SHELLniekoniecznie mówi ci, z której powłoki aktualnie korzystasz; zwykle mówi ci o twojej domyślnej powłoce. zestawy tcsh $versioni $tcsh; zestawy bash $BASH_VERSION. Nie wszystkie muszle muszą mieć podobne mechanizmy.
Keith Thompson
1
@OneTwoThree: #!Linia musi pasować do składni skryptu, a nie do powłoki interaktywnej używanej przez każdego, kto uruchamia skrypt.
#!/bin/csh -f
;-f
mówi powłoce nie pozyskać użytkownika.login
i.cshrc
, co sprawia, że szybciej uruchomić skrypt i unika zależności od ustawień użytkownika. (Lub jeszcze lepiej, nie pisz skryptów csh.) Nie używaj-f
do skryptów sh lub bash; nie ma tego samego znaczenia.Odpowiedzi:
Jest to znane jako
Shebang
:http://en.wikipedia.org/wiki/Shebang_(Unix)
Shebang ma znaczenie tylko wtedy, gdy skrypt ma pozwolenie na wykonanie (np. Chmod u + x script.sh).
Kiedy powłoka wykonuje skrypt, użyje określonego interpretera.
Przykład:
#!/bin/bash # file: foo.sh echo 1 $ chmod u+x foo.sh $ ./foo.sh 1
źródło
#!
Linia informuje jądro (w szczególności realizacjiexecve
wywołania systemowego), że ten program jest napisany w języku interpretowanym; bezwzględna nazwa ścieżki, która następuje, identyfikuje interpretera. Programy skompilowane do kodu maszynowego zaczynają się od innej sekwencji bajtów - w większości nowoczesnych Uniksów,7f 45 4c 46
( ^?ELF), która je identyfikuje.Możesz umieścić bezwzględną ścieżkę do dowolnego programu po tagu
#!
, o ile sam ten program nie jest#!
skryptem. Jądro przepisuje wywołaniegdzie
./script
zaczyna się, powiedzmy,#! /usr/bin/perl
tak, jakby wiersz poleceń faktycznie istniałLub, jak widziałeś, możesz użyć
#! /bin/sh
do napisania skryptu, który ma być interpretowany przezsh
.#!
Linii są przetwarzane tylko wtedy, gdy bezpośrednio wywołać skrypt (./script
w linii poleceń); plik musi być również wykonywalny (chmod +x script
). Jeśli nie linia nie jest konieczne (i będą ignorowane, jeśli jest obecny), a plik nie musi być wykonywalny. Punkt z tej funkcji jest umożliwienie Ci bezpośrednio invoke programów interpretowany języków bez konieczności znać język, jakim są napisane. (Do - będzie można odkryć, że bardzo wiele programów akcji są w rzeczywistości przy użyciu tej funkcji.)sh ./script
#!
grep '^#!' /usr/bin/*
Oto kilka zasad korzystania z tej funkcji:
#!
Muszą być dwie bardzo pierwsze bajty w pliku. W szczególności plik musi być kodowany zgodnie z ASCII (np. UTF-8 będzie działać, ale UTF-16 nie) i nie może zaczynać się od „znaku kolejności bajtów”, w przeciwnym razie jądro nie rozpozna go jako#!
scenariusz.#!
musi być ścieżką bezwzględną (zaczyna się od/
). Nie może zawierać znaków spacji, tabulacji ani nowej linii.#!
i/
. Nie umieszczaj tam więcej niż jednej spacji.#!
linii, nie zostaną one rozwinięte.#! /usr/bin/awk -f
), czasami jest to po prostu przydatne (#! /usr/bin/perl -Tw
). Niestety nie możesz umieścić dwóch lub więcej argumentów po ścieżce bezwzględnej.#! /usr/bin/env interpreter
zamiast#! /absolute/path/to/interpreter
. To prawie zawsze błąd. Sprawia, że zachowanie programu zależy od$PATH
zmiennej użytkownika, który wywołuje skrypt. I nie wszystkie systemy sąenv
na pierwszym miejscu.setuid
lubsetgid
przywilejów, nie mogą ich używać#!
; muszą być skompilowane do kodu maszynowego. (Jeśli nie wiesz, co tosetuid
jest, nie martw się tym).Odnośnie
csh
, odnosi się tosh
mniej więcej do tego, co Nutrimat Advanced Tea Substitute ma do herbaty. Ma (a raczej miał; współczesne implementacjesh
dogoniły) szereg zalet w porównaniush
z interaktywnym użyciem, ale używanie go (lub jego następcytcsh
) do tworzenia skryptów jest prawie zawsze błędem . Jeśli nie znasz ogólnie skryptów powłoki, zdecydowanie zalecam zignorowanie tego i skupienie się nash
. Jeśli używaszcsh
krewnego jako powłoki logowania, przełącz nabash
lubzsh
, aby interaktywny język poleceń był taki sam, jak język skryptowy, którego się uczysz.źródło
#!
; bez komentarza, czy to dobry styl. Zobacz to pytanie i moją odpowiedź, aby omówić zalety i wady#!/usr/bin/env
włamania.#!/usr/bin/env
była Właściwa Rzecz, ale pozostaje moim zdaniem, że prawie zawsze jest to zły pomysł.Określa, jakiej powłoki (interpretera poleceń) używasz do interpretowania / uruchamiania skryptu. Każda powłoka różni się nieco sposobem interakcji z użytkownikiem i wykonywania skryptów (programów).
Kiedy wpisujesz polecenie w linii poleceń systemu Unix, wchodzisz w interakcję z powłoką.
Np.
#!/bin/csh
Odnosi się do powłoki C, powłoki/bin/tcsh
t, powłoki/bin/bash
bash itp.Możesz powiedzieć, której powłoki interaktywnej używasz
echo $SHELL
polecenie lub alternatywnie
Możesz zmienić powłokę poleceń za pomocą
chsh
polecenia.Każdy ma nieco inny zestaw poleceń i sposób przypisywania zmiennych oraz własny zestaw konstrukcji programistycznych. Na przykład instrukcja if-else z bash wygląda inaczej niż ta w powłoce C.
Ta strona może być interesująca, ponieważ "tłumaczy" pomiędzy poleceniami / składnią bash i tcsh.
Użycie dyrektywy w skrypcie powłoki umożliwia uruchamianie programów przy użyciu innej powłoki. Na przykład używam
tcsh
powłoki interaktywnie, ale często uruchamiam skrypty bash za pomocą / bin / bash w pliku skryptu.Na bok:
Ta koncepcja rozciąga się również na inne skrypty. Na przykład, jeśli programujesz w Pythonie, umieścisz
#!/usr/bin/python
u góry programu w Pythonie
źródło
#! $SHELL
? Czy to umieściłoby właściwą muszlę w Shebangu?!#/bin/bash
. Dyrektywy. Informuje system, jakiej powłoki należy użyć do wykonania skryptu powłoki.$SHELL
niekoniecznie mówi ci, z której powłoki aktualnie korzystasz; zwykle mówi ci o twojej domyślnej powłoce. zestawy tcsh$version
i$tcsh
; zestawy bash$BASH_VERSION
. Nie wszystkie muszle muszą mieć podobne mechanizmy.#!
Linia musi pasować do składni skryptu, a nie do powłoki interaktywnej używanej przez każdego, kto uruchamia skrypt.