Perché è necessario inserire #! / Bin / bash all'inizio di un file di script?


487

Ho già scritto degli script Bash e tutti hanno funzionato bene senza #!/bin/bashall'inizio.

A che serve metterlo? Le cose sarebbero diverse?

Inoltre, come si pronuncia #? So che !è pronunciato come "bang".

Come si #!pronuncia?


8
Non è necessario e non dovresti a meno che tu non abbia scelta. Usa '#! / Bin / sh' mentre puoi e scopri la differenza tra una shell (POSIX) e bash. Arriverà un giorno prima che il tuo curriculum cresca troppo a lungo quando ti ritroverai su un sistema con una shell diversa e vuoi ancora che i tuoi script funzionino.
Jens,

50
Si pronuncia "Hash-Bang" o "She-Bang".
Beachhouse

22
Penso che valga la pena notare che questo viene eseguito solo se esegui il tuo script come eseguibile. Quindi, se si imposta il flag eseguibile e quindi si digita ./yourscript.extension, ad esempio, ./helloworld.pyo ./helloworld.sh, cercherà l'interprete in quella riga superiore, che sarebbe #!/bin/pythono !#/bin/bash, mentre quando si esegue lo script come python helloworld.py, la prima riga non verrà osservata perché è commentata su. Quindi è una sequenza speciale per la shell / kernel.
JFA,

@JFA c'è un cambiamento nella sequenza tra bash e python, quando si usa! # Per python e #! per bash?
AAI

1
@AjeyaAnand no era un errore di battitura, buona cattura
JFA

Risposte:


426

È una convenzione, quindi la shell * nix sa quale tipo di interprete eseguire.

Ad esempio, le versioni precedenti di ATT di default erano sh (la shell Bourne), mentre le versioni precedenti di BSD erano impostate su csh (shell C).

Ancora oggi (dove la maggior parte dei sistemi esegue bash, la "Bourne Again Shell" ), gli script possono essere in bash, python, perl, ruby, PHP, ecc. Ecc. Ad esempio, potresti vedere #!/bin/perlo #!/bin/perl5.

PS: Il punto esclamativo ( !) è chiamato affettuosamente "bang" . Il simbolo di commento della shell ( #) viene talvolta chiamato "hash" .

PPS: Ricorda - sotto * nix, associare un suffisso a un tipo di file è semplicemente una convenzione , non una "regola" . Un eseguibile può essere un programma binario, uno qualsiasi tra un milione di tipi di script e altre cose. Da qui la necessità di #!/bin/bash.


1
Ho scoperto qualcos'altro di utile, $ #. Come si chiama?
nodo ninja

91
Lo shebang non è una convenzione di shell , viene interpretato dal kernel quando gestisce il execve(2)syscall; quindi lo shebang è una convenzione del kernel , non una shell.
Basile Starynkevitch il

10
Inoltre, aiuta alcuni editor come Vim a determinare la lingua per l'evidenziazione della sintassi se il file non ha estensione. Senza lo shebang, Vim mostrerà uno script bash come il semplice file di testo.
Aaron Blenkush il

1
Mi chiedo se è necessario aggiungere #!/bin/shcose come .profilee cose che vengono caricate
Kolob Canyon,

5
Quindi ... hash-bang-slash-bin-slash-bash ?
Bernat

135

Per essere più precisi, lo shebang #! , quando sono i primi due byte di un file eseguibile ( x mode ), viene interpretato dalla chiamata di sistema execve (2) (che esegue i programmi). Ma le specifiche POSIX perexecve non menzionare lo shebang.

Deve essere seguito da un percorso file di un eseguibile dell'interprete (che BTW potrebbe anche essere relativo, ma il più delle volte è assoluto).

Un bel trucco (o forse non così bello ) per trovare un interprete (es. python) Nell'utente $PATHè usare il envprogramma (sempre /usr/bin/envsu tutti i Linux) come ad es.

 #!/usr/bin/env python

Qualsiasi eseguibile ELF può essere un interprete. Potresti anche usare #!/bin/cato #!/bin/truese lo volessi! (ma sarebbe spesso inutile)


8
Vedi questa domanda per una discussione #!/usr/bin/envdell'hack.
Keith Thompson,

se voglio passare un argomento a Python come faccio a farlo in realtà voglio eseguire #!/usr/bin/env bash -x. Come lo faccio ?
indianwebdevil,

è semplice, l'ho trovato anch'io, basta aggiungere il parametro dopo#!/usr/bin/env bash -x
indianwebdevil,

bashè quasi sempre /bin/bashcosì il tuo shebang dovrebbe essere#!/bin/bash -x
Basile Starynkevitch

50

Si chiama shebang . In unix-speak, # si chiama sharp (come nella musica) o hash (come hashtag su Twitter) e! si chiama bang. (Puoi effettivamente fare riferimento al tuo precedente comando shell con !!, chiamato bang-bang). Quindi, quando messi insieme, ottieni haSH-BANG, o shebang.

La parte dopo il #! indica a Unix quale programma utilizzare per eseguirlo. Se non è specificato, proverà con bash (o sh, o zsh, o qualunque sia la tua variabile $ SHELL) ma se è lì userà quel programma. Inoltre, # è un commento nella maggior parte delle lingue, quindi la riga viene ignorata nell'esecuzione successiva.


2
Se sono già in bash, avvia un'altra istanza bash se vede #! / Bin / bash? E se sono già in bash e lo lascio fuori? C'è qualche differenza?
nodo ninja

2
@javascriptninja in entrambi i casi avvia una nuova shell bash. Nel caso di bash, non c'è davvero alcuna differenza, purché tu stia già usando bash. Lo shebang conta davvero solo se (a) devi correre in qualcosa che non è solo una shell, come python o perl, o (b) non usi la shell bash (cioè usi zsh) ma devi eseguire qualcosa che richiede di essere eseguito in bash.
austin1howard,

Tuttavia, secondo me è buona norma includere lo shebang, così solo qualcuno che legge il codice sa cosa sta succedendo.
austin1howard,

2
Sbagliato: execve(2)syscall non usa la $SHELLvariabile. È il kernel che sta interpretando lo shebang.
Basile Starynkevitch,

1
@BasileStarynkevitch che è corretto, il caricatore di elfi nel kernel interpreta lo shebang. Stavo affermando che $ SHELL sarebbe stato usato se non fosse stato fornito nessun shebang.
austin1howard,

19

La faccenda è una direttiva per il caricatore di utilizzare il programma che è specificato dopo il #!come interprete per il file in questione quando si tenta di eseguirlo. Quindi, se si tenta di eseguire un file chiamato foo.shche ha #!/bin/bashnella parte superiore, il comando effettivo che viene eseguito è /bin/bash foo.sh. Questo è un modo flessibile di usare interpreti diversi per programmi diversi. Questo è qualcosa implementato a livello di sistema e l'API a livello di utente è la convenzione shebang.

Vale anche la pena sapere che lo shebang è un numero magico - un numero leggibile dall'uomo che identifica il file come uno script per l'interprete indicato.

Il tuo punto su "lavorare" anche senza shebang è solo perché il programma in questione è uno script di shell scritto per la stessa shell di quella che stai usando. Ad esempio, potresti benissimo scrivere un file javascript e quindi inserire un #! /usr/bin/js(o qualcosa di simile) per avere uno "script Shell" javascript.


18

Il sistema operativo utilizza la shell predefinita per eseguire lo script della shell. così menzionando il percorso della shell all'inizio dello script, stai chiedendo al sistema operativo di usare quella particolare shell. È anche utile per la portabilità .


15

Ogni distribuzione ha una shell predefinita. Bash è l'impostazione predefinita sulla maggior parte dei sistemi. Se ti capita di lavorare su un sistema con una shell predefinita diversa, gli script potrebbero non funzionare come previsto se sono scritti in modo specifico per Bash.

Bash si è evoluto negli anni prendendo il codice da kshe sh.

Aggiungendo #!/bin/bashcome prima riga dello script, si dice al sistema operativo di invocare il specificato shellper eseguire i comandi che seguono nello script.

#! viene spesso definito "hash-bang", "she-bang" o "sha-bang".


9

Si chiama shebang . È composto da un segno numerico e da un punto esclamativo (#!), Seguito dal percorso completo dell'interprete come / bin / bash. Tutti gli script in UNIX e Linux vengono eseguiti utilizzando l'interprete specificato su una prima riga.



0

Può essere utile a qualcuno che utilizza un sistema diverso che non ha quella libreria prontamente disponibile. Se questo non è dichiarato e hai alcune funzioni nello script che non sono supportate da quel sistema, dovresti dichiarare # / bin / bash. Ho già riscontrato questo problema al lavoro e ora lo includo solo come pratica.

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.