Dlaczego wszystkie pliki skryptów zaczynają się od
#!/bin/sh
lub z
#!/bin/csh
Czy to jest wymagane? Jaki jest tego cel? Jaka jest różnica między nimi?
Dlaczego wszystkie pliki skryptów zaczynają się od
#!/bin/sh
lub z
#!/bin/csh
Czy to jest wymagane? Jaki jest tego cel? Jaka jest różnica między nimi?
Odpowiedzi:
Jest to znane jako Shebang
:
http://en.wikipedia.org/wiki/Shebang_(Unix)
#! interpreter [opcjonalny-arg]
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
#!
Linia informuje jądro (w szczególności realizacji execve
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łanie
./script arg1 arg2 arg3 ...
gdzie ./script
zaczyna się, powiedzmy, #! /usr/bin/perl
tak, jakby wiersz poleceń faktycznie istniał
/usr/bin/perl ./script arg1 arg2 arg3
Lub, jak widziałeś, możesz użyć #! /bin/sh
do napisania skryptu, który ma być interpretowany przez sh
.
#!
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
lub setgid
przywilejów, nie mogą ich używać #!
; muszą być skompilowane do kodu maszynowego. (Jeśli nie wiesz, co to setuid
jest, nie martw się tym).Odnośnie csh
, odnosi się to sh
mniej więcej do tego, co Nutrimat Advanced Tea Substitute ma do herbaty. Ma (a raczej miał; współczesne implementacje sh
dogoniły) szereg zalet w porównaniu sh
z 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 csh
krewnego jako powłoki logowania, przełącz na bash
lub zsh
, aby interaktywny język poleceń był taki sam, jak język skryptowy, którego się uczysz.
#!
; 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
env | grep -i shell
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
#! $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.
#!/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.