POSIX zorunlu yardımcı programları neden kabukta yerleşik değil?


45

Bu sorunun amacı, belirli bir bilgisayar problemini çözmemek, merakı cevaplamaktır. Soru şudur: POSIX zorunlu yardımcı programlar neden genellikle kabuk uygulamalarına dahil edilmemiştir?

Örneğin, temelde birkaç küçük metin dosyasını okuyan ve düzgün bir şekilde biçimlendirildiğini kontrol eden bir komut dosyası var, ancak makinemde önemli miktarda dize işleminden dolayı çalıştırılması 27 saniye sürüyor. Bu dize manipülasyonu çeşitli yardımcı programları çağırarak binlerce yeni işlemler yapar, bu nedenle yavaşlık. Ben araçlardan bazıları yani inşa olsaydı bu oldukça eminim grep, sed, cut, tr, ve exprardından komut bir saniye içinde aday olacağını ya da daha az (C deneyimlerime dayanarak).

Bu araçların oluşturulmasının, kabuk betiğindeki bir çözümün kabul edilebilir bir performansa sahip olup olmadığı arasındaki farkı yaratacağı birçok durum olacak gibi görünüyor.

Açıkçası, bu araçları yerleşik hale getirmemek için seçilmesinin bir nedeni var. Belki de bir sistemin bir yardımcı program sürümüne sahip olmak, bu yardımcı programın çeşitli mermiler tarafından kullanılmakta olan eşitsiz versiyonlarının kullanılmasını önler. Gerçekten çok fazla yeni süreç yaratmanın temel yükünü tutmak için başka nedenler düşünemiyorum ve POSIX, her biri POSIX oldukları sürece, farklı uygulamalara sahip olmanın bir sorun gibi görünmediği yararlar hakkında yeterince tanımlıyor Uysal. En azından bu kadar çok sürecin olmayışındaki sorun kadar büyük değil.


15
27 saniye çok yavaşsa, Python, Perl veya başka bir yarı derlenmiş dili kullanabilirsiniz. Alternatif olarak, betiğinizin yavaş kısımlarını yayınlayın ve iyileştirmeler isteyin. Birinin (daha hızlı olanı) yapabileceği üç veya dört komut kullanıyor olabilirsiniz.
roaima

8
Mermiler gerçekten ağır işler için yapılmamıştı, maalesef ve sadece bir kabuk betiği ile kaçabildiğiniz zamanlardan beri dünya çok değişti. Roaima ile aynı fikirdeyim - her makul sysadmin Python veya Perl'e gitmeli ve kabuğun her şeyi halletmesini beklememelidir
Sergiy Kolodyazhnyy

16
Kabuğun birincil amacı, verileri doğrudan işlemek değil diğer programları çalıştırmaktır. Yıllar boyunca, kendileri tarafından sağlanan bazı dış programlar veya özellikler (globbing, aritmetik printf, vb.) Mermi yeterince yararlı oldukları zaman kabuklara dahil edilmiştir.
chepner

8
Komut dosyanızı codereview.stackexchange.com adresine gönderirseniz, hakemlerin komut dosyanızı sert bir şekilde hızlandırmak için bazı önerilerde bulunabileceklerinden emin olabilirsiniz (ya da en azından neden kabuk yerine Python / etc'de yazılması gerektiğine dikkat edin).
chepner

5
@Kyle: awkEğer aksi kullanarak uygulamak olabileceğini komut uygulamak için (çok hızlı olduğunu) POSIX'deki zorunlu aracıdır ve özellikle de uygundur sed, cut, tr, grep, ve exprbir kabuk komut dosyası içinde.
Nominal Hayvan

Yanıtlar:


11

Shell komut dosyalarının bu tür bir hızda çalışması beklenmez. Komut dosyanızın hızını artırmak istiyorsanız, perl olarak deneyin. Bu hala çok yavaşsa, java veya c gibi statik olarak yazılmış bir dile gitmeniz veya çok yavaş parçaları çalıştıran perl için bir C modülü yazmanız gerekir.

Shell, kavramı kabuk ile ispatlayabilirseniz, kabuk dönümünü alabilecek daha fazla sınır kontrolü yapabilen daha iyi bir betik diline geçin.

Unix OS'den daha büyük bir resmi oluşturan iyi tanımlanmış görevleri yapan birçok küçük program içermesi bekleniyor. Bu daha büyük programları bölümlere ayırdığı için iyi bir şey. Örneğin, qmail'e bir göz atın ve bunu sendmail ile karşılaştırın. qmail birçok programdan yapılmıştır:

http://www.nrg4u.com/qmail/the-big-qmail-picture-103-p1.gif

Ağ arka planını kullanmak sıra yöneticisinden yararlanmanıza yardımcı olmaz.


OP özellikle kodun hızını arttırma konusunda önerilerde bulunmadı. Asıl soru, neden bazı kamu kurumlarının cdya da benzeri yapılarda olmadığıydı pwd.
Stephen C

4
Doğru. Cevap, monolitik ve bölümlendirilmiş arasındaki farkı ifade etmek ve bu lehine bir neden göstermek oldu.
Ed Neville


1
@StephenC cdbir yerleşiktir - ve aslında olması gerekir, çünkü alt dizindeki çalışma dizinini değiştirmek üst işlemleri etkilemez.
Jonas

67

POSIX zorunlu yardımcı programları neden kabukta yerleşik değil?

POSIX uyumlu olması için, çoğu yardımcı programı tek başına komut olarak sağlamak için bir sistem gerekir 1 .

Onları inşa ettirmek, onların kabuğun içinde ve dışında iki farklı yerde var olmaları gerektiği anlamına gelir. Tabii ki, harici versiyonun yerleşik yapıya bir kabuk betiği sarmalayıcısı kullanarak uygulanması mümkün olacaktır, ancak bu yardımcı programları arayan kabuk dışı uygulamaları dezavantajlı hale getirecektir.

Not BusyBox dahili olarak birçok komutları uygulayan ve kendisine bağlantıları kullanarak bağımsız varyantı sağlayarak önerilen bir yol seçti. Bir sorun, komut setinin oldukça büyük olmasına rağmen, uygulamalar genellikle standardın bir alt kümesidir, bu yüzden uyumlu değildir.

En azından da unutmayın ksh93, bashve zshpaylaşılan kütüphanelerden dinamik yük yerleşikleri için çalışan kabuk için özel yöntemler sunarak daha ileri gitmek. Teknik olarak, hiçbir şey daha sonra tüm POSIX yardımcı programlarının yerleşik olarak kullanılmasını ve kullanıma sunulmasını engellemez.

Son olarak, yeni işlemlerin ortaya çıkarılması modern işletim sistemleriyle oldukça hızlı bir işlem haline geldi. Gerçekten bir performans sorununa maruz kalırsanız, komut dosyalarınızın daha hızlı çalışmasını sağlamak için bazı iyileştirmeler olabilir.

1 POSIX.1-2008

Ancak, tablodaki normal yerleşikler de dahil olmak üzere tüm standart hizmet programları , Özel Özel Hizmet Programları'nda açıklanan özel dahili bileşenler değil, bunların yürütme ailesi yoluyla erişilebilecek şekilde uygulanmalıdır. POSIX.1-2008 Sistem Arabirimleri hacminde tanımlandığı gibi işlev görür ve doğrudan bunu gerektiren standart yardımcı programlar tarafından çağrılabilir (env, find, nice, nohup, time, xargs).


4
Bu doğru cevap, ancak şunu ekleyeyim, bu araçların arayüzü genellikle zaten stdin / stdout yoluyla olduğu için, her biri aynı zamanda bir bash içerisinde yerleşik bir rutin olarak uygulanmış olsa bile, hala etkili bir şekilde ihtiyaç duyacağını Zaten kendini çatallamak ve her komut için bir boru hattında borular oluşturmak, bu yüzden sadece marjinal kazançlar elde edilebilirdi
Chunko

2
@Chunko Evet. alt kabuklar çatal / yürütülen işlemlerden daha hafiftir.
jlliagre

3
@slebetman Amacımı kaçırıyorsunuz. Alt kabuklar, Linux'ta çalışıp çalışmadıklarına bakılmaksızın, ne iş parçacığı ne de yürütülen işlemlerdir. Altkabuklarda bir tarafından oluşturulan sadece ebeveynlerinin klon vardır fork değil takiben exec; forkgünümüzde kıyasla çok hafif bir işlem exec.
jlliagre

3
Meşgul kutu noforkyerleşiklerini, yerleşiklere göre 10 kat daha az tepegöz sırasına göre noexecölçtüm, bu da sırasıyla çataldan + ayrı bir ikili dosyadan 5 kat daha az yüke sahipti. Unix.stackexchange.com/a/274322/29483 e göre tanımlamalar Meşgul kutununnofork her şeyi yapmaması ilginçtir , ancak ben bir meşgul kutusu kodunun hafızayı temizlememekle kısaltıldığını ve sadece kısa ömürlü bir sürece dayandığını biliyorum.
sourcejedi

1
@jlliagre: Linux'ta bir çatal bir işlem yaratır. Belki de eksik olduğunuz nokta, Linux'ta, geliştiricilerin daha hafif bir şey yaratmanın başka bir avantaj sağlamayacağına karar verdikleri süreçleri o kadar optimize ettikleridir. Temel olarak linux'da bir işlem dişliler kadar hafiftir.
slebetman

9

Gönderen Bash ,

Yerleşik komutlar, işlevleri kullanmak için imkansız ya da ayrı bir yardımcı programla elde etmek için elverişsiz olanı uygulamak için gereklidir.

Duyduğuma göre UNIX felsefesi, kısıtlı işlevselliğe sahip çoklu uygulamalara dayanıyor. Yerleşiklerin her birinin, neden yerleştirildiğinin çok iyi bir nedeni vardır. Diğer her şey değildir. Bence daha ilginç bir soru sınıfı, "neden tam olarak pwd yerleşiktir?"


2
Tek kelimeyle: Modülerlik
Peschke

2
/ bin / pwd var. cdAyrı bir araç olarak uygulanması imkansız olan bir şeye daha iyi bir örnek olacağını düşünüyorum .
Oskar Skog

1
@ OskarSkog Önemli olan buydu. cdyerleşik pwdolması gerekmiyor. Öyleyse uygulayıcılar neden basheklemeyi seçtiler?
Stig Hemmer

1
... kapsadığı zemin olan unix.stackexchange.com/questions/145479 .
JdeBP

@StigHemmer /bin/bashvar, ancak yine de bir yerleşik. Yerleşiklerin
Stephen C

8

AT&T’deki çocuklar da aynı şeyi sordular

Eğer AT&T Software Toolkit'in tarihçesine bakarsanız (şu anda çekirdek takımdan ayrıldığından beri github'da uyumaya devam ediyor), AT&T Korn kabuğu, aka ksh93 ile yaptıkları tam olarak budur.

Performans her zaman ksh93 koruyucular için motivasyonun bir parçasıydı ve ksh oluştururken dinamik olarak yüklenmiş kütüphaneler olarak birçok ortak POSIX yardımcı programı oluşturmayı seçebilirsiniz. Bu komutları benzer bir dizin adına bağlayarak, içindeki dizin adının konumuna /opt/ast/binbağlı olarak komutun hangi sürümünün kullanılacağını kontrol edebilirsiniz $PATH.

Örnekler:

cat chmod chown cksum cmp cp cut date expr fmt head join ln
mkdir mkfifo mktemp mv nl od paste rm tail tr uniq uuencode wc

Tam liste github ast havuzunda bulunabilir.

Ast araçların çoğunun kendi kanıtlarına sahip olduğunu ve daha yaygın gnu uygulamalarından güçlü bir şekilde farklı olacağını unutmayın. AT&T Araştırma ekibi, kodları paylaşamadığınızda birlikte çalışabilirlik elde etmenin yolu olan resmi standartlara uyar.


6

Bu yüzden, her bir özel isteği yerine getirmek için orijinal aracı optimize etmek için kaynakları bir araya getirmedik. Sanırım açıklamamız gereken, bu özel arzunun ne kadar maliyetinin uygulanacağı.

POSIX, farklı uygulamalara sahip olmanın bir sorun gibi görünmediği yardımcı programlar hakkında yeterince tanımlamaktadır.

Bu kötü bir varsayımdır:

POSIX sonrası sistemler iyi nedenlerle daha güçlü ve kullanışlı olmaya devam ediyor; gerçeği takip eden bir standart olarak, asla yakalayamaz.

Ubuntu, eski System V init önyükleme işlemini optimize etmek için komut dosyaları için soyulmuş bir POSIX kabuğuna geçmek için bir çaba başlattı. Başarısız olduğunu söylemiyorum, ancak temizlenmesi gereken birçok hatayı tetikledi: “bashisler”, /bin/shbu bashözelliklerin mevcut olduğunu varsayarak altından geçen komut dosyaları .

POSIX sh, iyi bir genel amaçlı programlama dili değildir. Onun birincil amacı interaktif kabuk yanı çalışmaktır. Komutlarınızı bir komut dosyasına kaydetmeye başlar başlamaz, bir Turing tarpitine yaklaştığınızı unutmayın . Örneğin , normal bir boru hattının ortasındaki arızaları tespit etmek mümkün değildir . bashbunun için eklendi set -o pipefail, ancak bu POSIX’de değil.

Benzer kullanışlı ancak standartlaştırılmamış özellikler, hemen hemen her program tarafından olduğundan daha karmaşık olarak sağlanır true.

Anahat çizdiğiniz görev sınıfı için, Awk, Perl ve bugünlerde Python'a kaba bir çizgi çizebilirsiniz. Farklı araçlar yaratıldı ve bağımsız olarak geliştirildi. Örneğin GNU Awk’ın libutilposixextended içine yerleştirilmesini bekler miydiniz?

Şimdi size evrensel olarak daha iyi bir yaklaşıma sahip olduğumuzu söylemiyorum. Python için yumuşak bir noktam var. Awk şaşırtıcı derecede güçlü, ancak bazı özelliklerin GNU Awk'a özgü olması beni hayal kırıklığına uğrattı. Ancak mesele şu ki, çok sayıda dizeyi tek tek işlemenin (büyük olasılıkla dosyaların satırlarından) işleme POSIX kabuğunun tasarım amacı değildi.


Yapılandırılabilir bir konum listesinden çalıştırılan herhangi bir komutun, kabuğun komutla ilgili her şeyi anladığı durumlarda yerleşik bir işlem olarak kabul edileceğini varsayacak bir kabuk ile ilgili herhangi bir zorluk olup olmadığını merak ediyorum. Bir betik gerçekleştirirse cat -@fnord foo, kabuk karar vermelidir, çünkü -@asıl komutu çağırmanın ne anlama geldiğini bilmediğinden , sadece cat <foo >barkabuğa verilenler başka bir işlemi başlatmaya gerek duymaz.
supercat

1
@supercat karmaşıklığı.
sourcejedi

2

Ayrıca şu soru var: Hangi kabuğa kurarsınız?

Çoğu Unix / Linux sistemi bağımsız olarak geliştirilen birçok farklı mermiye sahiptir (sh / bash / korn / ???). Araçları kabuğun içine yerleştirirseniz, bu kabukların her kabuk için farklı bir uygulaması ile sonuçlanırsınız. Bu, ek yüke neden olur ve onu kullanmak için hangi kabuğu kullandığınıza bağlı olarak örneğin grep'te farklı özellikler / hatalarla karşılaşabilirsiniz.


zsh bugünlerde bazı çevrelerde oldukça popüler. csh / tcsh'ın tarihsel olarak büyük bir takipçisi oldu, ancak bugün çoğunu göreceğinizi sanmıyorum. Ve az bilinen kabukları bir bütün paket var ...
Bir CVn

Modülerlik. Yerleşiklerle, bu yerleşiklerden birinde bir değişiklik yapıldığında kabuğu yeniden derlemeniz veya yeniden yüklemeniz gerekir.
can-ned_food

1

Birçoğu iyi cevap verdi. Sadece bu cevapları iltifat etmek niyetindeyim. UNIX felsefesinin bir aracın bir şeyi yapması ve iyi yapması gerektiği kanısındayım. Biri her şeyi kapsayan bir araç yapmaya çalışırsa, bu çok fazla başarısızlık yeridir. İşlevselliği bu şekilde sınırlamak, güvenilir bir araç seti sağlar.

Ayrıca, sed veya grep gibi işlevler kabuğun içine yerleştirildiyse, istediğiniz zaman komut satırından çağırmak daha kolay olur mu?

Kapanırken, düşünün, BASH'da olmasını istediğiniz işlevlerden bazıları BASH'da . Örneğin, BASH RE eşleştirmesi için yeteneği kullanılarak gerçekleştirilir = ~ ikili operatör (bkz Kabuk dilbilgisi kılavuz içinde daha özel olarak ise, için [[]] yapının tartışma referans için ise ). Çok hızlı bir örnek olarak, 2 onaltılık basamak için bir dosya aradığımı söyleyin:

while read line; do
    if [[ $line =~ 0x[[:xdigit:]]{2} ]]; then
        # do something important with it
    fi
done < input_file.txt

Gelince Sed-benzeri Parametre Genişleme altında işlevsellik, görünüm Genişleme başlığı aynı adam sayfasının. Yapabileceğiniz birçok şeyi, sed'i hatırlatan göreceksiniz. Metinde bazı değiştirme türlerinde değişiklik yapmak için genellikle sed'i kullanırım. Yukarıdakilerin inşaatı:

# this does not take into account the saving of the substituted text
# it shows only how to do it
while read line; do
    ${line/pattern/substitution}
done < input_file.txt

Sonunda, yukarıda, "daha iyi" daha iyidir?

grep -E "[[:xdigit:]]{3}" input_file.txt
sed -e 's/pattern/substitution/' input_file.txt

Son soruya karşı bir argüman unix.stackexchange.com/questions/169716/…
phk

1

Bu, sanırım, tarihi bir kaza.

UNIX 1960'ların sonunda ve 1970'lerin başında yaratıldığında, bilgisayarların bugün olduğu kadar hafızaları yoktu. O zamanlar tüm bu işlevselliği kabuk yerleşikler olarak uygulamak mümkün olacaktı, ancak bellek kısıtlamaları nedeniyle, uygulayabilecekleri işlevsellik miktarını sınırlandırmak ya da bellek ve / veya takas işlemlerini riske atmak zorunda kalacaklardı. sorunları.

Öte yandan, verilen işlevselliği ayrı programlar olarak uygulayarak ve gerekli iki sistemin mümkün olduğu kadar hafif yeni bir işlem başlatılmasını sağlayarak, bu sorunlara sahip olmayan ve hala makul bir şekilde çalışan bir betik ortamı yaratabilirler. hız.

Tabii ki, bu şeyler ayrı süreçler olarak uygulandıktan sonra, insanlar onları kabuk olmayan programlardan başlatacaklar ve daha sonra böyle kalmak zorunda kalacaklar ya da aniden bütün bu yazılımlar kırılmaya başlayacak.

Bununla birlikte, bazı işlevleri iki kez uygulayamayacağınız söylenemez, ve gerçekten de bazı kabuklar kabuk yerleşik olarak harici bir program olması gereken bazı işlevleri uygular; örneğin, bash echokomutu bir yerleşik olarak uygular , fakat aynı zamanda bir/usr/bin/echo

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.