In basho sh, suppongo che tutto ciò che inizia con #è un commento .
Ma negli bashscript scriviamo:
#!/bin/bash
E negli script Python, c'è:
#!/bin/python
Questo significa che di #per sé è un commento, mentre #!non lo è?
In basho sh, suppongo che tutto ciò che inizia con #è un commento .
Ma negli bashscript scriviamo:
#!/bin/bash
E negli script Python, c'è:
#!/bin/python
Questo significa che di #per sé è un commento, mentre #!non lo è?
Risposte:
#!riga viene utilizzata prima dell'esecuzione dello script, quindi ignorata quando viene eseguito lo script.Stai chiedendo quale sia la differenza tra una linea shebang e un commento normale.
Una riga che inizia con #!è tanto un commento quanto qualsiasi altra riga che inizia con #. Questo è vero se #!è la prima riga del file o in qualsiasi altro luogo. #!/bin/sh ha un effetto , ma non viene letto dall'interprete stesso .
#non è un commento in tutti i linguaggi di programmazione ma, come sapete, è un commento nelle shell in stile Bourne tra cui she bash(così come la maggior parte delle shell in stile non Bourne, come csh). È anche un commento in Python . Ed è un commento in una varietà di file di configurazione che in realtà non sono affatto script (come /etc/fstab).
Supponiamo che uno script di shell inizi con #!/bin/sh. Questo è un commento e l'interprete (la shell) ignora tutto sulla riga dopo il #personaggio.
Lo scopo di una #!linea non è di fornire informazioni all'interprete. Lo scopo della #!linea è di dire al sistema operativo (o qualunque processo avvii l'interprete) cosa usare come interprete .
Se si richiama lo script come file eseguibile, ad esempio eseguendolo ./script.sh, il sistema consulta la prima riga per vedere se inizia #!, seguito da zero o più spazi, seguito da un comando. In tal caso, esegue quel comando con il nome dello script come argomento. In questo esempio, viene eseguito /bin/sh script.sh(o, tecnicamente, /bin/sh ./script.sh).
Se invochi lo script chiamando esplicitamente l'interprete, la #!linea non viene mai consultata. Quindi, se corri sh script.sh, la prima riga non ha alcun effetto. Se script2.shla prima riga è #!/usr/games/nibbles, in esecuzione sh script2.shnon tenterà di aprire lo script nibbles(ma lo ./script2.shfarà).
Noterai che in nessun caso l'estensione dello script ( .sh), se ne ha una, influisce sul modo in cui viene eseguita. In un sistema simile a Unix, ciò non influisce normalmente su come viene eseguito lo script. Su alcuni altri sistemi, come Windows, la #!linea shebang potrebbe essere completamente ignorata dal sistema e l'estensione potrebbe determinare ciò che esegue gli script. (Ciò non significa che devi fornire le estensioni degli script, ma è uno dei motivi per cui, se lo fai, dovrebbero essere corretti.)
#!è stato scelto per servire questo scopo proprio perché # inizia un commento. La #!linea è per il sistema, non per l'interprete, e dovrebbe essere ignorata dall'interprete.
Tu (originariamente) hai detto che usi #!/bin/shper gli bashscript. Dovresti farlo solo se lo script non richiede alcuna delle bashestensioni - shdeve essere in grado di eseguire lo script. shnon è sempre un collegamento simbolico a bash. Spesso, anche su tutti i sistemi Debian e Ubuntu remoti di recente , shè un collegamento simbolico a dash.
Hai anche detto (nella prima versione della tua domanda, prima di modificarlo) che avvii i tuoi script Python con #!/bin/sh read by the interpretor. Se lo intendi letteralmente, allora dovresti assolutamente smettere di farlo. Se hello.pyinizia con quella riga, l'esecuzione ./hello.pyviene eseguita:
/bin/sh read by the interpretor hello.py
/bin/shproverà ad eseguire uno script chiamato read(con by the interpretor hello.pyi suoi argomenti), read(si spera) non verrà trovato e il tuo script Python non verrà mai visto da un interprete Python.
Se stai commettendo questo errore ma non hai il problema che sto descrivendo, probabilmente stai invocando i tuoi script Python specificando esplicitamente l'interprete (ad esempio, python hello.py), facendo sì che la prima riga venga ignorata. Quando distribuisci i tuoi script ad altri o li usi molto tempo dopo, potrebbe non essere chiaro che questo è necessario per farli funzionare. È meglio risolverli ora. O almeno rimuovere completamente la prima riga, in modo che quando non riescono a funzionare con ./il messaggio di errore abbia senso.
Per gli script Python, se sai dove si trova (o sta per essere) l'interprete Python, puoi scrivere la #!riga allo stesso modo:
#!/usr/bin/python
Oppure, se si tratta di uno script Python 3, è necessario specificare python3, poiché pythonè quasi sempre Python 2 :
#!/usr/bin/python3
Tuttavia, il problema è che mentre /bin/shdovrebbe sempre esistere, e /bin/bashquasi sempre esiste su sistemi in cui bashè presente il sistema operativo, Python può esistere in una varietà di luoghi.
Pertanto, molti programmatori Python usano questo invece:
#!/usr/bin/env python
(O #!/usr/bin/env python3per Python 3.)
Questo fa sì che lo script faccia affidamento envsull'essere nel "posto giusto" invece di fare affidamento sul pythonfatto di essere nel posto giusto. Questa è una buona cosa, perché:
envsi trova quasi sempre in /usr/bin.python sia il tuo script da eseguire è quello che appare per primo nel file PATH. A partire hello.pyda #!/usr/bin/env pythonmake ./hello.pyrun /usr/bin/env python hello.py, che è (praticamente) equivalente a running python hello.py.Il motivo per cui non #!pythonè possibile utilizzare è che:
/).python nella directory corrente . Cercare il percorso quando il comando non contiene una barra è un comportamento specifico della shell.Occasionalmente uno script Python o altro che non è uno script shell avrà una riga shebang che inizia con #!/bin/sh ...dove si ...trova un altro codice. Questo a volte è corretto, perché ci sono alcuni modi per invocare la shell ( sh) compatibile con Bourne con argomenti per farlo invocare un interprete Python. (Probabilmente uno degli argomenti conterrà python.) Tuttavia, per la maggior parte degli scopi, #!/usr/bin/env pythonè più semplice, più elegante e più probabile che funzioni nel modo desiderato.
Molti linguaggi di programmazione e di scripting, e alcuni altri formati di file, usano #come commento. Per ognuno di essi, un file nella lingua può essere eseguito da un programma che lo prende come argomento specificando il programma sulla prima riga dopo #!.
In alcuni linguaggi di programmazione, #normalmente non è un commento, ma come caso speciale la prima riga viene ignorata se inizia con #!. Questo facilita l'uso della #!sintassi anche se #altrimenti non fa una riga un commento.
Sebbene sia meno intuitivo, qualsiasi file il cui formato di file può contenere una prima riga che inizia con #!seguito dal percorso completo di un eseguibile può avere una riga shebang. Se lo fai, e il file è contrassegnato come eseguibile, puoi eseguirlo come un programma ... facendolo aprire come un documento.
Alcune applicazioni usano questo comportamento intenzionalmente. Ad esempio, in VMware, i .vmxfile definiscono le macchine virtuali. Puoi "eseguire" una macchina virtuale come se fosse uno script perché questi file sono contrassegnati come eseguibili e hanno una linea shebang che li fa aprire in un'utilità VMware.
rmrimuove i file. Non è un linguaggio di scripting. Tuttavia, #!/bin/rmè possibile eseguire un file che viene avviato e contrassegnato come eseguibile e, quando lo si esegue, rmviene richiamato su di esso, eliminandolo.
Questo è spesso concettualizzato come "il file si elimina da solo". Ma il file non è davvero in esecuzione. Questo è più simile alla situazione sopra descritta per i .vmxfile.
Tuttavia, poiché la #!riga facilita l'esecuzione di un semplice comando (inclusi gli argomenti della riga di comando), è possibile eseguire alcuni script in questo modo. Come semplice esempio di uno "script" più sofisticato di #!/bin/rm, considera:
#!/usr/bin/env tee -a
Questo prende l'input dell'utente in modo interattivo, lo fa ritornare all'utente riga per riga e lo aggiunge alla fine del file "script".
Utile? Non molto. Concettualmente interessante? Totalmente! Sì. (Un po '.)
Script / programmi che sono più lingue contemporaneamente , ad esempio, per simulare la funzionalità hashbang nei sistemi operativi che non lo possedevano .
(Questi programmi sono chiamati poliglotti , ma ciò non deve essere confuso con l'altro senso di poliglotta nello sviluppo del software , un programma / progetto in cui parti diverse sono scritte in lingue diverse.)
Metacommands in QBasic / QuickBASIC, che segnalavano al compilatore (per codice compilato) opzioni per la generazione di codice, ma facevano parte dei commenti e quindi venivano ignorati durante la compilazione / interpretazione effettiva.
-xbandiera Pythons ?
-x"salta [s] la prima riga ..." la 2a riga viene numerata 1anziché 2la 3a riga 2anziché 3, ecc. Ecco perché non dovresti usare quella bandiera. ;) -xè per lo scripting su sistemi operativi non Unix che hanno una sintassi simile a shebang che non inizia #(quindi non un commento Python).
perl script.plvs ./script.pl), allora l'interprete sarà leggere la linea shebang per analizzare le bandiere, come -w. Tuttavia, non è consigliabile fare affidamento su questa funzione.
Uno shebang è la sequenza di caratteri costituita dal segno del numero di caratteri e dal punto esclamativo (ad esempio "#!") Quando si presenta come i due caratteri iniziali sulla riga iniziale di uno script.
Sotto i sistemi operativi * nix, quando viene eseguito uno script che inizia con uno shebang, il programma di caricamento programma analizza il resto della riga iniziale dello script come una direttiva interprete; viene invece eseguito il programma interprete specificato, passando ad esso come argomento il percorso inizialmente utilizzato durante il tentativo di eseguire lo script. Ad esempio, se uno script è denominato con il percorso "path / to / your-script" e inizia con la seguente riga:
#!/bin/sh
quindi al programma di caricamento del programma viene richiesto di eseguire il programma "/ bin / sh", ad esempio la shell Bourne o una shell compatibile, passando "path / to / your-script" come primo argomento.
Di conseguenza, uno script viene chiamato con il percorso "path / to / python-script" e inizia con la seguente riga:
#!/bin/python
quindi al programma caricato viene richiesto di eseguire il programma "/ bin / python" invece ad es. interprete Python, passando "path / to / python-script" come primo argomento.
In breve "#" commenterà una riga mentre la sequenza di caratteri "#!" che si presentano come i primi due caratteri sulla riga iniziale di uno script hanno significato delineato come sopra.
Per i dettagli, vedi Perché alcuni script iniziano con #! ...?
Fonte: alcune sezioni di questa risposta sono derivate (con lievi modifiche) da Shebang (Unix) su Wikipedia in inglese (dai collaboratori di Wikipedia ). Questo articolo è concesso in licenza in base a CC-BY-SA 3.0 , come il contenuto dell'utente qui su AU, quindi questa derivazione è consentita con attribuzione.
#!viene chiamato shebangquando si presenta come i due caratteri iniziali sulla riga iniziale di uno script. Viene utilizzato negli script per indicare un interprete per l'esecuzione. Il shebangè per il sistema operativo (kernel), non per la shell; quindi non verrà interpretato come un commento.
Per gentile concessione: http://en.wikipedia.org/wiki/Shebang_%28Unix%29
In generale, se un file è eseguibile, ma in realtà non è un programma eseguibile (binario), e tale linea è presente, il programma specificato dopo #! viene avviato con lo scriptname e tutti i suoi argomenti. Questi due personaggi # e! devono essere i primi due byte nel file!
Informazioni dettagliate: http://wiki.bash-hackers.org/scripting/basics#the_shebang
No, viene utilizzato solo dalla execchiamata di sistema del kernel Linux e trattato come un commento dall'interprete
Quando fai su bash:
./something
su Linux, questo chiama la execchiamata di sistema con il percorso ./something.
Questa riga del kernel viene chiamata sul file passato a exec: https://github.com/torvalds/linux/blob/v4.8/fs/binfmt_script.c#L25
if ((bprm->buf[0] != '#') || (bprm->buf[1] != '!'))
Legge i primi byte del file e li confronta con #!.
Se il confronto è vero, il resto della riga viene analizzato dal kernel Linux, che effettua un'altra execchiamata con percorso /usr/bin/env pythone file corrente come primo argomento:
/usr/bin/env python /path/to/script.py
e questo funziona con qualsiasi linguaggio di scripting che utilizza #come carattere di commento.
E sì, puoi fare un ciclo infinito con:
printf '#!/a\n' | sudo tee /a
sudo chmod +x /a
/a
Bash riconosce l'errore:
-bash: /a: /a: bad interpreter: Too many levels of symbolic links
#! sembra essere leggibile dall'uomo, ma non è necessario.
Se il file si avviava con byte diversi, la execchiamata di sistema utilizzava un gestore diverso. L'altro gestore incorporato più importante è per i file eseguibili ELF: https://github.com/torvalds/linux/blob/v4.8/fs/binfmt_elf.c#L1305 che verifica la presenza di byte 7f 45 4c 46(che risulta essere umano leggibile per .ELF). Confermiamo leggendo i primi 4 byte di /bin/ls, che è un eseguibile ELF:
head -c 4 "$(which ls)" | hd
produzione:
00000000 7f 45 4c 46 |.ELF|
00000004
Quindi quando il kernel vede quei byte, prende il file ELF, lo mette in memoria correttamente e avvia un nuovo processo con esso. Vedi anche: https://stackoverflow.com/questions/8352535/how-does-kernel-get-an-executable-binary-file-running-under-linux/31394861#31394861
Infine, puoi aggiungere i tuoi gestori shebang con il binfmt_miscmeccanismo. Ad esempio, è possibile aggiungere un gestore personalizzato per i .jarfile . Questo meccanismo supporta anche i gestori per estensione del file. Un'altra applicazione è eseguire in modo trasparente eseguibili di un'architettura diversa con QEMU .
Tuttavia , non credo che POSIX specifichi shebang: https://unix.stackexchange.com/a/346214/32558 , anche se menzionato nelle sezioni logiche e nel modulo "se gli script eseguibili sono supportati dal sistema qualcosa potrebbe accadere".
#include. Anche lì, il#non è inteso come un commento.