Dlaczego muszę umieścić sh przed uruchomieniem plików .sh?

16

Kiedy chcę uruchamiać .shpliki w Terminalu, muszę je umieścić shprzed nimi.

Czy jest jakiś sposób, aby tego uniknąć, a tym samym zaoszczędzić pisania?

Więcej niż pięć
źródło
3
Zrobiłem folder w ~ / bin, w którym mogę umieścić moje skrypty powłoki i umieściłem go na mojej $ PATH, a także podłączyłem akcję folderu do folderu ~ / bin, aby automatycznie ustawić uprawnienia do wykonywania, ponieważ tak łatwo o tym zapomnieć.
Kaydell,

Odpowiedzi:

22

Jeśli uruchamiasz swój skrypt z powłoki, tak naprawdę nie potrzebujesz #!/bin/shshebang, jak opisano w tej odpowiedzi - każdy system uniksopodobny, którego używałem, w tym OS X, ustawi się domyślnie, /bin/shjeśli nie zostanie określony konkretny interpreter ( ale to dobry pomysł, ponieważ inne niż powłoki nie będą wiedziały, jak wykonać skrypt, chyba że podasz shebang.)

Nie potrzebujesz również .shrozszerzenia. Ci zrobić konieczność ustalenia uprawnień wykonywalnych, np

$ chmod +x script.sh

(Jest $to znak zachęty powłoki; używam go do zilustrowania poleceń wydawanych interaktywnej powłoce. Nie wpisuj jej!)

Myślę jednak, że masz problem z tym, że utworzyłeś skrypt, np. script.shW bieżącym katalogu, i próbujesz go wykonać, po prostu pisząc script.sh. na przykład

$ cat >script.sh
echo hello, world
^D
$ chmod +x script.sh
$ script.sh
-bash: script.sh: command not found

( ^Doznacza control- D. Ten zapis znajdziesz w wielu artykułach o używaniu Uniksa).

Fakt, że script.shw tym przypadku jest to skrypt powłoki, to tylko połowa problemu; Twoim problemem jest to, że domyślnie powłoka nie przeszuka programu w bieżącym katalogu. Działa to jednak:

$ sh script.sh
hello, world

ponieważ shbierze skrypt za argument.

Możesz wykonać skrypt - lub ponownie dowolny plik wykonywalny - w bieżącym katalogu, jeśli jest oznaczony jako plik wykonywalny (tj. chmod +x), Określając, że chcesz uruchomić ten w bieżącym katalogu:

$ ./script.sh
hello, world

Możesz także przenieść skrypt do katalogu na swoim PATH. Polecam /usr/local/binto, jeśli skrypt ma być używany w całym systemie lub binkatalog w domu, jeśli skrypt jest tylko dla Ciebie. Ten ostatni wymaga dodania $HOME/bin, które rozwija się do nowego katalogu bin, do twojego PATHpoprzez dodanie następujących linii do twojego .profilew katalogu domowym:

PATH=$HOME/bin:$PATH
export PATH

Na koniec możesz, jeśli chcesz, faktycznie dodać bieżący katalog do swojego PATH, co pozwoli ci po prostu przejść do katalogu zawierającego script.sh- lub dowolny inny plik wykonywalny - i wpisać

$ script.sh

wykonać to. Jednak nie zalecam tej praktyki , ponieważ osoba atakująca może teraz nakłonić cię do uruchomienia dowolnego pliku wykonywalnego, upuszczając skrypt wykonywalny (o nazwie, powiedzmy, ls) w katalogu, w którym się znajdziesz. Jeśli jednak naprawdę chcesz to zrobić, po prostu dodaj do swojego .profile:

PATH=.:$PATH
export PATH
zigg
źródło
Połóż '.' na końcu $ PATH zamiast na początku i teraz nie musisz się martwić o fantomowe „ls”. (Chociaż jeśli ktoś może dostać się do twojego systemu, masz większe problemy.)
TJ Luoma,
2
@TJ, ale nie trzeba się martwić o rzeczy, jak sli llsczy l... to znaczy, literówek. Wystarczy wyjechać .poza $PATH. Ponadto niekoniecznie (lub nie należy) ufać wszystkim w systemie. Na przykład, załóżmy, że istnieje jakiś exploit, który umożliwia atakującemu upuść dowolny plik do jakiegoś katalogu, ale muszą Państwo wykonać ten plik, aby eskalować do lepszego wykorzystania (np, zbierać dane i telefon domowy). Obrona w głębi!
Reid,
@TJLuoma Co powiedział @Reid, a ponadto należy pamiętać, że istnieje wiele przypadków użycia systemu Unix poza osobistym pulpitem OS X. Nie próbowałem tego, ale założę się, że nawet konto gościa może zostawić jeden z tych przedmiotów w /tmpinnym katalogu z możliwością zapisu na całym świecie.
zigg
Jeśli korzystasz z systemu, w którym inne osoby mają dostęp do używanych przez Ciebie katalogów, masz większe problemy.
TJ Luoma,
@TJLuoma Najlepiej nigdy nie używaj wielu kont w żadnym systemie uniksowym. /tmpi in. przyjechać z terytorium.
zigg
10

Nie musisz dzwonić, shjeśli plik skryptu jest oznaczony jako wykonywalny. W takim przypadku możesz nazwać to moim imieniem, tak jak każde inne polecenie z istniejącej powłoki.


Aby być w pełni poprawnym, będziesz chciał zrobić dwie rzeczy:

  1. Zmodyfikuj skrypt, tak aby zawierał dyrektywę shebang na górze skryptu:

    #!/bin/sh

    ... To powiedziałoby powłoce, którego interpretera użyć do uruchomienia skryptu; w tym przypadku /bin/shplik wykonywalny.

  2. Oznacz skrypt jako wykonywalny za pomocą komendy chmod :

    chmod u+x scriptname.sh

Po wykonaniu obu tych czynności możesz uruchomić skrypt, wpisując nazwę pliku skryptu w wierszu polecenia. Musisz znajdować się w tym samym katalogu co skrypt, chyba że wykonasz dodatkowy krok dodawania folderu zawierającego do zmiennej PATH . Jeśli nie obchodzi Cię, która powłoka uruchamia skrypt, nie musisz określać kroku pierwszego, shale często lepiej jest być precyzyjnym i ustawić „shebangsh”.

Chris W. Rea
źródło
Shebangs nie są w rzeczywistości potrzebne /bin/sh, chociaż nie ranią.
zigg
@zigg - masz rację. Mam nadzieję, że Chris nie będzie miał nic przeciwko moim edycjom… Nuke lub ponownie edytuj zgodnie z potrzebami: -0
bmike
@bike Edycje działają dla mnie. Jeśli chodzi o shebangi, moim nawykiem było zawsze sprecyzowanie, ponieważ kiedyś pisałem wiele kshskryptów na HP-UX - ale dobrze wiedzieć, że nie jest to absolutnie konieczne.
Chris W. Rea
1
Myślę, że muszę wycofać się z mojego wcześniejszego stwierdzenia o konieczności shebang (choć reszta mojej odpowiedzi wciąż jest ważna). Możesz uruchomić skrypt bez shebang z powłoki, ale jeśli użyjesz execsyscall, dostaniesz ENOEXEC(błąd formatu exec ). Przepraszam za to, @bmike, @ ChrisW.Rea. Zamierzam teraz edytować moją odpowiedź.
zigg