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 execvepanggilan 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 execvesystem call menggantikan kode dari proses yang sedang berjalan; ada panggilan sistem terpisah forkuntuk 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/interpreterdengan argumen /my/script. Maka terserah untuk /some/interpretermemutuskan bahwa itu /my/scriptadalah 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 execvepanggilan 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 -eprocessmana 1234 adalah PID dari shell.
Dalam bash, mekanisme fallback ini diimplementasikan dengan memanggil forktetapi 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 ENOEXECdengan menelepon /bin/shdengan 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