Jeśli skrypt.sh jest po prostu czymś typowym
#!/bin/bash
echo "Hello World!"
Czy istnieje preferowany sposób uruchomienia skryptu? Myślę, że najpierw musisz go chmod, aby stał się wykonywalny?
Jeśli skrypt.sh jest po prostu czymś typowym
#!/bin/bash
echo "Hello World!"
Czy istnieje preferowany sposób uruchomienia skryptu? Myślę, że najpierw musisz go chmod, aby stał się wykonywalny?
Odpowiedzi:
W przypadku konkretnego skryptu w obu przypadkach będzie działać, z wyjątkiem tego, że ./script.sh
wymaga wykonania i czytelnych bitów, a bash script.sh
jedynie wymaga bitu czytelnego.
Przyczyna różnicy wymagań dotyczących uprawnień leży w sposobie ładowania programu, który interpretuje skrypt:
./script.sh
sprawia, że powłoka uruchamia plik tak, jakby był zwykłym plikiem wykonywalnym.Powłoka sama się rozwidla i używa wywołania systemowego (np. execve
), Aby system operacyjny wykonał plik w rozwidlonym procesie. System operacyjny sprawdzi uprawnienia do pliku (stąd należy ustawić bit wykonawczy) i prześle żądanie do programu ładującego , który spojrzy na plik i określi sposób jego wykonania. W Linuksie skompilowane pliki wykonywalne zaczynają się od magicznej liczby ELF , podczas gdy skrypty zaczynają się od #!
( hashbang ). Nagłówek hashbang oznacza, że plik jest skryptem i musi zostać zinterpretowany przez program określony po haszu. To pozwala samemu skryptowi powiedzieć systemowi, jak interpretować skrypt.
Za pomocą skryptu moduł ładujący program uruchomi się /bin/bash
i przekaże ./script.sh
jako argument wiersza polecenia.
bash script.sh
sprawia, że twoja powłoka działa bash
i przekazuje script.sh
jako argument wiersza poleceńSystem operacyjny się załaduje bash
(nawet nie patrząc script.sh
, ponieważ jest to tylko argument wiersza poleceń). Utworzony bash
proces zinterpretuje następnie, script.sh
ponieważ został przekazany jako argument wiersza polecenia. Ponieważ script.sh
jest odczytywany tylko bash
jako zwykły plik, bit wykonania nie jest wymagany.
Zalecam ./script.sh
jednak użycie , ponieważ możesz nie wiedzieć, jakiego interpretera wymaga skrypt. Pozwól więc programowi ładującemu ustalić to dla Ciebie.
. ./script.sh
to nie to samo, co bash script.sh
(lub ./script.sh
. Rozważmy skrypt #!/usr/bin/python -V
<nowa linia> print test
.
. script.sh
. Ale zgadzam się z ludźmi, którzy zniechęcają do używania .
polecenia w skryptach, które nie miały być wywoływane w ten sposób. Dziwię się, że nikt o tym nie wspominał, jeśli skrypt zawiera exit
polecenia, a Ty je pozyskasz, może Cię wylogować. Mniej poważnym problemem byłoby, gdyby skrypt działał cd
, ponieważ wpłynęłoby to również na powłokę nadrzędną (interaktywną).
bash script.sh
wywołuje skrypt bezpośrednio za pomocą bash.
./script.sh
używa shebang, #!/bin/bash
aby określić sposób wykonania.
Jeśli naprawdę chcesz wiedzieć, który plik binarny jest wykonywany, możesz zrobić to bash script.sh
z which bash
.
W twoim przykładzie nie ma to znaczenia. Tak, musisz chmod +x script.sh
być w stanie wykonać go bezpośrednio przez ./script.sh
.
/bin/bash
jest to pierwszy bash
w twoim $PATH
.
#!/bin/bash
działa tylko, jeśli jest/bin/bash
./script.sh
.
Utwórz plik Delete_Self.sh w następujący sposób:
#!/bin/rm
echo I am still here!
Uruchom ten skrypt, a sh Delete_Self.sh
zobaczysz „Nadal tu jestem!” odbiło się echem.
Spraw, by był wykonywalny i uruchom go, ponieważ ./Delete_Self.sh
zobaczysz, że nic nie jest odbijane ponownie, gdy Delete_Self.sh
sam plik zniknie.
Różnica polega na tym, że:
bash script.sh
zignoruje #! wiersz, ponieważ jako program do uruchamiania script.sh określono bash../script.sh
przeczyta #! wiersz, aby określić program do uruchomienia script.sh
.Oprócz innych odpowiedzi przydatna jest znajomość różnicy między uruchomieniem skryptu za pomocą ./script.sh
(i) i źródła ./script.sh
(ii) - Wersja (i) tworzy nową powłokę, w której można uruchomić polecenie, podczas gdy (ii) uruchamia go w bieżąca powłoka - która może być obowiązkowa, jeśli plik wykonywalny zmienia zmienne środowiskowe, które należy zachować po wyjściu z pliku wykonywalnego. Na przykład, aby aktywować środowisko conda Pythona, należy zastosować:
source activate my_env
Uwaga: Inną alternatywą source
, którą możesz napotkać, jest .
wbudowane, tj
. activate my_env