Shabang

Da Wikipedia, l'enciclopedia libera.

Nei sistemi operativi Unix e Unix-like lo shabang (chiamato anche shebang, hashbang, hashpling, o pound bang) è una sequenza di caratteri che inizia per "#!" collocata esattamente all'inizio di uno script, la quale indica al sistema quale interprete utilizzare per eseguire lo script stesso.

I caratteri della sequenza "shabang" (detta anche "hashbang")

Più precisamente, uno shabang consiste in un magic number (il carattere cancelletto e il punto esclamativo "#!"), seguito dal pathname assoluto dell'interprete da utilizzare.

Lo shabang viene utilizzato in modo che lo script appaia e funzioni agli occhi dell'utente come un qualsiasi altro file eseguibile nativo per la piattaforma.

Dato che nei linguaggi di scripting il carattere "#" indica comunemente l'inizio di una linea di commento, l'interprete ignorerà il contenuto della riga che contiene in incipit lo shabang; la linea esiste infatti soltanto per indicare quale interprete è necessario, e concettualmente non fa parte dello script.

Origine del termine[modifica | modifica wikitesto]

Il nome shabang deriva da una contrazione di SHArp bang o haSH bang, che rappresentano i nomi tradizionalmente usati in ambienti Unix per rifersi ai due caratteri in questione. Un'altra teoria sul sh di shabang deriva dalla shell testuale standard, "/bin/sh", che è solitamente l'interprete specificato.

Storia[modifica | modifica wikitesto]

Lo shabang fu introdotto da Dennis Ritchie tra la versione 7 di Unix e la versione 8 nei Bell Labs. Fu quindi aggiunta a BSD a Berkeley. Dato che la versione 8 e successive non furono rilasciate al pubblico, la prima diffusione di massa dello shabang avvenne proprio su BSD.

Portabilità[modifica | modifica wikitesto]

Mentre molti shabang indicano interpreti che hanno pathname standard ben noti, è anche possibile che tra varianti di uno stesso sistema operativo lo stesso interprete vada indicato con pathname differenti .

In assenza di una rigida standardizzazione delle posizioni di ciascun interprete, ci possono essere problemi dovuti al fatto che lo shabang potrebbe richiedere un interprete che non esiste, o che non si trova nel posto indicato. Questo limita la portabilità del file.

Per questo motivo, nel passaggio da computer a computer, è spesso necessario modificare lo script proprio per permettere la portabilità tra sistemi diversi. Questa è una delle ragioni per cui lo standard POSIX non prevede questa caratteristica, che è però comunemente utilizzata, soprattutto a livello didattico.

Spesso il comando env può essere usato per aggirare il problema.

Un altro problema di portabilità è legato alla gestione di eventuali parametri specificati all'interprete, in quanto alcuni sistemi hanno possibilità limitate al riguardo. Ad esempio sui sistemi basati su Linux lo shabang

#!/usr/bin/env perl -w

verrà eseguito come /usr/bin/env "perl -w", con "perl" e "-w" uniti in un unico parametro a /usr/bin/env e questo causa un errore:

 /usr/bin/env: perl -w: No such file or directory

Altri sistemi possono comportarsi in modo ancora diverso.

Shabang come numero magico[modifica | modifica wikitesto]

Lo shabang è di fatto una versione leggibile di un magic number nel file eseguibile. La stringa magica diviene la sequenza di byte 0x23 0x21 all'inizio del file, che corrisponde appunto alla rappresentazione secondo la codifica ASCII dei caratteri "#!".

I file eseguibili che non richiedono interpreti hanno invece altri magic number.

Linee shabang d'esempio[modifica | modifica wikitesto]

Script di shell[modifica | modifica wikitesto]

Esegue usando Bash:

#!/bin/bash

Esegue usando la shell /bin/sh. Su molti dei sistemi Unix e Unix-like questa è una shell POSIX (ad esempio su HP-UX, AIX ed anche su GNU/Linux, dove Bash si comporta come una shell POSIX se invocata con questo nome), mentre su Solaris è invece una Bourne shell:

#!/bin/sh

Esegue usando Korn shell:

#!/bin/ksh

Esegue usando csh, la C shell:

#!/bin/csh

Script Perl[modifica | modifica wikitesto]

Esegue usando Perl:

#!/usr/bin/perl

Esegue usando Perl, ma si assume che l'interprete Perl sia in un'altra directory:

#!/usr/local/bin/perl

Script Python[modifica | modifica wikitesto]

Esegue usando Python:

#!/usr/bin/python

Esegue usando Python versione 2.3:

#!/usr/bin/python2.3

Esegue usando Python versione 2.4:

#!/usr/bin/python2.4

Esegue usando Python versione 2.5:

#!/usr/bin/python2.5

Script Ruby[modifica | modifica wikitesto]

Esegue usando Ruby:

#!/usr/bin/ruby

Script Tcl[modifica | modifica wikitesto]

Esegue uno script Tcl invocando l'interprete attraverso /bin/sh:

#!/bin/sh
# Questa linea e la seguente sono ignorate da tclsh, mentre la shell ignora solo questa linea \
exec tclsh "$0" "$@"

Questo metodo sfrutta una particolarità del linguaggio Tcl: se una linea di commento termina con una barra inversa ("\"), allora il commento prosegue anche sulla linea successiva, mentre ciò non è non è vero per la shell.

Di fatto lo script viene avviato una prima volta tramite /bin/sh, che ignora la linea di commento e procede ad eseguire il comando "exec tclsh "$0" "$@"", che ricerca tclsh nelle directory elencate nella variabile d'ambiente $PATH e lo invoca passandogli il pathname dello script e tutti i parametri specificati, sostituendolo al processo della shell. L'interprete Tcl a questo punto inizia a leggere lo script, considera come un commento tutte e tre le linee, e procede quindi ad esaminare le linee successive.

Altri script[modifica | modifica wikitesto]

Esegue usando l'interprete Awk presente nella directory /bin/. Notare l'uso dell'opzione -f, altrimenti lo script verrebbe considerato come file di testo di input da elaborare (invece che le istruzioni AWK da eseguire):

#!/bin/awk -f

Esegue usando Lua:

#!/usr/bin/lua

Esegue usando l'interprete PHP:

#!/usr/bin/php

Invocazione con parametri e opzioni[modifica | modifica wikitesto]

In molti sistemi si può indicare di seguito all'interprete un parametro o una opzione, ed in alcuni di essi anche più parametri e/o opzioni. Tuttavia, implementazioni diverse hanno comportamenti e vincoli diversi: ad esempio in molti sistemi, tra cui quelli basati su Linux, tutto ciò che segue l'interprete è passato come un unico parametro anche se contiene spazi, mentre su altri sistemi vi sono limitazioni sulla lunghezza complessiva dello shabang.[1]

Esegue usando l'interprete AWK, e ad esso viene passata anche l'opzione -f:

#!/bin/awk -f
# Il resto dello script AWK
...

Esegue usando l'interprete Perl, e ad esso viene passata anche l'opzione -w per ottenere i messaggi di warning:

#!/usr/bin/perl -w
#
# Il resto dello script Perl
...

Esegue usando bash, indicando con l'opzione -x di mostrare ogni comando subito prima di eseguirlo:

#!/bin/bash -x
#
# Il resto dello script Bash
...

Risoluzione di problemi legati allo shabang tramite env[modifica | modifica wikitesto]

L'invocazione tramite env è utile in quanto diventa possibile specificare un interprete non conoscendo il suo pathname assoluto. env infatti cerca l'interprete nelle directory specificate nella variabile d'ambiente $PATH.

Ad esempio, supponendo di non sapere con precisione dove è installato l'interprete Perl:

#!/usr/bin/env perl
#
# Il resto dello script Perl
...

Nonostante questo metodo aumenti di molto la portabilità, esso non è infallibile: mentre env è quasi sempre disponibile in /usr/bin/env, in un numero ristretto di piattaforme si trova in /bin/env. In questo caso, come nel caso in cui si indichi un qualsiasi path non coerente con le impostazioni generali del sistema operativo, l'interprete dei comandi (il terminale) restituisce un errore e non esegue lo script.

Inoltre, sui sistemi che non separano tra di loro i parametri specificati di seguito all'interprete (che in questo caso è /usr/bin/env) diventa impossibile specificare parametri all'interprete vero e proprio.

Altri esempi[modifica | modifica wikitesto]

Questo è un quine, ovvero un file che produce in output sé stesso attraverso il comando cat:

#!/bin/cat
Testo qualsiasi, anche
su più righe.
...

Questo script non fa altro che scrivere all'infinito il nome con cui è invocato:

#!/usr/bin/yes
Testo qualsiasi (/usr/bin/yes non legge file)
...

Questo script non fa altro che auto-cancellarsi, usando rm come interprete:

#!/bin/rm
Testo qualsiasi (/bin/rm non legge il file, ma lo cancella e basta)
...

Note[modifica | modifica wikitesto]

  1. ^ (EN) Andries Brouwer, The #! line in #! - the Unix truth as far as I know it. URL consultato il 24-05-2008.

Voci correlate[modifica | modifica wikitesto]

Collegamenti esterni[modifica | modifica wikitesto]