Apa perbedaan antara menjalankan "bash script.sh" dan "./script.sh"?

42

Jika script.sh hanyalah sesuatu yang khas seperti

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

Apakah ada cara yang disukai untuk menjalankan skrip? Saya pikir Anda pertama-tama harus chmod sehingga menjadi dieksekusi?

user72136
sumber

Jawaban:

56

Untuk skrip spesifik Anda, cara apa pun akan berfungsi, kecuali yang ./script.shmembutuhkan eksekusi dan bit yang dapat dibaca, sementara bash script.shhanya membutuhkan bit yang dapat dibaca.


Alasan perbedaan persyaratan izin terletak pada bagaimana program yang menginterpretasikan skrip Anda dimuat:

  • ./script.sh membuat shell Anda menjalankan file seolah-olah itu adalah executable biasa.

Shell execvebercabang sendiri dan menggunakan panggilan sistem (mis. ) Untuk membuat sistem operasi menjalankan file dalam proses bercabang. Sistem operasi akan memeriksa izin file (maka bit eksekusi perlu diatur) dan meneruskan permintaan ke program loader , yang melihat file dan menentukan bagaimana cara mengeksekusinya. Di Linux yang dapat dikompilasi executable mulai dengan angka ajaib ELF , sedangkan skrip mulai dengan #!( hashbang ). Header hashbang berarti bahwa file tersebut adalah skrip dan perlu ditafsirkan oleh program yang ditentukan setelah hashbang. Ini memungkinkan skrip itu sendiri untuk memberi tahu sistem cara menafsirkan skrip.

Dengan skrip Anda, program loader akan mengeksekusi /bin/bashdan lulus ./script.sh sebagai argumen baris perintah.

  • bash script.shmenjadikan shell Anda berjalan bashdan lulus script.shsebagai argumen baris perintah

Jadi sistem operasi akan memuat bash(bahkan tidak melihat script.sh, karena itu hanya argumen baris perintah). Proses yang dibuat bashkemudian akan menafsirkan script.shkarena dilewatkan sebagai argumen baris perintah. Karena script.shhanya dibaca bashsebagai file biasa, bit eksekusi tidak diperlukan.


Saya sarankan menggunakan ./script.sh, karena Anda mungkin tidak tahu juru bahasa mana yang membutuhkan skrip. Jadi biarkan program loader menentukannya untuk Anda.

SkyDan
sumber
3
Jika bit yang dapat dieksekusi tidak disetel, Anda juga dapat menjalankan skrip dengan melakukan "./script.sh"
Dog eat cat world
1
@ Anjing Anda benar. Titik adalah pintasan untuk 'sumber' perintah bawaan, yang menjalankan skrip dalam proses bash saat ini. Jadi hanya bit yang bisa dibaca yang diperlukan.
SkyDan
5
@Dogeatcatworld sementara itu benar, menjalankan . ./script.shbukan hal yang sama dengan bash script.sh(atau ./script.sh. Pertimbangkan skrip #!/usr/bin/python -V<newline> print test.
casey
12
Berhati-hatilah bahwa sumber skrip dapat mengakibatkan kontaminasi sesi interaktif. Misalnya, jika skrip mengubah variabel lingkungan PATH, perubahan ini akan memengaruhi perintah yang dijalankan mengikuti sumber. Pendekatan ini harus benar-benar dicadangkan untuk situasi di mana Anda bergantung pada efek samping (skrip pengaturan lingkungan dan sejenisnya). Untuk situasi lain di mana Anda tidak dapat mengubah izin, menjalankan perintah di baris shebang, mengikuti dengan nama skrip adalah pendekatan yang paling aman.
ctt
6
Perhatikan bahwa, jika Anda sumber skrip di direktori saat ini, Anda tidak perlu menggunakan ./ ; katakan saja . script.sh. Tapi saya setuju dengan orang-orang yang tidak suka menggunakan .perintah pada skrip yang tidak dimaksudkan seperti itu. Saya terkejut bahwa tidak ada yang menyebutkan bahwa, jika skrip berisi exitperintah, dan Anda sumbernya, itu bisa mengeluarkan Anda. Masalah yang kurang mengerikan adalah jika skrip melakukan cd, karena itu juga akan mempengaruhi shell induk (interaktif).
Scott
18

bash script.shmeminta skrip secara langsung menggunakan bash.
./script.shmenggunakan shebang #!/bin/bashuntuk menentukan bagaimana mengeksekusi.

Jika Anda benar-benar ingin tahu, biner mana yang dijalankan jika Anda melakukannya, bash script.shAnda bisa mengetahuinya which bash.

Jadi, dalam contoh Anda itu tidak ada bedanya. Ya, Anda harus chmod +x script.shdapat menjalankannya langsung melalui ./script.sh.

xx4h
sumber
2
Yah, tidak ada bedanya dengan menganggap itu /bin/bashadalah yang pertama bashdi Anda $PATH.
cjm
Kamu benar. Dan shebang #!/bin/bashhanya berfungsi jika ada/bin/bash
xx4h
Bash (versi 4.2.37) pada sistem saya menjalankan skrip bahkan tanpa bit eksekusi. Mengapa Anda mengatakan bit eksekusi diperlukan?
SkyDan
Ya, bit eksekusi hanya diperlukan dengan memanggil via ./script.sh.
xx4h
4

Buat file Delete_Self.sh seperti ini:

 #!/bin/rm

 echo I am still here!

Jalankan skrip ini karena sh Delete_Self.shAnda akan melihat "Saya masih di sini!" bergema kembali.

Jadikan itu dapat dieksekusi, dan jalankan karena ./Delete_Self.shAnda akan melihat tidak ada yang digaungkan kembali, sementara file Delete_Self.shitu sendiri hilang.

Jadi perbedaannya adalah:

  • bash script.shakan mengabaikan #! baris, karena bash ditentukan sebagai program untuk menjalankan script.sh.
  • ./script.shakan membaca #! baris untuk menentukan program yang akan dijalankan script.sh.
David
sumber
+1 untuk contoh yang bagus
ThisaruG
1

Selain jawaban lain, mengetahui perbedaan antara menjalankan skrip melalui ./script.sh(i) dan sumber ./script.sh(ii) berguna - Versi (i) membuat shell baru untuk menjalankan perintah, sedangkan (ii) menjalankannya di shell saat ini - yang dapat diwajibkan jika executable mengubah variabel lingkungan yang perlu dipertahankan setelah keluar executable. Misalnya, untuk mengaktifkan lingkungan python conda, berikut ini harus digunakan:

source activate my_env

NB Alternatif lain sourceyang mungkin Anda temui adalah .builtin, yaitu

. activate my_env
einonm
sumber