Karena file tersebut bukan tipe yang dapat dieksekusi yang dikenali oleh sistem, dan dengan asumsi Anda memiliki izin untuk mengeksekusi file itu, execve()
panggilan sistem biasanya akan gagal dengan kesalahan ENOEXEC
( bukan yang dapat dieksekusi ).
Apa yang terjadi kemudian tergantung pada fungsi aplikasi dan / atau perpustakaan yang digunakan untuk menjalankan perintah.
Itu bisa berupa shell, fungsi execlp()
/ execvp()
libc.
Sebagian besar aplikasi lain akan menggunakan salah satu dari mereka ketika mereka menjalankan perintah. Mereka akan memanggil shell misalnya dengan menggunakan system("command line")
fungsi libc yang biasanya akan memanggil sh
untuk mem-parsing baris perintah itu (jalur yang dapat ditentukan pada waktu kompilasi (seperti /bin/sh
vs /usr/xpg4/bin/sh
pada Solaris)), atau memanggil shell yang disimpan dalam $SHELL
dirinya sendiri seperti vi
dengan !
perintahnya, atau xterm -e 'command line'
dan banyak perintah lainnya ( su user -c
akan meminta shell login pengguna alih-alih $SHELL
).
Secara umum, file teks tanpa-shebang yang tidak dimulai #
dianggap sebagai sh
skrip. Yang sh
itu akan bervariasi.
execlp()
/ execvp()
, setelah execve()
kembali ENOEXEC
biasanya akan memintanya sh
. Untuk sistem yang memiliki lebih dari satu sh
karena mereka dapat memenuhi lebih dari satu standar, yang sh
biasanya akan ditentukan pada waktu kompilasi (dari aplikasi menggunakan execvp()
/ execlp()
dengan menghubungkan gumpalan kode yang berbeda yang merujuk ke jalur yang berbeda dengan sh
). Sebagai contoh, pada Solaris, itu akan menjadi /usr/xpg4/bin/sh
(standar, POSIX sh
) atau /bin/sh
(cangkang Bourne (cangkang kuno) pada Solaris 10 dan lebih lama, ksh93 dalam Solaris 11).
Ketika datang ke kerang, ada banyak variasi. bash
, AT&T ksh
, shell Bourne biasanya akan menafsirkan skrip itu sendiri (dalam proses anak kecuali exec
digunakan) setelah mensimulasikan a execve()
, yang tidak mengatur semua variabel yang tidak diekspor, menutup semua fds close-on-exec, menghapus semua jebakan kustom, alias, fungsi ... ( bash
akan menafsirkan skrip dalam sh
mode). yash
akan mengeksekusi sendiri (dengan mode sh
seperti argv[0]
dalam sh
) untuk menafsirkannya.
zsh
, pdksh
, ash
Kerang berbasis biasanya akan memanggil sh
(jalur yang ditentukan pada saat kompilasi).
Untuk csh
dan tcsh
(dan sh
beberapa BSD awal), jika karakter pertama file tersebut #
, maka mereka akan mengeksekusi sendiri untuk menafsirkannya, dan sh
sebaliknya. Yang kembali ke waktu pre-peristiwa di mana csh
tidak mengakui #
sebagai komentar tapi tidak Bourne shell, sehingga #
merupakan petunjuk bahwa ia adalah script csh.
fish
(setidaknya versi 2.4.0), baru saja mengembalikan kesalahan jika execve()
gagal (tidak mencoba memperlakukannya sebagai skrip).
Beberapa shell (suka bash
atau AT&T ksh
) pertama-tama akan mencoba untuk menentukan apakah file tersebut dimaksudkan sebagai skrip atau tidak. Jadi Anda mungkin menemukan bahwa beberapa shell akan menolak untuk mengeksekusi skrip jika ada karakter NUL di beberapa byte pertama.
Juga perhatikan bahwa jika execve()
gagal dengan ENOEXEC tetapi file tersebut memang memiliki garis shebang, beberapa shell mencoba menafsirkan garis shebang itu sendiri.
Jadi beberapa contoh:
- Ketika
$SHELL
adalah /bin/bash
, xterm -e 'myscript with args'
akan myscript
ditafsirkan oleh bash
di sh
modus. Sementara dengan xterm -e myscript with args
, xterm
akan digunakan execvp()
sehingga skrip akan ditafsirkan oleh sh
.
su -c myscript
pada Solaris 10 di mana root
shell login adalah /bin/sh
dan /bin/sh
shell Bourne akan myscript
ditafsirkan oleh shell Bourne.
/usr/xpg4/bin/awk 'BEGIN{system("myscript")'
pada Solaris 10 akan ditafsirkan oleh /usr/xpg4/bin/sh
(sama untuk /usr/xpg4/bin/env myscript
).
find . -prune -exec myscript {} \;
pada Solaris 10 (menggunakan execvp()
) akan menafsirkannya /bin/sh
bahkan dengan /usr/xpg4/bin/find
, bahkan dalam lingkungan POSIX (bug kepatuhan).
csh -c myscript
akan menafsirkannya csh
jika dimulai dengan #
, dengan sh
sebaliknya.
Secara keseluruhan, Anda tidak dapat memastikan shell apa yang akan digunakan untuk menafsirkan skrip itu jika Anda tidak tahu bagaimana dan oleh apa itu akan dipanggil.
Dalam kasus apa pun, read -p
ini adalah bash
hanya sintaks, jadi Anda harus memastikan bahwa skrip diinterpretasikan oleh bash
(dan menghindari .sh
ekstensi yang menyesatkan ). Entah Anda tahu jalur yang bash
dapat dieksekusi dan gunakan:
#! /path/to/bash -
read -p ...
Atau Anda dapat mencoba dan mengandalkan $PATH
pencarian yang bash
dapat dieksekusi (dengan asumsi bash
diinstal) dengan menggunakan:
#! /usr/bin/env bash
read -p ...
( env
Hampir di mana-mana ditemukan di /usr/bin
). Atau, Anda dapat membuatnya POSIX + Bourne kompatibel dalam hal ini Anda dapat menggunakan /bin/sh
. Semua sistem akan memiliki /bin/sh
. Pada sebagian besar dari mereka itu akan (sebagian besar) kompatibel dengan POSIX, tetapi Anda mungkin masih menemukan shell Bourne di sana.
#! /bin/sh -
printf >&2 'Enter a user name: '
read user
printf '%s\n' "$user"