Skip to main content
  1. Concetti/

Shebang - #!

·3 mins
Alessio Barnini
Author
Alessio Barnini
Table of Contents

Cosa fa
#

Sequenza di due caratteri #! all'inizio di uno script che dice al kernel quale interprete usare per eseguirlo. Il kernel legge i primi due byte del file — se trova #! (shebang), usa il path che segue come interprete. Se non c'e', la shell corrente esegue lo script.

TL;DR
#

./script.sh
kernel legge primi 2 byte
     ├── trova #!  →  usa l'interprete specificato
     │                sempre lo stesso, ovunque
     └── non trova #!  →  usa la shell corrente
                          comportamento dipende dall'ambiente

Come funziona
#

# Il kernel vede:
#!/bin/bash
echo "ciao"

# Lo trasforma in:
/bin/bash ./script.sh

# Equivalente a scrivere direttamente:
bash script.sh

Il #! non e' commento per il kernel — e' una direttiva. Per bash invece # e' un commento, quindi la riga shebang viene ignorata dall'interprete.


Shebang comuni
#

#!/bin/bash        # bash esplicito
#!/bin/sh          # POSIX puro — usa sh (spesso dash su Ubuntu)
#!/usr/bin/env python3  # python3 — cerca nel PATH
#!/usr/bin/env node     # node.js — cerca nel PATH

/usr/bin/env e' un pattern importante — invece di hardcodare il path dell'interprete, cerca nel PATH dell'utente. Piu' portabile tra sistemi diversi dove python3 potrebbe stare in /usr/local/bin/ invece di /usr/bin/.


Senza shebang — comportamento non portabile
#

# script.sh senza shebang
x=10
echo $x
Sei in bash:  ./script.sh  →  bash lo esegue  →  funziona
Sei in zsh:   ./script.sh  →  zsh lo esegue   →  funziona
Sei in dash:  ./script.sh  →  dash lo esegue  →  potrebbe fallire
                                                   se usi bash-specific

Risultato dipendente dall'ambiente — non portabile.


Shebang e variabili — serve sempre export
#

Indipendentemente dallo shebang, uno script lanciato con ./ o bash script.sh e' sempre una subshell — un processo figlio separato.

CASO 1 — con shebang #!/bin/bash
─────────────────────────────────────────
shell corrente
export MESSAGGIO="ciao"     ← esportata
LOCALE="solo qui"           ← locale, non esportata
    └─► subshell (bash via shebang)
            echo $MESSAGGIO"ciao"    ← eredita
            echo $LOCALE""        ← non eredita

CASO 2 — senza shebang
─────────────────────────────────────────
shell corrente (bash)
export MESSAGGIO="ciao"     ← esportata
LOCALE="solo qui"           ← locale, non esportata
    └─► subshell (bash perche' sei in bash)
            echo $MESSAGGIO"ciao"    ← eredita
            echo $LOCALE""        ← non eredita

CASO 3source (nessuna subshell)
─────────────────────────────────────────
shell corrente
LOCALE="solo qui"           ← locale
    source script.sh               ← gira nella shell corrente
echo $LOCALE"solo qui"  ← stessa shell, vede tutto

La regola non cambia con lo shebang — export serve sempre quando lanci uno script come processo separato. Solo source bypassa questa regola perche' non crea una subshell.


Cosa succede se l'interprete non esiste
#

#!/bin/dash
echo "ciao"
./script.sh
# -bash: ./script.sh: /bin/dash: bad interpreter: No such file or directory

Nessun fallback — errore immediato. Il kernel cerca esattamente quel path.


Scenario Reale
#

Uno script di backup gira perfettamente sul Mac dello sviluppatore con zsh ma fallisce sul server di produzione Ubuntu. Causa: nessuno shebang, e lo sviluppatore usa array bash-specific.

# Sul Mac (zsh) — funziona
./backup.sh

# Sul server (sh → dash) — fallisce
./backup.sh
# syntax error: unexpected "("  ← array bash-specific non riconosciuto

Soluzione: aggiungere #!/bin/bash e verificare che bash sia installato sul server, oppure riscrivere in POSIX puro con #!/bin/sh.


Dove l'ho incontrato
#

  • Script Python failed_logins.py — usa #!/usr/bin/env python3
  • Script bash durante lo studio

Collegato a
#

  • system — categoria
  • posix — lo standard che definisce il comportamento di sh
  • shell-comparison — le diverse shell e le loro differenze
  • export — serve sempre quando si lancia uno script come subshell
  • shell-environment — variabili d'ambiente e loro ereditarieta'

Related