Come eseguire uno script di shell su una console Unix o un terminale Mac?


507

Lo so, dimenticalo e riapprendilo di nuovo. È ora di scriverlo.


15
scrivendo il treno di
voto

non voterò solo per ammirare quel fantastico errore che ci sei arrivato!
BRHSM,

Risposte:


942

Per eseguire uno shscript non eseguibile , utilizzare:

sh myscript

Per eseguire uno bashscript non eseguibile , utilizzare:

bash myscript

Per avviare un eseguibile (che è qualsiasi file con permesso eseguibile); basta specificarlo con il suo percorso:

/foo/bar
/bin/bar
./bar

Per rendere eseguibile uno script, concedi l'autorizzazione necessaria:

chmod +x bar
./bar

Quando un file è eseguibile, il kernel è responsabile di capire come eseguirlo. Per i non binari, questo viene fatto osservando la prima riga del file. Dovrebbe contenere un hashbang:

#! /usr/bin/env bash

L'hashbang dice al kernel quale programma eseguire (in questo caso il comando /usr/bin/envviene eseguito con l'argomento bash). Quindi, lo script viene passato al programma (come secondo argomento) insieme a tutti gli argomenti forniti dallo script come argomenti successivi.

Ciò significa che ogni script eseguibile dovrebbe avere un hashbang . In caso contrario, non stai dicendo al kernel di cosa si tratta , e quindi il kernel non sa quale programma utilizzare per interpretarlo. Potrebbe essere bash, perl, python, sh, o qualcos'altro. (In realtà, il kernel utilizzerà spesso la shell predefinita dell'utente per interpretare il file, il che è molto pericoloso perché potrebbe non essere affatto l'interprete giusto o potrebbe essere in grado di analizzarne alcuni ma con sottili differenze comportamentali come il caso tra she bash).

Una nota su /usr/bin/env

Più comunemente, vedrai gli hash bang in questo modo:

#!/bin/bash

Il risultato è che il kernel eseguirà il programma /bin/bashper interpretare lo script. Sfortunatamente, bashnon viene sempre spedito per impostazione predefinita e non è sempre disponibile in /bin. Mentre su macchine Linux di solito lo è, ci sono una serie di altre macchine POSIX in cui vengono bashspedite in varie posizioni, come /usr/xpg/bin/basho /usr/local/bin/bash.

Per scrivere uno script bash portatile, non possiamo quindi fare affidamento sulla codifica hardware della posizione del bashprogramma. POSIX ha già un meccanismo per trattare con che: PATH. L'idea è che tu installi i tuoi programmi in una delle directory che si trovano PATHe il sistema dovrebbe essere in grado di trovare il tuo programma quando vuoi eseguirlo per nome.

Purtroppo, non puoi semplicemente fare questo:

#!bash

Il kernel non (qualcuno potrebbe) fare una PATHricerca per te. C'è un programma che può fare una PATHricerca per te, però, si chiama env. Fortunatamente, in quasi tutti i sistemi è envinstallato un programma /usr/bin. Quindi iniziamo a envutilizzare un percorso hardcoded, che quindi esegue una PATHricerca bashe lo esegue in modo che possa interpretare il tuo script:

#!/usr/bin/env bash

Questo approccio ha un aspetto negativo: secondo POSIX, l'hashbang può avere un argomento . In questo caso, utilizziamo bashcome argomento il envprogramma. Ciò significa che non ci rimane spazio per passare argomenti bash. Quindi non c'è modo di convertire qualcosa di simile #!/bin/bash -exua questo schema. Dovrai invece inserire set -exul'hashbang.

Questo approccio ha anche un altro vantaggio: alcuni sistemi potrebbero essere forniti con un /bin/bash, ma l'utente potrebbe non apprezzarlo, potrebbe trovarsi difettoso o obsoleto e potrebbe aver installato il proprio bashaltrove. Questo è spesso il caso di OS X (Mac) in cui Apple spedisce un prodotto obsoleto /bin/bashe gli utenti installano un aggiornamento /usr/local/bin/bashusando qualcosa come Homebrew. Quando si utilizza l' envapproccio che esegue una PATHricerca, si tiene conto delle preferenze dell'utente e si utilizza la sua bash preferita rispetto a quella fornita dal suo sistema.


66
Grazie per aver dedicato del tempo a scrivere una buona risposta a una semplice domanda.
PA

5
Se uso zshcome shell, dovrei usare il hashbang #! /usr/bin/env zsh?
stefmikhail,

6
@stefmikhail: Non importa quale interprete di shell usi per invocare lo script, dovresti usare #! /usr/bin/env zshse (e solo se) il codice all'interno dello script dovrebbe essere eseguito dalla shell Z.
Johnsyweb,

1
+1 per spiegazione. tendo a dimenticare, ma conoscere il significato del comando mi aiuterà a ricordare.
Angelin Nadar,

2
@Carpetsmoker Questo è corretto e non limitato all'hashbang. Gli script bash dovrebbero sempre usare le terminazioni di riga UNIX, altrimenti l'ultimo argomento di ogni comando verrà aggiunto ad esso, proprio come il nome del comando hashbang.
lhunath,

80

Per avviare lo script di shell 'file.sh':

sh file.sh

bash file.sh

Un'altra opzione è impostare il permesso eseguibile usando il comando chmod:

chmod +x file.sh

Ora esegui il file .sh come segue:

./file.sh

16

Per la shell bourne:

sh myscript.sh

Per bash:

bash myscript.sh

Grazie per aver risposto a questa domanda abbastanza ovvia. Per un ragazzo Mac come me è facile dimenticare i vecchi comandi Unix tra i giri.
PA

10

Se si desidera che lo script venga eseguito nella shell corrente (ad es. Si desidera che possa influire sulla directory o sull'ambiente), si dovrebbe dire:

. /path/to/script.sh

o

source /path/to/script.sh

Si noti che /path/to/script.shpuò essere relativo, ad esempio . bin/script.shesegue script.shnella bindirectory nella directory corrente.


7
Prestare molta attenzione quando si procede o si utilizzano punti relativi. Dovresti sempre avviarli con ./ Se non lo fai, e il relativo percorso non contiene alcuna barra, otterrai qualcosa in PERCORSO, PRIMA di qualcosa nella directory corrente! Molto pericoloso per abuso.
lhunath,

0

Innanzitutto, autorizza l'esecuzione: -
chmod +x script_name

  1. Se lo script non è eseguibile: -
    Per eseguire il file di script sh: -
    sh script_name
    Per eseguire il file di script bash: -
    bash script_name
  2. Se lo script è eseguibile: -
    ./script_name

NOTA : -puoi verificare se il file è eseguibile o meno usando 'ls -a'


0

L'estensione del file .command è assegnata a Terminal.app. Facendo doppio clic su qualsiasi file .command verrà eseguito.


0

Piccola aggiunta, per eseguire un interprete dalla stessa cartella, usando ancora #! Hashbang negli script.

Ad esempio un eseguibile php7.2 copiato da / usr / bin si trova in una cartella lungo uno script hello .

#!./php7.2
<?php

echo "Hello!"; 

Per eseguirlo:

./hello

Che si comportano allo stesso modo di:

./php7.2 hello
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.