Jak uruchomić skrypt powłoki na konsoli Unix lub terminalu Mac?

506

Wiem o tym, zapomnij o tym i naucz się ponownie. Czas to zapisać.

ROCZNIE
źródło
15
pisanie pozytywnego pociągu aż do stacji reputacji
DivideByZer0
nie będę głosować tylko po to, by podziwiać ten niesamowity błąd, który tam masz!
BRHSM

Odpowiedzi:

941

Aby uruchomić niewykonywalny shskrypt, użyj:

sh myscript

Aby uruchomić niewykonywalny bashskrypt, użyj:

bash myscript

Aby uruchomić plik wykonywalny (dowolny plik z uprawnieniami do pliku wykonywalnego); po prostu określ go według ścieżki:

/foo/bar
/bin/bar
./bar

Aby skrypt był wykonywalny, daj mu niezbędne uprawnienia:

chmod +x bar
./bar

Gdy plik jest wykonywalny, jądro jest odpowiedzialne za wymyślenie, jak go wywołać. W przypadku plików innych niż pliki binarne można to zrobić, patrząc na pierwszą linię pliku. Powinien zawierać hashbang:

#! /usr/bin/env bash

Hashbang informuje jądro, który program ma zostać uruchomiony (w tym przypadku polecenie /usr/bin/envjest uruchamiane z argumentem bash). Następnie skrypt jest przekazywany do programu (jako drugi argument) wraz ze wszystkimi argumentami podanymi w skrypcie jako kolejne argumenty.

Oznacza to, że każdy skrypt, który można wykonać, powinien mieć hashbang . Jeśli nie, to nie mówisz jądru, co to jest , dlatego jądro nie wie, jakiego programu użyć do jego interpretacji. To może być bash, perl, python, sh, lub coś innego. (W rzeczywistości jądro często używa domyślnej powłoki użytkownika do interpretacji pliku, co jest bardzo niebezpieczne, ponieważ może nie być wcale właściwym interpreterem lub może być w stanie parsować niektóre z nich, ale z subtelnymi różnicami behawioralnymi, takimi jak przypadek między shi bash).

Uwaga na temat /usr/bin/env

Najczęściej zobaczysz takie hash bang:

#!/bin/bash

W rezultacie jądro uruchomi program w /bin/bashcelu interpretacji skryptu. Niestety bashnie zawsze jest domyślnie wysyłany i nie zawsze jest dostępny w /bin. Podczas gdy na maszynach z Linuksem zwykle tak jest, istnieje wiele innych maszyn POSIX, które są bashwysyłane w różnych lokalizacjach, takich jak /usr/xpg/bin/bashlub /usr/local/bin/bash.

Aby napisać przenośny skrypt bash, nie możemy zatem polegać na twardym kodowaniu lokalizacji bashprogramu. POSIX ma już mechanizm radzenia sobie z tym: PATH. Chodzi o to, że instalujesz programy w jednym z katalogów, które się znajdują, PATHa system powinien być w stanie znaleźć Twój program, gdy chcesz go uruchomić według nazwy.

Niestety nie można tego po prostu zrobić:

#!bash

Jądro nie będzie (niektórzy mogą) PATHszukać ciebie. Istnieje jednak program, który może przeprowadzić PATHwyszukiwanie, nazywa się env. Na szczęście prawie wszystkie systemy mają envzainstalowany program /usr/bin. Dlatego zaczynamy envużywać zakodowanej ścieżki, która następnie PATHwyszukuje bashi uruchamia ją, aby mogła zinterpretować twój skrypt:

#!/usr/bin/env bash

To podejście ma jedną wadę: Według POSIX, hashbang może mieć jeden argument . W tym przypadku używamy bashjako argumentu envprogramu. Oznacza to, że nie mamy już miejsca na przekazywanie argumentów bash. Więc nie ma sposobu, aby przekonwertować coś takiego #!/bin/bash -exuna ten schemat. Zamiast tego będziesz musiał położyć set -exuhashbang.

Podejście to ma również inną zaletę: niektóre systemy mogą być dostarczane z /bin/bash, ale użytkownikowi może się to nie podobać, może być wadliwe lub przestarzałe i może zainstalować własne bashgdzieś indziej. Dzieje się tak często w przypadku systemu OS X (Mac), w którym Apple dostarcza nieaktualne, /bin/basha użytkownicy instalują aktualne /usr/local/bin/bashwersje, używając czegoś takiego jak Homebrew. Kiedy korzystasz z envmetody PATHwyszukiwania, bierzesz pod uwagę preferencje użytkownika i używasz jego preferowanego basha w stosunku do tego, z którym został dostarczony system.

lhunath
źródło
66
Dziękujemy za poświęcenie czasu na napisanie dobrej odpowiedzi na proste pytanie.
PA
5
Jeśli użyję zshjako mojej powłoki, czy użyłbym hashbang #! /usr/bin/env zsh?
stefmikhail
6
@stefmikhail: Nie ma znaczenia, którego interpretera powłoki używasz do wywoływania skryptu, powinieneś użyć, #! /usr/bin/env zshjeśli (i tylko jeśli) kod w skrypcie powinien zostać wykonany przez powłokę Z.
Johnsyweb
1
+1 za wyjaśnienie. zapominam, ale znajomość znaczenia polecenia pomoże mi przypomnieć sobie.
Angelin Nadar
2
@Carpetsmoker To jest poprawne i nie ogranicza się tylko do hashbangu. Skrypty bash powinny zawsze używać zakończeń linii UNIX, w przeciwnym razie do ostatniego argumentu każdego polecenia zostanie dołączony znak \ r, podobnie jak nazwa polecenia hashbang.
lhunath,
80

Aby uruchomić skrypt-file „file.sh”:

sh file.sh

bash file.sh

Inną opcją jest ustawienie uprawnień do wykonywania za pomocą komendy chmod:

chmod +x file.sh

Teraz uruchom plik .sh w następujący sposób:

./file.sh
ROCZNIE
źródło
15

W przypadku powłoki Bourne'a:

sh myscript.sh

Do bash:

bash myscript.sh

źródło
Dziękujemy za odpowiedź na to dość oczywiste pytanie. Dla takiego faceta na Maca jak ja łatwo zapomnieć o starych komendach uniksowych między okrążeniami.
PA
10

Jeśli chcesz, aby skrypt działał w bieżącej powłoce (np. Chcesz, aby mógł wpływać na twój katalog lub środowisko), powinieneś powiedzieć:

. /path/to/script.sh

lub

source /path/to/script.sh

Uwaga: /path/to/script.shmoże być względna, na przykład . bin/script.shuruchamia script.shw binkatalogu w bieżącym katalogu.

Chas. Owens
źródło
7
Zachowaj szczególną ostrożność podczas pozyskiwania lub dot'owania za pomocą względnych nazw ścieżek. Powinieneś zawsze zaczynać je od ./ Jeśli tego nie zrobisz, a względna nazwa ścieżki nie zawiera żadnych ukośników, będziesz pozyskiwać coś w ŚCIEŻCE, PRZED czymś w bieżącym katalogu! Bardzo niebezpieczne z powodu nadużyć.
lhunath,
0

Najpierw zezwól na wykonanie: -
chmod +x script_name

  1. Jeśli skrypt nie jest wykonywalny: -
    Do uruchomienia pliku skryptu sh: -
    sh script_name
    Do uruchomienia pliku skryptu bash: -
    bash script_name
  2. Jeśli skrypt jest wykonywalny: -
    ./script_name

UWAGA : -można sprawdzić, czy plik jest wykonywalny, czy nie, używając „ls -a”

Vineet Jain
źródło
0

Rozszerzenie pliku .command jest przypisane do Terminal.app. Dwukrotne kliknięcie dowolnego pliku .command spowoduje jego wykonanie.

benwiggy
źródło
0

Mały dodatek, aby uruchomić interpreter z tego samego folderu, nadal używając #! Hashbang w skryptach.

Na przykład plik wykonywalny php7.2 skopiowany z / usr / bin znajduje się w folderze wzdłuż skryptu hello .

#!./php7.2
<?php

echo "Hello!"; 

Aby uruchomić:

./hello

Które zachowują się tak samo jak:

./php7.2 hello
NVRM
źródło