Jaka jest różnica między ./ i sh, aby uruchomić skrypt?

71

Napisałem prosty skrypt. Kiedy uruchamiam sh <myscriptname.sh>, mam prawidłowe wyjście, ale kiedy uruchamiam ./<myscriptname.sh>, pojawia się błąd.

Jaka jest różnica między tym, co robię, sha czym ./?

mr_eclair
źródło
15
Zamiast po prostu powiedzieć „dostaję błąd”, byłoby pomocne, gdybyś wkleił to, co powiedział błąd.
SpashHit

Odpowiedzi:

67

Po uruchomieniu dowolnego skryptu poprzez przekazanie nazwy pliku do programu interpretera skryptów, uruchamiasz program interpretera ze skryptem jako przekazanym argumentem. Na przykład wyglądałoby to na proces „sh” z argumentem „nazwa_pliku.sh”. shInterpreter jest otwarcie pliku.

Z drugiej strony, jeśli uruchomisz sam skrypt, system wywołuje określony program interpretera i podaje zawartość skryptu. W takim przypadku proces wygląda jak „nazwa_pliku.sh” bez argumentów.

Powinieneś upewnić się, że masz linię huku:

#!/bin/bash
# bash script here

Linia Bang jest pierwszą linią w skrypcie i zaczyna się od tych samych dwóch znaków #!, to jest to, co system czyta, gdy próbuje wykonać skrypt, a następnie system przekazuje skrypt do programu natychmiast po tym. Zauważ, że ten wiersz nie ma nic wspólnego z bash i działa równie dobrze dla Pythona i Perla, mimo że są to bardzo różne języki. Użyłbyś #!/usr/bin/pythonna przykład, a następnie podążał za nim kod python.

Po otrzymaniu skryptu upewnij się, że masz ustawione uprawnienia do wykonywania:

chmod a+x filename.sh

Następnie możesz uruchomić skrypt jako własny proces:

./filename.sh

Lub umieść plik w znanej lokalizacji z ładną nazwą programu, na przykład /usr/sbini uruchom z dowolnego miejsca:

sudo cp filename.sh /usr/sbin/program-name
program-name

Jest to naprawdę praktyczna zaleta korzystania z linii Bang z odpowiednimi uprawnieniami - chodzi o wdrożenie . Bardzo trudno jest zmusić użytkowników do uruchomienia skryptu, jeśli muszą pamiętać, z jakim programem uruchomić skrypt. Pamiętaj, aby podać pełną ścieżkę do skryptu za każdym razem, gdy chcą go uruchomić. Gdzie, /usr/local/binna przykład, umieszczenie go i wykonanie, może zaoszczędzić okropnego smutku osobom próbującym użyć twojego skryptu. Programy te stają się następnie dostępne dla wszystkich użytkowników na twoim komputerze.

Jest także dobry do identyfikacji. Jeśli pójdziesz do topprogramu, prowadzony przez skrypt bez linii huk po prostu mieć nazwę interpreter znaczy bash, perlalbo python. Ale jeśli skrypt jest uruchamiany z odpowiednimi uprawnieniami, wyświetla się nazwa skryptu.

Uwaga: Jeśli chcesz rozpowszechniać skrypt, który jest dostępny dla wszystkich, utwórz stronę podręcznika i pakiet deb, aby go zainstalować. Musimy zmniejszyć liczbę losowych skryptów online i zwiększyć liczbę debów, które można odinstalować.

Martin Owens -doctormo-
źródło
1
Możesz także użyć osobistego folderu bin: utwórz folder bin do swojego folderu domowego, wyloguj się i zaloguj ponownie, a następnie powinieneś być w stanie uruchomić wszystkie skrypty w tym folderze bez sh lub ./.
papukaija
Oczywiście, ale dodanie folderu domowego do ŚCIEŻKI może być nieco uciążliwe. Lepiej zainstaluj rzeczy. Chociaż mówiło się o dodaniu ~ / .local / bin do ścieżki domyślnie, aby umożliwić lokalnym użytkownikom instalowanie pakietów.
Martin Owens -doctormo-
Zauważ, że domyślnym tłumaczem bashnie jest sh.
Nathan Osman
1
Nie umieszczaj rozszerzeń w skryptach, zwłaszcza gdy je wstawiasz PATH.
geirha
1
/usr/local/binjest prawdopodobnie lepszy /usr/sbin- wskazuje, że program jest lokalny dla tej maszyny, a nie częścią dystrybucji.
glenn jackman
41

Krótka wersja:

  • shto interpreter wiersza poleceń (myślnik).
    Uruchomienie sh my_scriptpowoduje, że dash interpretuje skrypt.

  • ./próbuje dowiedzieć się, którego interpretatora użyć, patrząc na pierwszą linię. Np. #!/bin/bashLub nawet #!/bin/ruby(w przeciwieństwie do biegania ruby my_script).

Stefano Palazzo
źródło
7
Tak naprawdę to ./nic nie znajduje, to metoda wykonania systemu, która sprawdza pierwsze dwa bajty pliku.
Martin Owens -doctormo-
9
Absolutnie. Oto bardzo długie wyjaśnienie tego wszystkiego. Jestem pragmatyczny :)
Stefano Palazzo
Kiedy używasz, sha plik zawiera sha-bang, czy to oznacza, że ​​sha-bang zostanie zignorowany, czy też otworzy powłokę, w której shrównież linki, a może może inną powłokę lub co ona robi :)?
Ini
5

Różnica, którą robisz, to

  • z sh, używasz programu, który zinterpretuje wiersze w skrypcie tak jak byś wpisywane je na interaktywnej wierszu terminalu,

  • ze ./robisz skrót przy założeniu, że skrypt jest właśnie tu, w bieżącym katalogu ty siedzisz w I będzie to plik wykonywalny (bo na przykład jesteś wydane chmod +x myscript.sh), co pozwala zaoszczędzić bezcenny czas dla przyszłych czasów :-)

meduz
źródło
3
+1 za to, że jako jedyny zwięźle stwierdza, że ​​plik musi być wykonywalny.
Mikel
2
Zauważ, że shplik nie musi koniecznie być wykonywalny.
Ini
3

Istnieją trzy główne powody, dla których możesz otrzymać błąd:

  • plik nie jest wykonywalny
    run chmod +x <myscriptname.sh>to naprawić
  • partycja nie pozwala działającym skryptom (jest zamontowany „ noexec”)
    kopiować skrypt do/usr/local/bin
  • w #!wierszu wystąpił błąd,
    upewnij się, że pierwszy wiersz to #!/bin/shlub#!/bin/bash

Jeśli pierwsza linia wygląda poprawnie, ale nadal nie działa, upewnij się, że plik nie ma zakończeń linii DOS.

Błąd wyglądałby mniej więcej tak:

$ ./myscript.sh
bash: ./myscript.sh: /bin/bash^M: bad interpreter: No such file or directory

Można to naprawić poprzez uruchomienie dos2unix <myscriptname.sh>, lub jeśli nie masz, że
perl -p -i -e 's/\r\n$/\n/' <myscriptname.sh>.

Mikel
źródło
0

Odpowiedź brzmi: sh to nazwa bardzo popularnej powłoki. Ale przestarzałe i zastąpione innymi. Obecnie sh jest powiązany z innymi powłokami zainstalowanymi na komputerze. np. mam tam bash. Uruchamianie dowolnej powłoki z sh zwykle wyzwala tryb „kompatybilności” z oryginalnym zachowaniem „powłoki”.

Więc rozwiązanie jest dość proste. Spójrz, co kryje się za poleceniem sh (ls -al / bin / sh), i umieść #! / Bin / cokolwiek_funkcja w pierwszym wierszu (lub jeśli w skrypcie jest coś takiego edytuj).

Alternatywnie może występować pewien błąd w samym skrypcie. Podobnie jak zależność spełniana przez sh, ale nie faktycznie używany interpreter.

przemo_li
źródło
0
mkdir ~/bin ; cp myscript.sh ~/bin/

echo "export PATH="$PATH:/home/$USER/bin" >> ~/.profile ; source ~/.profile ; 

Nie /usr/sbin, to w przypadku nieistotnych narzędzi administracyjnych, /usr/local/binjest lepszym wyborem, jeśli nie chcesz ~/bin/, ale sudowskazane jest unikanie jak największej ilości.

Joey1978
źródło
W systemie Ubuntu domyślny ~/.profilema już kod do dodawania ~/bin, jeśli istnieje, do PATH. Z drugiej strony, nie umieszczaj rozszerzeń w skryptach.
geirha
1
Odwoływałem się do <myscriptname.sh>, ale jakie jest uzasadnienie nie umieszczania rozszerzeń w skryptach? Zwykle tak robię, ponieważ wyświetlanie takich zwykłych plików tekstowych powstrzymuje mnie przed próbą edycji plików binarnych, które również przechowuję w ~ / bin /. ( ls ~/bin/|wc -l = 428)
Włożyłem
Wyobraź sobie, że piszesz skrypt, aby osiągnąć określone zadanie. Wtedy zdajesz sobie sprawę, że napisanie tego konkretnego skryptu w Pythonie sprawi, że będzie on znacznie wydajniejszy, więc przepisujesz go w Pythonie. Teraz masz dwie możliwości. 1) Pozostaw teraz bardzo mylące rozszerzenie .sh lub 2) zmień nazwę skryptu i wyszukaj i zamień wszystkie zastosowania skryptu, aby użyć nowej nazwy. Jeśli spojrzysz na skrypty /bini /usr/binzobaczysz, że nie używają one rozszerzeń.
geirha