Qual è la differenza tra ./ e sh per eseguire uno script?


71

Ho scritto una sceneggiatura semplice. Quando corro sh <myscriptname.sh>, ho ottenuto l'output corretto, ma quando corro ./<myscriptname.sh>, ho ricevuto un errore.

Qual è la differenza tra quando lo faccio she ./?


15
Invece di dire semplicemente "Ottengo un errore", sarebbe d'aiuto se incollassi ciò che diceva l'errore.
SpashHit

Risposte:


67

Quando si esegue uno script passando il nome file al programma interprete di script, si esegue il programma interprete con lo script come argomento passato in esso. Ad esempio, questo assomiglierebbe al processo 'sh' con l'argomento 'nomefile.sh'. L' shinterprete sta aprendo il file.

D'altra parte, se si esegue lo script stesso, il sistema chiama il programma interprete specificato e inserisce i contenuti degli script. In questo caso il processo appare come 'nomefile.sh' senza argomenti.

Dovresti assicurarti di avere una linea di bang:

#!/bin/bash
# bash script here

Una bang line è la prima riga dello script e inizia con gli stessi due caratteri #!, questi sono ciò che il sistema legge quando tenta di eseguire lo script e quindi il sistema passa lo script al programma immediatamente dopo. Nota che questa linea non ha nulla a che fare con bash e funziona altrettanto bene per python e perl, anche se sono linguaggi molto diversi. Dovresti usare #!/usr/bin/pythonad esempio e poi seguirlo con il codice Python.

Una volta che hai il tuo script, assicurati di aver impostato le autorizzazioni di esecuzione:

chmod a+x filename.sh

Quindi è possibile eseguire lo script come processo proprio:

./filename.sh

O metti il ​​file in un percorso noto con un bel nome di programma, come /usr/sbined eseguilo da qualsiasi luogo:

sudo cp filename.sh /usr/sbin/program-name
program-name

E questo è davvero il vantaggio pratico dell'uso della bang line con le giuste autorizzazioni: si tratta solo di implementare . È molto difficile indurre gli utenti a eseguire uno script se devono ricordare con quale programma eseguire lo script. Ricorda di dare un percorso completo allo script ogni volta che vogliono eseguirlo. Dove, /usr/local/binad esempio, inserendolo e rendendolo eseguibile, puoi risparmiare un sacco di dolore per le persone che cercano di usare la tua sceneggiatura. Questi programmi diventano quindi disponibili per tutti gli utenti sul tuo computer.

È anche buono per l'identificazione. Se entri nel topprogramma, uno script eseguito senza la linea di bang avrà solo il nome dell'interprete bash, ovvero , perlo python. Ma se uno script viene eseguito con le autorizzazioni giuste, viene visualizzato il nome dello script.

Nota: se si desidera distribuire uno script accessibile a tutti, creare una pagina man e un pacchetto deb per installarlo. Dobbiamo ridurre il numero di script casuali online e aumentare il numero di debs che possono essere disinstallati.


1
Puoi anche usare una cartella bin personale: crea una cartella bin nella tua cartella home disconnettiti e accedi di nuovo e dovresti quindi essere in grado di eseguire qualsiasi script in quella cartella senza sh o ./.
papukaija,

Certo, ma aggiungere la tua cartella home al tuo PERCORSO può essere un po 'un mal di testa. Meglio installare le cose. Sebbene si sia parlato dell'aggiunta di ~ / .local / bin al percorso per impostazione predefinita per consentire l'installazione di pacchetti da parte degli utenti locali.
Martin Owens -doctormo-

Si noti che l'interprete predefinito è bashno sh.
Nathan Osman,

1
Non inserire estensioni negli script, soprattutto non quando lo inserisci PATH.
geirha,

1
/usr/local/binè probabilmente meglio allora /usr/sbin- indica che il programma è locale a questa macchina piuttosto che essere parte della distribuzione.
Glenn Jackman,

41

La versione corta:

  • shè l'interprete della riga di comando (trattino).
    L'esecuzione sh my_scriptconsente a dash di interpretare lo script.

  • ./cerca di scoprire quale interprete usare, guardando la prima riga. Ad esempio #!/bin/bash, o addirittura #!/bin/ruby(al contrario di correre ruby my_script).


7
In realtà non ./trova nulla, è il metodo di esecuzione del sistema che esamina i primi due byte del file.
Martin Owens -doctormo-

9
Assolutamente. Ecco una spiegazione molto lunga di tutto ciò. Sono pragmatico :)
Stefano Palazzo

Quando usi she il file contiene uno sha-bang, significa che lo sha-bang verrà ignorato o aprirà la shell dove shanche i collegamenti e quindi forse qualche altra shell o cosa fa :)?
Ini

5

La differenza che fai è

  • con sh, stai eseguendo un programma che interpreterà le linee nel tuo script proprio come le avresti digitate sul prompt interattivo del terminale,

  • con ./cui stai facendo una scorciatoia supponendo che lo script sia proprio qui nella directory corrente in cui ti trovi E sarà eseguibile (perché per esempio hai emesso chmod +x myscript.sh), risparmiando tempo prezioso per tempi futuri :-)


3
+1 per essere l'unico a dichiarare concisamente che il file deve essere eseguibile.
Mikel,

2
Si noti che con shil file non deve essere necessariamente eseguibile.
Ini

3

Esistono tre motivi principali per cui potresti ricevere un errore:

  • il file non è eseguibile
    corsa chmod +x <myscriptname.sh>per risolvere questo
  • la partizione non consente l'esecuzione di script (è montato " noexec") su cui
    copiare lo script/usr/local/bin
  • la #!riga presenta un errore
    assicurarsi che la prima riga sia #!/bin/sho#!/bin/bash

Se la tua prima riga sembra corretta, ma continua a non funzionare, assicurati che il file non abbia terminazioni di riga DOS.

L'errore sarebbe simile al seguente:

$ ./myscript.sh
bash: ./myscript.sh: /bin/bash^M: bad interpreter: No such file or directory

È possibile risolvere il problema eseguendo dos2unix <myscriptname.sh>, o se non si dispone di questo,
perl -p -i -e 's/\r\n$/\n/' <myscriptname.sh>.


0

E la risposta è che sh è il nome di una shell molto popolare. Ma obsoleto e sostituito da altri. Oggi sh è collegato ad altre shell installate sulla macchina. ad esempio ho messo la bash lì. L'esecuzione di qualsiasi shell da sh in genere attiva una modalità di "compatibilità" con comportamento originale "shell".

Quindi la soluzione è abbastanza semplice. Guarda cosa c'è dietro il comando sh (ls -al / bin / sh) e metti #! / Bin / whatever_you_find_there come prima riga (o se c'è qualcosa di simile nel tuo script modificalo).

E in alternativa potrebbe esserci qualche bug nello script stesso. Come la dipendenza che incontra sh, ma non l'interprete effettivamente utilizzato.


0
mkdir ~/bin ; cp myscript.sh ~/bin/

echo "export PATH="$PATH:/home/$USER/bin" >> ~/.profile ; source ~/.profile ; 

No /usr/sbin, è per gli strumenti amministrativi non essenziali, /usr/local/binè una scelta migliore se non si desidera avere un ~/bin/, ma sudoè consigliabile evitare il più possibile.


Su Ubuntu, il valore predefinito ~/.profileha già il codice per l'aggiunta ~/bin, se esiste, a PATH. In un'altra nota, non inserire estensioni negli script.
geirha,

1
Stavo facendo riferimento a <myscriptname.sh>, ma qual è la logica per non inserire estensioni negli script? Di solito lo faccio perché avere i file di testo in chiaro visibili in questo modo mi impedisce di provare a modificare i binari che tengo anche in ~ / bin /. ( ls ~/bin/|wc -l = 428) Ho messo un sacco di roba lì dentro;)
Joey1978,

Immagina di scrivere una sceneggiatura per realizzare un compito specifico. Quindi ti rendi conto che scrivere questo particolare script in Python lo renderà molto più efficiente, quindi lo riscrivi in ​​Python. Ora hai due scelte. 1) Lasciare l'estensione .sh ora molto fuorviante, oppure 2) rinominare lo script e cercare e sostituire tutti gli usi dello script per usare il nuovo nome. Se guardi gli script /bine /usr/binvedrai che non usano le estensioni.
geirha,
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.