cd
adalah built-in shell yang diamanatkan POSIX :
Jika perintah sederhana menghasilkan nama perintah dan daftar argumen opsional, tindakan berikut harus dilakukan:
- Jika nama perintah tidak mengandung garis miring, langkah pertama yang berhasil dalam urutan berikut akan terjadi:
...
- Jika nama perintah cocok dengan nama utilitas yang tercantum dalam tabel berikut, utilitas itu harus dipanggil.
...
cd
...
- Kalau tidak, perintah harus dicari untuk menggunakan PATH ...
Meskipun ini tidak secara eksplisit mengatakan itu harus built-in, spesifikasi selanjutnya mengatakan, dalam deskripsicd
:
Karena cd mempengaruhi lingkungan eksekusi shell saat ini, ia selalu disediakan sebagai built-in shell biasa.
Dari bash
manual :
Perintah built-in shell berikut ini diwarisi dari Bourne Shell. Perintah-perintah ini diimplementasikan sebagaimana ditentukan oleh standar POSIX.
...
cd
cd [-L|[-P [-e]]] [directory]
Saya kira Anda bisa memikirkan arsitektur di mana cd
tidak harus menjadi builtin. Namun, Anda harus melihat apa yang tersirat built-in. Jika Anda menulis kode khusus di shell untuk melakukan sesuatu untuk beberapa perintah, Anda sudah hampir memiliki builtin. Semakin banyak yang Anda lakukan, semakin baik hanya memiliki builtin.
Sebagai contoh, Anda dapat meminta shell memiliki IPC untuk berkomunikasi dengan subproses, dan akan ada cd
program yang akan memeriksa keberadaan direktori dan apakah Anda memiliki izin untuk mengaksesnya dan kemudian berkomunikasi dengan shell untuk memerintahkannya mengubah direktori. Namun, Anda harus kemudian memeriksa apakah proses berkomunikasi dengan Anda adalah anak-anak (atau membuat alat komunikasi khusus hanya dengan anak-anak, seperti deskriptor file khusus, memori bersama, dll.), Dan jika prosesnya memang benar menjalankan cd
program tepercaya atau yang lainnya. Itu adalah sekaleng cacing.
Atau Anda bisa memiliki cd
program yang membuat chdir
system call, dan memulai shell baru dengan semua variabel lingkungan saat ini diterapkan ke shell baru, dan kemudian membunuh shell induknya (entah bagaimana) ketika dilakukan. 1
Lebih buruk lagi, Anda bahkan dapat memiliki sistem di mana suatu proses dapat mengubah lingkungan proses lain (saya pikir secara teknis Anda dapat melakukan ini dengan para penentang). Namun sistem seperti itu akan sangat, sangat rentan.
Anda akan menemukan diri Anda menambahkan kode lebih banyak dan lebih banyak untuk mengamankan metode seperti itu, dan itu jauh lebih mudah untuk membuatnya menjadi builtin.
Bahwa sesuatu itu executable tidak mencegahnya menjadi builtin. Inti masalah:
echo
dan test
echo
dan test
merupakan utilitas yang diamanatkan POSIX ( /bin/echo
dan /bin/test
). Namun hampir setiap shell populer memiliki builtin echo
dan test
. Demikian pula, kill
builtin yang tersedia sebagai program. Lainnya termasuk:
sleep
(tidak seperti biasa)
time
false
true
printf
Namun, ada beberapa kasus di mana perintah tidak bisa apa-apa selain builtin. Salah satunya adalah cd
. Biasanya, jika path lengkap tidak ditentukan, dan nama perintah cocok dengan yang builtin, fungsi yang cocok dengan perintah itu disebut. Bergantung pada shell, perilaku bawaan dan perilaku yang dapat dieksekusi mungkin berbeda (ini khususnya masalahecho
, yang memiliki perilaku yang sangat berbeda . Jika Anda ingin memastikan perilaku tersebut, lebih baik untuk memanggil yang dapat dieksekusi menggunakan path lengkap, dan mengatur variabel seperti POSIXLY_CORRECT
(bahkan saat itu tidak ada jaminan nyata).
Secara teknis tidak ada yang mencegah Anda menyediakan OS yang juga sebuah shell dan memiliki setiap perintah sebagai builtin. Dekat dengan ujung ekstrem ini adalah BusyBox monolitik . BusyBox adalah biner tunggal, yang (tergantung pada namanya) dapat berperilaku sebagai salah satu dari lebih dari 240 program , termasuk Shell Almquist ( ash
). Jika Anda membatalkan PATH
pengaturan saat menjalankan BusyBox ash
, program yang tersedia di BusyBox masih dapat diakses oleh Anda tanpa menentukan a PATH
. Mereka hampir menjadi builtin shell, kecuali bahwa shell itu sendiri adalah semacam builtin ke BusyBox.
Jika Anda melihat dash
sumbernya, utas eksekusi adalah sesuatu seperti ini (tentu saja, dengan fungsi tambahan yang terlibat ketika pipa dan hal-hal lain digunakan):
main
→ cmdloop
→ evaltree
→evalcommand
evalcommand
lalu gunakan findcommand
untuk menentukan apa perintahnya. Jika itu adalah builtin, maka :
case CMDBUILTIN:
if (spclbltin > 0 || argc == 0) {
poplocalvars(1);
if (execcmd && argc > 1)
listsetvar(varlist.list, VEXPORT);
}
if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) {
if (exception == EXERROR && spclbltin <= 0) {
FORCEINTON;
break;
cmdentry.u.cmd
adalah struct
( struct builtincmd
), yang salah satu anggotanya adalah pointer fungsi, dengan tanda tangan khas main
: (int, char **)
. The evalbltin
fungsi panggilan (tergantung pada apakah builtin adalah eval
perintah atau tidak) baik evalcmd
, atau fungsi pointer ini. Fungsi sebenarnya didefinisikan dalam berbagai file sumber. echo
, misalnya, adalah :
int
echocmd(int argc, char **argv)
{
int nonl;
nonl = *++argv ? equal(*argv, "-n") : 0;
argv += nonl;
do {
int c;
if (likely(*argv))
nonl += print_escape_str("%s", NULL, NULL, *argv++);
if (nonl > 0)
break;
c = *argv ? ' ' : '\n';
out1c(c);
} while (*argv);
return 0;
}
Semua tautan ke kode sumber di bagian ini berbasis nomor baris, sehingga dapat berubah tanpa pemberitahuan.
1 sistem POSIX memang cd
dapat dieksekusi .
Catatan:
Ada banyak posting bagus di Unix & Linux yang berhubungan dengan perilaku shell. Khususnya:
Jika Anda belum melihat pola dalam pertanyaan yang terdaftar sejauh ini, hampir semuanya melibatkan Stéphane Chazelas .
type
perintah