Hva er forskjellen mellom å kjøre “ bash script.sh ” og “ ./script .sh ”?

Hvis script.sh bare er noe typisk som

#!/bin/bash echo "Hello World!" 

Er det en foretrukket måte å kjøre skriptet på? Jeg tror du først må modifisere det slik at det blir kjørbart?

Svar

For det spesifikke skriptet ditt vil en eller annen måte fungere, bortsett fra at ./script.sh krever utføring og lesbare biter, mens bash script.sh bare krever lesbar bit.


Årsaken til tillatelseskravets forskjell ligger i hvordan programmet som tolker skriptet ditt lastes inn:

  • ./script.sh gjør at skallet ditt kjører filen som om det var en vanlig kjørbar.

Skallet gaffel seg selv og bruker et systemanrop (f.eks. execve) for å få operativsystemet til å utføre filen i den gaffelte prosessen. Operativsystemet vil sjekke filens tillatelser (derav må kjøringsbiten settes) og videresende forespørselen til programlaster , som ser på filen og bestemmer hvordan du skal kjøre den. I Linux-kompilerte kjørbare filer starter med et ELF magisk nummer, mens skript starter med et #! ( hashbang ). En hashbang-header betyr at filen er et skript og må tolkes av programmet som er spesifisert etter hashbang. Dette tillater et skript seg selv for å fortelle systemet hvordan man skal tolke skriptet.

Med skriptet ditt vil programlaster utføre /bin/bash og passere ./script.sh som kommandolinje-argument.

  • bash script.sh får skallet til å kjøre bash script.sh som kommandolinjeargument

Så operativsystemet vil laste (ikke en gang ser på script.sh, fordi det bare er et kommandolinjeargument). Den opprettede bash prosessen tolker deretter script.sh fordi den sendes som kommandolinjeargumentet. Fordi script.sh leses bare av bash som en vanlig fil, eksekveringsbiten er ikke nødvendig.


Jeg anbefaler å bruke ./script.sh, fordi du kanskje ikke vet hvilken tolk skriptet krever. La programlaster bestemme det for deg.

Kommentarer

  • Hvis den kjørbare biten ikke er angitt, kan du også kjøre skriptet ved å gjøre " ./script.sh"
  • @Dog Du har rett. Prikken er en snarvei for innebygd kommando ' kilde ' , som kjører skriptet i den nåværende bash-prosessen. Så det er bare den lesbare biten som kreves.
  • @Dogeatcatworld mens det er sant, kjører . ./script.sh er ikke det samme ting som (eller ./script.sh. Tenk på skriptet #!/usr/bin/python -V < newline > print test.
  • Vær oppmerksom på at sourcing av et skript kan føre til forurensning av den interaktive økten. Hvis for eksempel et skript endrer PATH-miljøvariabelen, vil denne endringen påvirke kommandoer som kjøres etter kilden. Denne tilnærmingen bør egentlig være reservert for situasjoner der du er avhengig av bivirkningene (miljøoppsettskript og lignende). For andre situasjoner der du ikke kan ' t endre tillatelsene, er det den tryggeste metoden å kjøre kommandoen i shebang-linjen, etterfulgt av skriptnavnet.
  • , hvis du henter et skript i gjeldende katalog, trenger du ikke bruke ./ ; bare si . script.sh. Men jeg er enig med menneskene som fraråder å bruke kommandoen . på skript som ikke var ment å bli påkalt på den måten. Jeg er overrasket over at ingen nevnte at hvis skriptet inneholder exit kommandoer, og du kilder det, kan det logge deg ut. Et mindre alvorlig problem ville være hvis skriptet gjør et cd, da det også vil påvirke det overordnede (interaktive) skallet.

Svar

bash script.sh påkaller skriptet direkte ved hjelp av bash.
./script.sh bruker shebang #!/bin/bash for å bestemme hvordan du skal utføre.

Hvis du virkelig vil vite, hvilken binær som blir utført hvis du gjør en bash script.sh du kan finne ut med which bash.

Så i eksemplet ditt gjør det ingen forskjell. Ja, du må chmod +x script.sh for å kunne utføre den direkte via ./script.sh.

Kommentarer

  • Vel, det gjør ingen forskjell forutsatt at /bin/bash er den første bash i $PATH.
  • Du ' har rett. Og shebang #!/bin/bash fungerer bare hvis det er en /bin/bash
  • Bash (versjon 4.2.37) på meg systemet kjører skripter selv uten bit-settet. Hvorfor sier du at eksekveringsbit er påkrevd?
  • Ja, eksekveringsbit er bare nødvendig ved å påkalle via ./script.sh.

Svar

Opprett en fil Delete_Self.sh slik:

 #!/bin/rm echo I am still here! 

Kjør dette skript som sh Delete_Self.sh vil du se «Jeg er fortsatt her!» ekko tilbake.

Gjør det kjørbart, og kjør det som ./Delete_Self.sh du vil se at ingenting blir ekko tilbake, mens filen Delete_Self.sh seg selv er borte.

Så forskjellen er at:

  • bash script.sh vil ignorere #! linje, fordi bash er spesifisert som programmet for å kjøre script.sh.
  • ./script.sh vil lese #! linje for å bestemme programmet som skal kjøres script.sh.

Kommentarer

  • +1 for det fine eksemplet

Svar

I tillegg til de andre svarene, å vite forskjellen mellom å kjøre et skript via ./script.sh (i) og kilde ./script.sh (ii) er nyttig – (i) -versjonen oppretter et nytt skall for å kjøre kommandoen, mens (ii) kjører den i det nåværende skallet – noe som kan være obligatorisk hvis den kjørbare filen endrer miljøvariabler som må bevares etter at den kjørbare utgangen er avsluttet. For eksempel, for å aktivere et python conda-miljø, må følgende brukes:

source activate my_env 

N.B. Et annet alternativ til source som du kan støte på er . innebygd, dvs.

. activate my_env 

Legg igjen en kommentar

Din e-postadresse vil ikke bli publisert. Obligatoriske felt er merket med *