Ketika skrip shell dimulai #!
, baris pertama itu adalah komentar sejauh menyangkut shell. Namun dua karakter pertama bermakna bagi bagian lain dari sistem: kernel. Dua karakter #!
ini disebut shebang . Untuk memahami peran shebang, Anda perlu memahami bagaimana program dijalankan.
Menjalankan suatu program dari suatu file memerlukan tindakan dari kernel. Ini dilakukan sebagai bagian dari execve
panggilan sistem. Kernel perlu memverifikasi izin file, membebaskan sumber daya (memori, dll.) Yang terkait dengan file yang dapat dieksekusi yang saat ini berjalan dalam proses panggilan, mengalokasikan sumber daya untuk file yang dapat dieksekusi yang baru, dan mentransfer kontrol ke program baru (dan lebih banyak hal yang Saya tidak akan menyebutkan). The execve
system call menggantikan kode dari proses yang sedang berjalan; ada panggilan sistem terpisah fork
untuk membuat proses baru.
Untuk melakukan ini, kernel harus mendukung format file yang dapat dieksekusi. File ini harus berisi kode mesin, diatur sedemikian rupa sehingga kernel mengerti. Script shell tidak mengandung kode mesin, jadi tidak bisa dijalankan dengan cara ini.
Mekanisme shebang memungkinkan kernel untuk menunda tugas menafsirkan kode ke program lain. Ketika kernel melihat bahwa file yang dapat dieksekusi dimulai #!
, ia membaca beberapa karakter berikutnya dan menginterpretasikan baris pertama dari file tersebut (minus ruang memimpin #!
dan opsional) sebagai jalur ke file lain (ditambah argumen, yang tidak akan saya bahas di sini ). Ketika kernel diberitahu untuk mengeksekusi file /my/script
, dan ia melihat bahwa file dimulai dengan baris #!/some/interpreter
, kernel mengeksekusi /some/interpreter
dengan argumen /my/script
. Maka terserah untuk /some/interpreter
memutuskan bahwa itu /my/script
adalah file skrip yang harus dijalankan.
Bagaimana jika suatu file tidak mengandung kode asli dalam format yang dimengerti oleh kernel, dan tidak dimulai dengan shebang? Nah, maka file tidak dapat dieksekusi, dan execve
panggilan sistem gagal dengan kode kesalahan ENOEXEC
(Executable format error).
Ini bisa menjadi akhir dari cerita, tetapi sebagian besar shell menerapkan fitur mundur. Jika kernel kembali ENOEXEC
, shell melihat isi file dan memeriksa apakah itu terlihat seperti skrip shell. Jika shell mengira file tersebut terlihat seperti skrip shell, ia menjalankannya dengan sendirinya. Rincian cara melakukannya tergantung pada shell. Anda dapat melihat sebagian dari apa yang terjadi dengan menambahkan ps $$
skrip Anda, dan lebih banyak lagi dengan menyaksikan proses dengan di strace -p1234 -f -eprocess
mana 1234 adalah PID dari shell.
Dalam bash, mekanisme fallback ini diimplementasikan dengan memanggil fork
tetapi tidak execve
. Proses bash anak membersihkan keadaan internalnya sendiri dan membuka file skrip baru untuk menjalankannya. Oleh karena itu proses yang menjalankan skrip masih menggunakan gambar kode bash asli dan argumen baris perintah asli berlalu ketika Anda memanggil bash pada awalnya. ATT ksh berperilaku dengan cara yang sama.
% bash --norc
bash-4.3$ ./foo.sh
PID TTY STAT TIME COMMAND
21913 pts/2 S+ 0:00 bash --norc
Dash, sebaliknya, bereaksi ENOEXEC
dengan menelepon /bin/sh
dengan jalur ke skrip yang diteruskan sebagai argumen. Dengan kata lain, ketika Anda menjalankan skrip shebangless dari dash, berperilaku seolah-olah skrip tersebut memiliki garis shebang #!/bin/sh
. Mksh dan zsh berperilaku dengan cara yang sama.
% dash
$ ./foo.sh
PID TTY STAT TIME COMMAND
21427 pts/2 S+ 0:00 /bin/sh ./foo.sh