Care este diferența dintre rularea “ bash script.sh ” și “ ./script .sh ”?

Dacă script.sh este doar ceva tipic ca

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

Există o opțiune preferată modalitate de a rula scriptul? Cred că mai întâi trebuie să-l modificați, astfel încât să devină executabil?

Răspuns

Pentru scriptul dvs. specific, oricare dintre moduri va funcționa, cu excepția că ./script.sh necesită execuție și biți lizibili, în timp ce bash script.sh necesită numai biți lizibili.


Motivul diferența de cerință a permisiunilor constă în modul în care este încărcat programul care interpretează scriptul dvs.:

  • ./script.sh face ca shell-ul dvs. să ruleze fișierul ca și cum ar fi fost un lucru obișnuit executabil.

Shell-ul se bifurcă singur și folosește un apel de sistem (de ex. execve) pentru a face ca sistemul de operare să execute fișierul în procesul bifurcat. Sistemul de operare va verifica permisiunile fișierului (prin urmare, bitul de execuție trebuie setat) și va transmite solicitarea către programul de încărcare , care privește fișierul și determină cum să-l execute. În Linux executabilele compilate încep cu un număr ELF , în timp ce scripturile încep cu un #! ( hashbang ). Un antet hashbang înseamnă că fișierul este un script și trebuie interpretat de programul specificat după hashbang. Acest lucru permite un script pentru a spune sistemului cum să interpreteze scriptul.

Cu scriptul dvs., programul de încărcare va executa /bin/bash și va trece ./script.sh ca argument al liniei de comandă.

  • bash script.sh face ca shell-ul dvs. să ruleze bash script.sh ca argument al liniei de comandă

Deci sistemul de operare va încărca (nici măcar nu ne uităm la script.sh, deoarece este doar un argument din linia de comandă). Procesul bash creat va interpreta apoi script.sh deoarece este trecut ca argument al liniei de comandă. Deoarece script.sh este citit doar de bash ca fișier obișnuit, bitul de execuție nu este necesar.


Vă recomand să utilizați ./script.sh, totuși, pentru că este posibil să nu știți ce interpret are nevoie de script. Deci, lăsați programul de încărcare să vă determine acest lucru.

Comentarii

  • Dacă bitul executabil nu este setat, puteți rula și scriptul făcând ". ./script.sh"
  • @Dog Ai dreptate. Punctul este o comandă rapidă pentru comanda încorporată ' sursă ' , care rulează scriptul în procesul bash curent. Deci, este necesar doar bitul lizibil.
  • @Dogeatcatworld în timp ce este adevărat, rularea . ./script.sh nu este aceeași lucru ca (sau ./script.sh. Luați în considerare scriptul #!/usr/bin/python -V < newline > print test.
  • Feriți-vă că obținerea unui script ar putea duce la contaminarea sesiunii interactive. De exemplu, dacă un script modifică variabila de mediu PATH, această modificare va afecta comenzile executate după sursă. Această abordare ar trebui cu adevărat rezervată pentru situațiile în care depindeți de efectele secundare (scripturi de configurare a mediului și altele asemenea). Pentru alte situații în care nu puteți ' t schimba permisiunile, executarea comenzii în linia shebang, urmând numele scriptului este cea mai sigură abordare.
  • Rețineți că , dacă sursați un script în directorul curent, nu este necesar să utilizați ./ ; spune doar . script.sh. Dar sunt de acord cu persoanele care descurajează utilizarea comenzii . pe scripturi care nu au fost menite să fie invocate în acest fel. Sunt surprins că nimeni nu a menționat că, dacă scriptul conține comenzi exit și îl veți obține, acesta vă poate deconecta. O problemă mai puțin gravă ar fi dacă scriptul face un cd, deoarece acest lucru ar afecta și shell-ul părinte (interactiv).

Răspuns

bash script.sh invocă scriptul direct folosind bash.
./script.sh folosește shebang #!/bin/bash pentru a determina cum să execute.

Dacă vrei cu adevărat să știi, ce binar este executat dacă faci un ați putea afla cu which bash.

Deci, în exemplul dvs., nu are nicio diferență. Da, trebuie să chmod +x script.sh pentru a o putea executa direct prin ./script.sh.

Comentarii

  • Ei bine, nu are nicio diferență presupunând că /bin/bash este primul bash în $PATH.
  • Ai ' dreptate. Și shebang #!/bin/bash funcționează numai dacă există un /bin/bash
  • Bash (versiunea 4.2.37) pe sistemul execută scripturi chiar și fără setul de biți de execuție. De ce spuneți că este necesar bitul de execuție?
  • Da, bitul de execuție este necesar doar prin invocarea prin ./script.sh.

Răspuns

Creați un fișier Delete_Self.sh astfel:

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

Rulați acest lucru script ca sh Delete_Self.sh veți vedea „Sunt încă aici!” ecou înapoi.

Faceți-l executabil și rulați-l ca ./Delete_Self.sh veți vedea că nu se repetă nimic în timp ce fișierul Delete_Self.sh în sine a dispărut.

Deci, diferența este că:

  • bash script.sh va ignora #! line, deoarece bash este specificat ca program pentru a rula script.sh.
  • ./script.sh va citi #! linie pentru a determina programul de rulat script.sh.

Comentarii

  • +1 pentru frumosul exemplu

Răspuns

Pe lângă celelalte răspunsuri, știind diferența dintre rularea unui script prin ./script.sh (i) și sursa ./script.sh (ii) este utilă – Versiunea (i) creează un nou shell în care se execută comanda, întrucât (ii) îl rulează în shell-ul curent – care poate fi obligatoriu dacă executabilul modifică variabilele de mediu care trebuie păstrate după ieșirea executabilului. De exemplu, pentru a activa un mediu conda python trebuie să se utilizeze următoarele:

source activate my_env 

N.B. O altă alternativă la source pe care o puteți întâlni este . integrat, adică

. activate my_env 

Lasă un răspuns

Adresa ta de email nu va fi publicată. Câmpurile obligatorii sunt marcate cu *