skrip shell masih berfungsi tanpa #! (sha-bang line)

10

Saya baru mengenal shell script dan banyak buku telah menulis yang menggunakan baris #! (Sha-bang) di awal skrip untuk memanggil penerjemah. Dan ini akan memanggil shell baru untuk skrip dan melakukan interpretasi baris demi baris. Tetapi satu naskah dasar saya masih berjalan tanpa garis ajaib.

jadi pertanyaan saya adalah:

  • dari mana naskah dasar saya mendapatkan penerjemah.
  • bagaimana script berhasil menemukan juru bahasa.

sekarang izinkan saya memberi tahu Anda tentang skrip dasar saya hanya berisi baris berikut:

gema "naskah dasar tanpa garis ajaib"

pengguna1678213
sumber

Jawaban:

3

Jika garis ajaib tidak disediakan, shell default digunakan untuk menjalankan skrip. Shell default ini bisa berupa shell Bourne (sh) yang merupakan kasus dalam beberapa rasa, namun, dalam beberapa rasa lain, shell default yang digunakan sama dengan shell login untuk menjalankannya. Masalahnya adalah: Jangan serahkan pada sistem untuk memutuskan shell, selalu berikan shell yang Anda inginkan di baris pertama.

Guru
sumber
1
yup..mungkin shell saya saat ini menggunakan shell default untuk script shell yang tidak memiliki angka ajaib.
user1678213
1
@ user1678213 Ya, ini shell Anda (dan bukan kernel) yang melakukan ini.
Gilles 'SO- stop being evil'
1
Saya percaya POSIX mengamanatkan bahwa / bin / sh digunakan dalam kasus ini.
vonbrand
2
@vonbrand Ini adalah kesalahpahaman umum. POSIX tidak mengamanatkan shell POSIX menjadi /bin/sh, hanya untuk menjadi shexecutable pertama yang ditemukan saat menjelajahi PATH yang sesuai.
jlliagre
3
Itu tidak benar, tidak pernah "shell masuk" yang digunakan untuk menjalankannya. Apa yang bisa terjadi adalah bahwa shell panggilan (jika skrip dipanggil dari shell) dapat memiliki anak itu sendiri menafsirkannya.
Stéphane Chazelas
8

Ketika Anda menjalankan suatu program, kernel memeriksa apakah itu dimulai dengan beberapa urutan byte ajaib . Jika file yang dapat dieksekusi dimulai dengan #!, kernel menafsirkan sisa baris sebagai nama juru bahasa. Jika file yang dapat dijalankan dimulai dengan \177ELF(di mana \177byte 127), itu memuat file sebagai executable ELF ; itulah jenis normal pada kebanyakan sistem unix saat ini.

Jika kernel tidak mengenali format file, ia menolak untuk mengeksekusi file dan mengembalikan kesalahan ENOEXEC (Exec format error). Ketika shell memperhatikan hal itu, dibutuhkan sendiri untuk menjalankan program sebagai skrip shell.

Untuk menyaksikan ini dalam tindakan, tambahkan beberapa perintah ke skrip Anda:

ps l $$
ls -l /proc/$$/exe
echo hello

(Ini untuk Linux, sesuaikan untuk unix lain.) Kemudian coba jalankan skrip itu dari berbagai shell. Anda akan melihat bahwa beberapa shell memunculkan instance baru untuk mengeksekusi skrip (bash, ksh93) sementara yang lain menelurkan /bin/sh(dash, pdksh, zsh).

Gilles 'SANGAT berhenti menjadi jahat'
sumber
Apa yang saya cari dengan ls -lperintah Anda ? Ini: lrwxrwxrwx 1 i 0 Oct 11 05:15 exe -> /bin/bash-? Jika demikian, apa isinya? Juga, melihat saya punya SHELL=/bin/bashpada env, tapi perubahan itu tampaknya tidak perubahan perilaku. Mungkin itu tidak berhubungan?
Emanuel Berg
sepertinya Anda mengubah variabel shell "SHELL" .jika ya, maka Anda hanya menghitung nilai variabel shell SHELL.it tidak akan mengubah shell Anda. Untuk mengganti shell Anda edit file / etc / passwd.
user1678213
2
@ EmanuelBerg Ya (saya seharusnya menulis ls -l /proc/$$/exe, sebenarnya). The exelink poin ke shell yang mengeksekusi naskah Anda. Saat Anda menjalankan skrip, Anda akan melihat bahwa itu bash yang menafsirkan skrip. Jika Anda menjalankannya dari pdksh misalnya, itu berjalan /bin/sh. Saya tidak tahu ada shell yang menggunakan SHELLvariabel lingkungan atau shell login dalam keadaan itu.
Gilles 'SO- stop being evil'
2
@ user1678213 Mengubah shell dalam /etc/passwdmengubah shell apa yang dieksekusi ketika Anda login melalui SSH atau pada konsol teks. Itu tidak mengubah shell yang mungkin menjalankan skrip.
Gilles 'SO- stop being evil'
2
@ user1678213 Saya memverifikasi apa yang saya tulis di sini dengan menjalankan tes. Tidak satu pun dari shell yang saya uji coba mencari /etc/passwduntuk memutuskan shell mana yang akan digunakan, mereka mengambil forked dari instance mereka sendiri atau dieksekusi /bin/sh.
Gilles 'SO- stop being evil'
-2

Itu mungkin salah satu dari 3 kemungkinan berikut:

  1. Anda memanggil skrip secara langsung dengan penerjemah, IE: bash script.sh

  2. Nama file skrip memiliki ekstensi .sh, yang membuat sistem mencari program default untuk jenis file ini

  3. Lingkungan shell yang Anda gunakan menjalankan 'gema' dengan sendirinya, karena saya hanya bisa menebak bahwa file skrip dapat dieksekusi. Jika, misalnya, Anda akan menggunakan bash shell dan memiliki perintah di file Anda yang hanya digunakan oleh ksh, maka Anda akan melihat bahwa itu tidak akan berfungsi.

Semoga berhasil!

bizna
sumber
3
saya juga tidak menyebutnya dengan bash atau dengan ekstensi apa pun.
user1678213
1
dan shell environment tidak mengeksekusinya karena ketika saya menjalankan perintah ps setelah menjalankan skrip saya. Perintah ps menunjukkan dua proses bash. yang artinya ada dua bash yang berjalan. satu adalah shell login bash saya dan yang lain adalah bash untuk basic_script saya
user1678213
1
2: kernel tidak akan melakukan hal seperti itu. Zsh dapat melakukannya, dan bash dapat diputar untuk melakukannya. 3: Ya, tapi sedikit berbeda di antara cangkang, lihat jawaban saya.
Gilles 'SO- stop being evil'