Jaka jest różnica między uruchomieniem “ bash script.sh ” i “ ./script .sh ”?

Jeśli script.sh jest czymś typowym, takim jak

#!/bin/bash echo "Hello World!" 

Czy jest preferowana sposób na uruchomienie skryptu? Myślę, że najpierw musisz go chmodować, aby stał się wykonywalny?

Odpowiedź

Dla twojego konkretnego skryptu każdy sposób zadziała, z wyjątkiem że ./script.sh wymaga wykonania i czytelnych bitów, podczas gdy bash script.sh wymaga tylko czytelnego bitu.


Powód różnica w wymaganiach dotyczących uprawnień polega na tym, jak ładowany jest program, który interpretuje twój skrypt:

  • ./script.sh sprawia, że twoja powłoka uruchamia plik tak, jakby był zwykłym wykonywalny.

Powłoka forkuje się i używa wywołania systemowego (np. execve), aby zmusić system operacyjny do wykonania pliku w procesie rozwidlonym. System operacyjny sprawdzi uprawnienia do pliku (dlatego bit wykonania musi zostać ustawiony) i przekaże żądanie do programu ładującego , który sprawdza plik i określa, jak go wykonać. W Linuksie skompilowane pliki wykonywalne zaczynają się od magicznej liczby ELF , a skrypty zaczynają się od #! ( hashbang ). Nagłówek hashbang oznacza, że plik jest skryptem i musi być zinterpretowany przez program określony po hashbangu. Umożliwia to skryptowi aby poinformować system, jak interpretować skrypt.

Wraz z Twoim skryptem program ładujący wykona /bin/bash i przekaże ./script.sh jako argument wiersza poleceń.

  • bash script.sh sprawia, że powłoka działa bash i przechodzi script.sh jako argument wiersza poleceń

W ten sposób system operacyjny załaduje (nawet nie patrząc na script.sh, ponieważ jest to tylko argument wiersza poleceń). Utworzony proces bash zinterpretuje następnie script.sh, ponieważ został on przekazany jako argument wiersza polecenia. Ponieważ script.sh jest odczytywane tylko przez bash jako zwykły plik, bit wykonania nie jest wymagany.


Polecam używanie ./script.sh, ponieważ możesz nie wiedzieć, którego interpretera wymaga skrypt. Pozwól więc programowi ładującemu określić to za Ciebie.

Komentarze

  • Jeśli bit wykonywalny nie jest ustawiony, możesz również uruchomić skrypt, wykonując ". ./script.sh"
  • @Dog Masz rację. Kropka to skrót do wbudowanego polecenia ' source ' , który uruchamia skrypt w bieżącym procesie bash. Dlatego wymagany jest tylko czytelny bit.
  • @Dogeatcatworld to prawda, ale uruchomienie . ./script.sh to nie to samo rzecz jako (lub ./script.sh. Rozważ skrypt #!/usr/bin/python -V < newline > print test.
  • Uważaj, że pozyskiwanie skryptu może spowodować zanieczyszczenie sesji interaktywnej. Na przykład, jeśli skrypt zmieni zmienną środowiskową PATH, ta zmiana wpłynie na polecenia uruchamiane po źródle. To podejście powinno być naprawdę zarezerwowane dla sytuacji, w których polegasz na efektach ubocznych (skrypty konfiguracji środowiska i tym podobne). W innych sytuacjach, w których możesz ' t zmienić uprawnienia, najbezpieczniejszym podejściem jest uruchomienie polecenia w wierszu shebang, po którym następuje nazwa skryptu.
  • Zwróć uwagę, że , jeśli pozyskujesz skrypt w bieżącym katalogu, nie musisz używać ./ ; po prostu powiedz . script.sh. Ale zgadzam się z ludźmi, którzy odradzają używanie polecenia . w skryptach, które nie miały być wywoływane w ten sposób. Dziwię się, że nikt o tym nie wspomniał, jeśli skrypt zawiera polecenia exit, a Ty go pobierasz, może Cię wylogować. Mniej poważnym problemem byłoby wykonanie przez skrypt cd, ponieważ wpłynęłoby to również na powłokę nadrzędną (interaktywną).

Odpowiedz

bash script.sh wywołuje skrypt bezpośrednio przy użyciu basha.
./script.sh używa shebang #!/bin/bash do określenia sposobu wykonania.

Jeśli naprawdę chcesz wiedzieć, który plik binarny jest wykonywany, jeśli wykonasz bash script.sh możesz się tego dowiedzieć z which bash.

W twoim przykładzie nie ma to znaczenia. Tak, musisz chmod +x script.sh, aby móc go wykonać bezpośrednio przez ./script.sh.

Komentarze

  • Cóż, nie ma znaczenia, zakładając, że /bin/bash jest pierwszym bash w swoim $PATH.
  • Masz ' dobrze. Shebang #!/bin/bash działa tylko wtedy, gdy jest /bin/bash
  • Bash (wersja 4.2.37) na moim system wykonuje skrypty nawet bez ustawionego bitu wykonania. Dlaczego mówisz, że bit wykonania jest wymagany?
  • Tak, bit wykonania jest potrzebny tylko przy wywołaniu przez ./script.sh.

Odpowiedź

Utwórz plik Delete_Self.sh w ten sposób:

 #!/bin/rm echo I am still here! 

Uruchom to skrypt jako sh Delete_Self.sh, zobaczysz komunikat „Nadal tu jestem!” echo z powrotem.

Ustaw go jako wykonywalny i uruchom jako ./Delete_Self.sh zobaczysz, że nic nie jest powtórzone, a plik Delete_Self.sh zniknął.

Różnica jest taka, że:

  • bash script.sh zignoruje #! linia, ponieważ bash jest określony jako program do uruchamiania script.sh.
  • ./script.sh odczyta #! wiersz określający program do uruchomienia script.sh.

Komentarze

  • +1 dla ładny przykład

Odpowiedź

Oprócz innych odpowiedzi, znajomość różnicy między uruchomieniem skryptu przez ./script.sh (i) i źródło ./script.sh (ii) są przydatne – wersja (i) tworzy nową powłokę, w której można uruchomić polecenie, podczas gdy (ii) uruchamia go w bieżącej powłoce – co może być obowiązkowe, jeśli plik wykonywalny zmienia zmienne środowiskowe, które muszą zostać zachowane po zakończeniu działania pliku wykonywalnego. Na przykład, aby aktywować środowisko Python Conda, należy użyć następujących elementów:

source activate my_env 

Uwaga. Inną alternatywą dla source, którą możesz napotkać, jest wbudowane ., tj.

. activate my_env 

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *