Mengapa POSIX memerlukan built-in shell tertentu untuk memiliki implementasi eksternal?

18

Dari pertanyaan ini tentang apakah printf adalah built-in untuk yash , muncul jawaban yang mengutip standar POSIX .

Jawabannya menunjukkan bahwa urutan pencarian POSIX adalah untuk menemukan implementasi eksternal dari perintah yang diinginkan, dan kemudian, jika shell telah mengimplementasikannya sebagai built-in, jalankan built-in. (Untuk bawaan yang bukan bawaan khusus .)

Mengapa POSIX memiliki persyaratan untuk penerapan eksternal sebelum mengizinkan implementasi internal dijalankan?

Sepertinya ... sewenang-wenang, jadi saya penasaran.

pelajar
sumber
Saya percaya itu adalah cara untuk mengaktifkan / menonaktifkan bawaan jika diinginkan / diperlukan.
Isaac
2
Menonaktifkan built-in dengan menghapus implementasi eksternal? Sekarang tidak ada perintah nama yang printftersedia.
Studog
@studog, jadi buat file kosong dengan nama yang sama dengan built-in, nyalakan bit eksekusi, dan letakkan di direktori di PATH Anda. : P
Wildcard
@Wildcard Cangkang yang benar-benar sesuai akan melihat namanya saat mencari PATHdan kemudian memanggil utilitas bawaan , bukan skrip eksternal. Bagaimana jika Anda ingin memanggil skrip eksternal di jalur Anda? Hmm ... Ini sepertinya membutuhkan tabel yang menjelaskan berbagai kemungkinan yang berbeda. Ada satu di sini , tetapi itu tidak masuk akal bagi saya.
Kusalananda
@ Kusalananda, ulang kalimat pertama Anda, itu poin saya. Karenanya mengapa saya mengatakan untuk membuat file kosong .
Wildcard

Jawaban:

15

Ini adalah aturan "seolah-olah".

Sederhananya: Perilaku shell seperti yang dilihat pengguna tidak boleh berubah jika implementasi memutuskan untuk membuat perintah eksternal standar juga tersedia sebagai shell built-in.

Kontras yang saya perlihatkan di /unix//a/496291/5132 antara perilaku (di satu sisi) PD Korn, MirBSD Korn, dan kerang Heirloom Bourne; (di sisi lain) kerang Z, 93 Korn, Bourne Again, dan Debian Almquist; dan (di genggaman tangan) cangkang Watanabe menyoroti ini.

Untuk shell yang tidak memiliki printfbuilt-in, mengeluarkan /usr/bindari PATHmembuat doa printfberhenti bekerja. Perilaku konforman POSIX, yang diperagakan oleh shell Watanabe dalam mode konformannya, menyebabkan hasil yang sama. Perilaku shell yang memiliki printfbuilt-in adalah seolah-olah menjalankan perintah eksternal.

Sedangkan perilaku semua shell yang tidak sesuai tidak berubah jika /usr/bindihapus dari PATH, dan mereka tidak berperilaku seolah-olah mereka memohon perintah eksternal.

Apa yang standar coba jamin untuk Anda adalah bahwa shell dapat membangun semua jenis perintah eksternal biasanya (atau mengimplementasikannya sebagai fungsi shell sendiri), dan Anda masih akan mendapatkan perilaku yang sama dari built-in seperti yang Anda lakukan dengan perintah eksternal jika Anda menyesuaikan PATHuntuk menghentikan perintah yang ditemukan. PATHtetap menjadi alat Anda untuk memilih dan mengendalikan perintah apa yang dapat Anda panggil.

(Seperti yang dijelaskan di /unix//a/448799/5132 , tahun lalu orang memilih kepribadian Unix mereka dengan mengubah apa yang ada di PATH.)

Orang mungkin berpendapat bahwa membuat perintah selalu berfungsi terlepas dari apakah itu dapat ditemukan pada PATH kenyataannya adalah titik membuat perintah eksternal biasanya built-in. (Itulah sebabnya nosh toolset saya baru saja mendapatkan printenvperintah bawaan di versi 1.38. Meskipun ini bukan shell.)

Tetapi standar memberi Anda jaminan bahwa Anda akan melihat perilaku yang sama untuk perintah eksternal reguler yang tidak aktif PATHdari shell seperti yang Anda lihat dari program non-shell lain yang menjalankan execvpe()fungsi, dan shell tidak akan secara ajaib dapat jalankan (tampaknya) perintah eksternal biasa yang tidak dapat ditemukan oleh program lain dengan yang sama PATH. Semuanya bekerja secara mandiri dari sudut pandang pengguna, dan PATHmerupakan alat untuk mengendalikan cara kerjanya.

Bacaan lebih lanjut

JdeBP
sumber
13

Itu sangat tidak masuk akal dan itu sebabnya tidak ada shell yang mengimplementasikannya dalam mode standarnya.

Dasar pemikiran standar dan contoh yang menggambarkan menunjukkan bahwa ini adalah upaya yang gagal untuk memiliki built-in reguler yang terkait dengan path, dan membiarkan pengguna menimpanya dengan memiliki biner sendiri muncul sebelum itu dalam PATH(misalnya printfbuilt-in yang terkait dengan /usr/bin/printfdapat ditimpa oleh /foo/bin/printfperintah eksternal dengan menetapkan PATH=/foo/bin:$PATH).

Namun, standar itu pada akhirnya tidak mengharuskan itu, tetapi sesuatu yang sama sekali berbeda (dan juga tidak berguna dan tidak terduga).

Anda dapat membaca lebih lanjut tentang hal ini dalam laporan bug ini . Mengutip dari dari teks yang diterima terakhir :

Banyak implementasi yang ada menjalankan built-in reguler tanpa melakukan pencarian PATH. Perilaku ini tidak cocok dengan teks normatif, dan tidak memungkinkan penulis skrip untuk menimpa utilitas bawaan bawaan melalui PATH yang dibuat khusus. Selain itu, alasan menjelaskan bahwa tujuannya adalah untuk memungkinkan penulis untuk menimpa bawaan dengan memodifikasi PATH, tetapi ini bukan apa yang dikatakan teks normatif .

FWIW, saya juga tidak berpikir ada shell yang mengimplementasikan persyaratan yang direvisi dari teks yang diterima.

mosvy
sumber
Lihat juga diskusi di article.gmane.org/gmane.comp.standards.posix.austin.general/… (dan ada beberapa yang lain).
Stéphane Chazelas
Juga github.com/att/ast/issues/370 (panjang)
Stéphane Chazelas
Tidak, (mis. Built-in printf yang terkait dengan / usr / bin / printf dapat ditimpa oleh perintah eksternal / foo / bin / printf dengan mengatur PATH = / foo / bin: $ PATH). , itu tidak benar. Keberadaan salah satu / keduanya / salah satu /usr/bin/printfatau /foo/bin/printfdi PATH akan mengaktifkan printf bawaan . Satu-satunya hal yang eksternal (dalam PATH) yang hilang printfakan lakukan adalah untuk menonaktifkan builtin. (Dengan surat spesifikasi).
Isaac