Vad är skillnaden mellan att köra “ bash script.sh ” och “ ./script .sh ”?

Om script.sh bara är något typiskt som

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

Finns det en föredragen sätt att köra skriptet? Jag tror att du först måste modifiera det så att det blir körbart?

Svar

För ditt specifika skript fungerar antingen sättet, förutom att ./script.sh kräver exekvering och läsbara bitar, medan bash script.sh endast kräver läsbar bit.


Anledningen till skillnaden mellan behörighetskrav ligger i hur programmet som tolkar ditt skript laddas:

  • ./script.sh gör att ditt skal kör filen som om det var en vanlig körbar.

Skalet gafflar sig själv och använder ett systemanrop (t.ex. execve) för att få operativsystemet att köra filen i den gafflade processen. Operativsystemet kontrollerar filens behörigheter (därför måste körningsbiten ställas in) och vidarebefordrar begäran till programladdaren , som tittar på filen och bestämmer hur man kör det. I Linux-kompilerade körbara filer börjar med ett ELF magiskt nummer, medan skript börjar med ett #! ( hashbang ). En hashbang-rubrik betyder att filen är ett skript och måste tolkas av programmet som anges efter hashbang. Detta tillåter ett skript sig själv för att berätta för systemet hur man tolkar skriptet.

Med ditt skript kör programladdaren /bin/bash och skickar ./script.sh som kommandoradsargument.

  • bash script.sh får ditt skal att köra bash script.sh som kommandoradsargument

Så operativsystemet laddar (inte ens titta på script.sh, för det är bara ett kommandoradsargument). Den skapade bash -processen tolkar sedan script.sh eftersom den skickas som kommandoradsargument. Eftersom script.sh läses endast av bash som en vanlig fil, exekveringsbiten krävs inte.


Jag rekommenderar att du använder ./script.sh, för du kanske inte vet vilken tolk skriptet kräver. Låt programladdaren bestämma det för dig.

Kommentarer

  • Om den körbara biten inte är inställd kan du också köra skriptet genom att göra " ./script.sh"
  • @Dog Du har rätt. Punkt är en genväg för inbyggt kommando ' källa ' , som kör skriptet i den aktuella basprocessen. Så endast den läsbara biten krävs.
  • @Dogeatcatworld medan det är sant, kör . ./script.sh är inte detsamma sak som (eller ./script.sh. Tänk på skriptet #!/usr/bin/python -V < newline > print test.
  • Var uppmärksam på att sourcing av ett skript kan leda till kontaminering av den interaktiva sessionen. Om ett skript till exempel ändrar miljövariabeln PATH, kommer denna ändring att påverka kommandon som körs efter källan. Detta tillvägagångssätt borde verkligen reserveras för situationer där du är beroende av biverkningarna (miljöinställningsskript och liknande). För andra situationer där du inte kan ' t ändra behörigheterna är det säkraste sättet att köra kommandot i shebang-raden, följt av skriptnamnet.
  • , om du köper ett skript i den aktuella katalogen behöver du inte använda ./ ; säg bara . script.sh. Men jag håller med de människor som avskräcker att använda kommandot . på skript som inte var avsedda att åberopas på det sättet. Jag är förvånad över att ingen nämnde att om manuset innehåller exit -kommandon, och du köper det, kan det logga ut dig. Ett mindre svårt problem skulle vara om skriptet gör ett cd, eftersom det också skulle påverka det överordnade (interaktiva) skalet.

Svar

bash script.sh anropar skriptet direkt med bash.
./script.sh använder shebangen #!/bin/bash för att bestämma hur man ska köra.

Om du verkligen vill veta, vilken binär körs om du gör en bash script.sh du kan ta reda på det med which bash.

Så i ditt exempel gör det ingen skillnad. Ja, du måste chmod +x script.sh för att kunna köra det direkt via ./script.sh.

Kommentarer

  • Tja, det gör ingen skillnad förutsatt att /bin/bash är den första bash i din $PATH.
  • Du ' har rätt. Och shebang #!/bin/bash fungerar bara om det finns en /bin/bash
  • Bash (version 4.2.37) på min systemet kör skript även utan exekveringsbituppsättningen. Varför säger du att exekveringsbit krävs?
  • Ja, exekveringsbit behövs bara genom att anropa via ./script.sh.

Svar

Skapa en fil Delete_Self.sh så här:

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

Kör detta skript som sh Delete_Self.sh ser du ”Jag är fortfarande här!” ekade tillbaka.

Gör det körbart och kör det som ./Delete_Self.sh så ser du att inget återkallas medan filen Delete_Self.sh själv är borta.

Så skillnaden är att:

  • bash script.sh ignorerar #! rad, eftersom bash anges som programmet för att köra script.sh.
  • ./script.sh kommer att läsa #! rad för att bestämma programmet som ska köras script.sh.

Kommentarer

  • +1 för det fina exemplet

Svar

Förutom de andra svaren, att veta skillnaden mellan att köra ett skript via ./script.sh (i) och källa ./script.sh (ii) är användbart – (i) -versionen skapar ett nytt skal för att köra kommandot, medan (ii) kör det i det aktuella skalet – vilket kan vara obligatoriskt om den körbara filen ändrar miljövariabler som behöver bevaras efter att den körbara utgången. För att till exempel aktivera en python-conda-miljö måste följande användas:

source activate my_env 

N.B. Ett annat alternativ till source som du kan stöta på är det inbyggda ., dvs

. activate my_env 

Lämna ett svar

Din e-postadress kommer inte publiceras. Obligatoriska fält är märkta *