Tujuan dari pertanyaan ini adalah untuk menjawab rasa ingin tahu, bukan untuk memecahkan masalah komputasi tertentu. Pertanyaannya adalah: Mengapa utilitas wajib POSIX tidak umum dibangun ke dalam implementasi shell?
Sebagai contoh, saya memiliki skrip yang pada dasarnya membaca beberapa file teks kecil dan memeriksa apakah mereka diformat dengan benar, tetapi butuh 27 detik untuk menjalankan, pada mesin saya, karena sejumlah besar manipulasi string. Manipulasi string ini membuat ribuan proses baru dengan memanggil berbagai utilitas, karenanya lambat. Saya cukup yakin bahwa jika beberapa utilitas dibangun di, yaitu grep
, sed
, cut
, tr
, dan expr
, maka script akan berjalan dalam satu detik atau kurang (berdasarkan pengalaman saya di C).
Tampaknya akan ada banyak situasi di mana membangun utilitas ini akan membuat perbedaan antara apakah solusi dalam skrip shell memiliki kinerja yang dapat diterima.
Jelas, ada alasan mengapa itu tidak membuat utilitas ini terintegrasi. Mungkin memiliki satu versi utilitas pada tingkat sistem menghindari memiliki beberapa versi yang tidak sama dari utilitas yang digunakan oleh berbagai shell. Saya benar-benar tidak dapat memikirkan banyak alasan lain untuk menjaga overhead menciptakan begitu banyak proses baru, dan POSIX mendefinisikan cukup tentang utilitas sehingga sepertinya tidak banyak masalah untuk memiliki implementasi yang berbeda, asalkan mereka masing-masing POSIX sesuai. Setidaknya tidak sebesar masalah seperti inefisiensi memiliki begitu banyak proses.
printf
, dll) telah dimasukkan ke dalam shell ketika mereka dianggap cukup berguna.awk
adalah utilitas wajib di POSIX, dan terutama juga cocok (yaitu, sangat cepat) untuk menerapkan skrip yang mungkin Anda menerapkan menggunakansed
,cut
,tr
,grep
, danexpr
dalam shell script.Jawaban:
Script shell tidak diharapkan berjalan dengan kecepatan seperti itu. Jika Anda ingin meningkatkan kecepatan skrip Anda, cobalah dalam perl. Jika itu masih terlalu lambat, maka Anda harus pindah ke bahasa yang diketik secara statis seperti java atau c, atau menulis modul C untuk perl yang menjalankan bagian-bagian yang terlalu lambat.
Shell adalah level pertama dari prototyping, jika Anda dapat membuktikan konsep dengan shell, kemudian pindah ke bahasa scripting yang lebih baik yang dapat melakukan lebih banyak batasan memeriksa yang akan mengambil acre of shell.
OS Unix diharapkan mencakup banyak program kecil yang melakukan tugas yang terdefinisi dengan baik yang membentuk gambaran yang lebih besar. Ini adalah hal yang baik karena ia menggabungkan program yang lebih besar. Lihatlah qmail, misalnya dan bandingkan dengan sendmail. qmail dibuat dari banyak program:
http://www.nrg4u.com/qmail/the-big-qmail-picture-103-p1.gif
Mengeksploitasi daemon jaringan tidak akan membantu Anda mengeksploitasi manajer antrian.
sumber
cd
ataupwd
.cd
adalah builtin - dan itu sebenarnya harus, karena mengubah direktori kerja dalam subproses tidak mempengaruhi proses induk.Karena memenuhi POSIX, sebuah sistem diperlukan 1 untuk menyediakan sebagian besar utilitas sebagai perintah mandiri.
Memiliki mereka builtin akan menyiratkan mereka harus ada di dua lokasi berbeda, di dalam cangkang dan di luarnya. Tentu saja, akan mungkin untuk mengimplementasikan versi eksternal dengan menggunakan pembungkus skrip shell ke builtin, tetapi itu akan merugikan aplikasi non shell yang memanggil utilitas.
Perhatikan bahwa BusyBox mengambil jalur yang Anda sarankan dengan menerapkan banyak perintah secara internal, dan menyediakan varian mandiri menggunakan tautan ke dirinya sendiri. Satu masalah adalah ketika set perintah bisa sangat besar, implementasinya sering merupakan bagian dari standar sehingga tidak sesuai.
Perhatikan juga bahwa setidaknya
ksh93
,bash
danzsh
melangkah lebih jauh dengan menyediakan metode khusus untuk menjalankan shell untuk secara dinamis memuat builtin dari pustaka bersama. Secara teknis, tidak ada yang mencegah semua utilitas POSIX untuk diimplementasikan dan tersedia sebagai builtin.Akhirnya, memunculkan proses baru telah menjadi operasi yang cukup cepat dengan OS modern. Jika Anda benar-benar terkena masalah kinerja, mungkin ada beberapa perbaikan untuk membuat skrip Anda berjalan lebih cepat.
1 POSIX.1-2008
sumber
fork
tidak diikuti olehexec
;fork
saat ini merupakan operasi yang sangat ringan dibandingkan denganexec
.nofork
builtins memiliki urutan 10x lebih sedikit overhead daripadanoexec
builtin, yang pada gilirannya memiliki ~ 5x lebih sedikit overhead daripada fork + exec dari biner yang terpisah. Definisi sesuai unix.stackexchange.com/a/274322/29483 Sangat menarik bahwa busybox bukannofork
segalanya, meskipun saya tahu beberapa kode busybox dipersingkat dengan tidak membersihkan memori, dan hanya mengandalkan proses yang berumur pendek.Dari manual referensi BASH ,
Seperti yang saya yakin Anda pernah dengar, filosofi UNIX sangat bergantung pada beberapa aplikasi yang semuanya memiliki fungsi terbatas. Setiap built-in memiliki alasan yang sangat bagus mengapa itu built-in. Yang lainnya tidak. Saya pikir kelas yang lebih menarik dari pertanyaan adalah sepanjang baris, "mengapa sebenarnya adalah
pwd
built-in?"sumber
cd
akan menjadi contoh yang lebih baik di sini tentang sesuatu yang tidak mungkin diimplementasikan sebagai alat yang terpisah.cd
harus dibangun di dalam,pwd
tidak. Jadi mengapabash
pelaksana memilih untuk memasukkannya?/bin/bash
memang ada, tetapi masih builtin. Lihat daftar builtin di gnu.org/software/bash/manual/html_node/…Orang-orang di AT&T bertanya pada diri sendiri hal yang sama
Jika Anda melihat sejarah AT&T Software Toolkit (saat ini tidak aktif di github sejak tim inti pergi), ini persis seperti yang mereka lakukan dengan AT&T Korn shell, alias ksh93.
Kinerja selalu menjadi bagian dari motivasi bagi pengelola ksh93, dan ketika membangun ksh Anda dapat memilih untuk membangun banyak utilitas POSIX umum sebagai perpustakaan yang dimuat secara dinamis. Dengan mengikat perintah-perintah ini ke nama direktori seperti
/opt/ast/bin
, Anda bisa mengontrol versi perintah mana yang akan digunakan, berdasarkan posisi nama direktori itu di$PATH
.Contoh:
Daftar lengkapnya dapat ditemukan di repositori github ast .
Perhatikan bahwa sebagian besar alat ast memiliki asalnya sendiri dan akan sangat berbeda dari implementasi gnu yang lebih umum. Tim Riset AT&T mematuhi standar resmi, yang merupakan cara untuk mencapai interoperabilitas ketika Anda tidak dapat berbagi kode.
sumber
Jadi kami tidak mengerahkan sumber daya untuk mengoptimalkan alat asli, untuk memenuhi setiap keinginan tertentu. Saya kira yang perlu kita jelaskan adalah berapa banyak keinginan spesifik ini akan membutuhkan biaya untuk diimplementasikan.
ini asumsi yang buruk :-P.
Sistem Post-POSIX terus menjadi lebih kuat dan nyaman untuk alasan yang baik; sebagai standar setelah-fakta itu tidak pernah benar-benar mengejar ketinggalan.
Ubuntu memulai upaya untuk beralih ke shell POSIX stript-down untuk skrip, untuk mengoptimalkan proses boot init System V lama. Saya tidak mengatakan itu gagal, tetapi itu memicu banyak bug yang harus dibersihkan: "bashisms", skrip yang berjalan di bawah
/bin/sh
sambil mengasumsikan bahwabash
fitur tersedia.POSIX sh bukan bahasa pemrograman serba guna yang bagus. Tujuan utamanya adalah bekerja dengan baik sebagai shell interaktif. Segera setelah Anda mulai menyimpan perintah ke skrip, ketahuilah bahwa Anda mendekati Turing tarpit . Misalnya tidak mungkin mendeteksi kegagalan di tengah pipa normal .
bash
ditambahkanset -o pipefail
untuk ini, tetapi ini bukan di POSIX.Fitur serupa yang bermanfaat namun tidak standar disediakan oleh hampir setiap utilitas yang lebih kompleks daripada
true
.Untuk kelas tugas yang Anda uraikan, Anda dapat menggambar garis kasar ke Awk, Perl, dan saat ini Python. Berbagai alat diciptakan, dan berkembang secara independen. Apakah Anda berharap mis. GNU Awk dimasukkan ke dalam libutilposixextended?
Saya tidak mengatakan bahwa sekarang kita memiliki satu pendekatan yang secara universal lebih baik, saya bisa mengarahkan Anda. Saya punya titik lemah untuk Python. Awk secara mengejutkan sangat kuat, walaupun saya telah frustrasi dengan beberapa fitur yang khusus untuk GNU Awk. Tetapi intinya adalah bahwa memproses sejumlah besar string secara individual (mungkin dari baris file) bukanlah tujuan desain dari shell POSIX.
sumber
cat -@fnord foo
shell harus memutuskan bahwa karena tidak tahu apa-@
artinya itu perlu menjalankan perintah yang sebenarnya, tetapi mengingat hanyacat <foo >bar
shell seharusnya tidak perlu menelurkan proses lain.Ada juga pertanyaan tentang: Di shell mana Anda akan membuatnya?
Sebagian besar sistem Unix / Linux memiliki banyak cangkang berbeda yang dikembangkan secara independen (sh / bash / korn / ???). Jika Anda membuat alat ke dalam shell, Anda akan berakhir dengan implementasi yang berbeda dari alat-alat ini untuk setiap shell. Ini akan menyebabkan overhead, dan Anda mungkin berakhir dengan berbagai fitur / bug di misalnya grep, tergantung pada shell yang Anda gunakan untuk memintanya.
sumber
Banyak yang menjawab dengan baik. Saya hanya bermaksud memuji jawaban itu. Saya pikir filosofi UNIX adalah bahwa alat harus melakukan satu hal dan melakukannya dengan baik. Jika seseorang mencoba membuat alat yang mencakup semuanya, itu lebih banyak tempat untuk kegagalan. Membatasi fungsionalitas dengan cara ini membuat seperangkat alat yang dapat diandalkan.
Juga, pertimbangkan, jika fungsionalitas seperti sed atau grep dibangun ke dalam shell, apakah akan mudah untuk dipanggil dari baris perintah saat Anda menginginkannya?
Sebagai penutup, pertimbangkan, beberapa fungsi yang Anda inginkan dalam BASH, adalah dalam BASH . Sebagai contoh, kemampuan untuk pencocokan RE dalam BASH diimplementasikan menggunakan operator biner = ~ (lihat Shell Grammar di Halaman Manual untuk lebih lanjut, khususnya, referensi diskusi tentang konstruksi [[]] untuk jika ). Sebagai contoh yang sangat cepat, katakanlah saya sedang mencari file untuk 2 digit hex:
Adapun fungsionalitas seperti sed , lihat di bawah Parameter Ekspansi dalam judul Ekspansi dari halaman manual yang sama. Anda akan melihat banyak hal yang dapat Anda lakukan yang mengingatkan pada sed. Saya paling sering menggunakan sed untuk membuat beberapa jenis subtitusi berubah menjadi teks. Membangun di atas:
Pada akhirnya, apakah yang di atas "lebih baik" daripada?
sumber
Saya kira, ini kecelakaan historis.
Ketika UNIX dibuat pada akhir 1960-an dan awal 1970-an, komputer tidak memiliki memori hampir sebanyak yang mereka lakukan saat ini. Mungkin saja, pada saat itu, untuk mengimplementasikan semua fungsi ini sebagai shell builtin, tetapi karena keterbatasan memori, mereka harus membatasi jumlah fungsionalitas yang dapat mereka terapkan, atau berisiko kehabisan memori dan / atau menukar sampah masalah.
Di sisi lain, dengan mengimplementasikan fungsi yang diberikan sebagai program terpisah, dan dengan membuat dua panggilan sistem yang diperlukan untuk memulai proses baru seringan mungkin, mereka dapat membuat lingkungan skrip yang tidak memiliki masalah tersebut dan yang masih berjalan dengan wajar kecepatan.
Tentu saja, sekali hal-hal itu diimplementasikan sebagai proses yang terpisah, orang akan memulainya dari program yang bukan shell, dan kemudian mereka harus tetap seperti itu, atau tiba-tiba semua perangkat lunak ini mulai rusak.
Itu bukan untuk mengatakan Anda tidak dapat mengimplementasikan beberapa fungsi dua kali, namun, dan memang beberapa shell mengimplementasikan beberapa fungsi yang seharusnya menjadi program eksternal sebagai shell builtin; misalnya, bash mengimplementasikan
echo
perintah sebagai builtin, tetapi ada juga a/usr/bin/echo
sumber