Yankı neden komut içinde yerleşik bir kabuktur?


34
$ which echo
echo: shell built-in command.
$ which ls
/bin/ls
$ which cat
/bin/cat

Neden yankı gibi bağımsız bir yarar değil ls, ps, catvs? Neden kabuk belirli? Herhangi bir iyi sebep var mı?


5
Bunun kabuğa özgü olduğunu unutmayın. ZSH onu oluşturur, BASH yapmaz.
tsvallender

21
@tsv: echoKesinlikle olan bir Bash yerleşik. Aslında her büyük modern kabuğun içinde yerleşiktir.
sonraki duyuruya kadar duraklatıldı.

Yanıtlar:


71

İki yerleşik sınıf vardır:

  1. Bazı komutların kabuk programın içine yerleştirilmesi gerekir, çünkü haricise çalışamazlar.

    cdçünkü eğer harici olsaydı, sadece kendi dizinini değiştirebilirdi; kabuğun mevcut çalışma dizinini etkileyemedi. (Ayrıca bakınız: Neden cdbir program değil? )

  2. Diğer komutlar sınıfı tamamen verimlilik için kabuğun içine yerleştirilmiştir.

    Adam sayfa bahseder yerleşikleri bir bölüm vardır , ve bu sınıfta komutların örnekler olarak.dash printfechotest

Unix sistemleri her zaman o ikinci sınıftaki komutlar için ayrı çalıştırılabilir kodlar ekledi. Bu ayrı yürütülebilir dosyalar, kullanacağınız her kabuğun içine de yerleştirilmiş olsalar bile, kullandığım tüm Unixy sistemlerinde hala mevcuttur. ( POSIX aslında bu yürütülebilir dosyaların mevcut olmasını gerektirir.)

echoAT&T Unix System V Sürüm 3.1’de kabuğun içine yerleştirildiğine inanıyorum . Bunu, AT & Ts 3B1 serisi Unix sistemleri için iki farklı kullanım kılavuzunun karşılaştırmasına dayandırdım . Birisi nazikçe bu kılavuzların 1986 basımını taradı ve çevrimiçi hale getirdi ; bunlar SVR3'ün orijinal sürümüne karşılık gelir. Komutun kabuğun içine yerleştirilmiş olup olmadığını bekleyeceğiniz UNIX System V Kullanıcı El Kitabı, Cilt II'ninecho 523. sayfasındaki listede olmadığını görebilirsiniz . 1987 den SVR3.1 kılavuzları benim yerel kağıt kopya olarak, bir kılavuzun bu bölümde listelenen.echo

Bunun AT & T'nin eve geri getirdiği bir Berkeley CSRG yeniliği olmadığından eminim . 4.3BSD, SVR3, 1986 ile aynı yıl çıktı, ancak 4.3BSD'nin sh.1 kılavuz sayfasına bakarsanız echo, "Özel Komutlar" bölümünde yerleşik komutlar listesinde olmadığını görüyorsunuz . Eğer CSRG bunu yaptıysa, kanıtlamak için belgelenmiş bir kaynak istememize izin verilmez.

Bu noktada, echokabuğun içine SVR3.1'den daha önce yerleştirilmiş olup olmadığını ve bu gerçeğin o zamana kadar belgelenmediğini merak edebilirsiniz . Bana sunulan en yeni SVR3 AT&T Unix kaynak kodu , Bourne kabuğu kaynak kodunu bulacağınız PDP-11 Sistem III tarball'ındadır . echoİçindeki yerleşik komut tablosunda bulamazsınız /usr/src/cmd/sh/msg.c. Bu dosyadaki zaman damgalarına dayanarak, bu echo1980'de kesinlikle kabuğun içinde olmadığını kanıtladı .


önemsiz şeyler

Aynı dizin builtin.c, bu soru için o noktada hiçbir şey içermeyen bir dosya da içeriyor , ancak bu ilginç yorumu buluyoruz:

/*      
    builtin commands are those that Bourne did not intend
    to be part of his shell.
    Redirection of i/o, or rather the lack of it, is still a
    problem..
*/      

Bahsettiğiniz SysV UM, Vol II'nin 385. sayfasında, printksh için yerleşik davrandığı söylenen yerleşik bir komut vardır echo. Bu komut ISC'den AT&T Unix SVR4 2.1 i386 gibi bir şeyde mevcuttur. print "\012"yankı ile aynı sonucu verir. Neden ksh'in baskı yaptığını ve neden yankılanmadığını merak ettin mi? Neyse gerçekten ilginç.

Birkaç yıl öncesine ait bu tür taşların birçoğu 2016 yılında bir düzenlemeyle ortaya çıkmayı bekliyor mu? +1
iruvar

+1. Teşekkürler. (Sistematik) okuma / öğrenme için yerleşik bir komut verme amacıyla kaynakları (referansları) verebilir misiniz?
Tim

Sistematik olarak okumak veya öğrenmek için bazı referanslar, kılavuzlar veya standartlar bulmak istiyorum. Bunu bash referans el kitabında ve POSIX spesifikasyonlarında aramaya çalıştım. Ama bulamıyorum. Onları özleyip özlemediğimden emin değilim.
Tim

@Tim: Bu ve buradaki diğer cevapların açıkladığı gibi, bazı komutların kabuk içine yerleştirilmesi gerekir veya işlerini yapamazlar. Diğerleri tamamen isteğe bağlıdır . Aslında Bourne kabuğundaki kaynak snippet'imin yukarıda söylediği aslında bu. Bu komutları kabuğun içine koymak isteğe bağlı olduğundan, yetkili bir mantık yalnızca bir uygulayıcının görüşünü verebilir.
Warren Young

19

Bazı komutların yerleşik olarak bulunmasının üçüncü bir nedeni vardır: Harici komutları çalıştırırken kullanılamazlar.

Bazen bir sistem öylesine bozulur ki lskomut çalışmaz. Bazı durumlarda, bir echo *irade hala çalışacaktır.

Bir başka (daha önemli!) Örnek kill: Bir sistemde boş PID'ler bitiyorsa, çalıştırılması mümkün değildir /bin/kill(çünkü bir PID'ye ihtiyacı vardır :-), fakat yerleşik killçalışacaktır).

Btw., whichHarici bir komuttur (en azından bash içerisinde dahili değildir), bu yüzden dahili komutları listeleyemez. Örneğin:

$ which echo
/bin/echo
$ type -a echo
echo is a shell builtin
echo is /bin/echo

Neredeyse tüm harici çalıştırılabilir dosyaların kütüphane dosyalarına güvendiğini unutmayın. Bazen felaketler olur ve bu kütüphaneler yüklenemez (öneri: ldconfigNe yaptığını KİMLERİNİZ bilemezseniz ASLA sorun değil). Ayrıca, / bin kutunuzu ya da daha da kötüsü, / sbin bölümünüzü havaya uçuruyorsanız, fakat hala yüklü bir kabuk varsa?
LawrenceC

PID'leriniz biterse, hangi PID'yi öldürmek istediğinizi bulmak zor olabilir. Bir pskomutu çalıştıramazsınız , böylece PID'leri manuel olarak bulmak zorunda kalırsınız /proc.
kasperd

Her ne kadar (en azından) CentOS whichçalışır bir bash takma alias | /usr/bin/which --read-alias ...dış yüzden which olabilir takma adları (ama yine de değil builtins) tanımlar. Bunu zekice mi yoksa sapkın olarak mı düşüneceğime karar veremiyorum.
dave_thompson_085

Ls komutu artık işe yaramadıysa, sürücüyü önyükleme / master yerine slave olarak takmanız ve dosya yapısını bu şekilde düzeltmeniz gerektiğini düşünüyorum. Bir dosyada yankılanmadığınız ve düzeltmesi uzun zaman alacağı sürece, sistem eko ​​ile bu ölçüde bozulma durumunu nasıl çözebileceğinizden emin değilim. Sistem yapısını düzeltmek için bir bash betiği yazabileceğinizi kabul etti.
jonnyjandles

13

Göre Bash Referans Kılavuzuna , bu kolaylık ilgili.

Kabuklar, ayrıca, ayrı bir yardımcı program aracılığıyla edinilmesi imkansız veya uygunsuz olan, işlevselliği uygulayan küçük bir dizi yerleşik komut da sağlar. Örneğin, cd, break, devam et ve exec) kabuğun dışına uygulanamaz çünkü kabukları doğrudan idare ederler. Tarih, getopts, öldürmek veya pwd yerleşiklerinin diğerleri arasında ayrı uygulamalarda uygulanabilir, ancak yerleşik komutlar olarak kullanmak daha uygundur. Tüm kabuk yerleşikleri sonraki bölümlerde açıklanmıştır.

Gelişmiş Bash Scripting Guide daha ayrıntılı açıklaması var:

"Bir yerleşik, kelimenin tam anlamıyla yerleşik olan Bash araç setinde bulunan bir komuttur. Bu, performans nedenlerinden dolayıdır - yerleşikler harici komutlardan daha hızlı çalışır, genellikle 1 ayrı bir işlem yapılmasını gerektirir - veya belirli bir yerleşikin doğrudan ihtiyacı olduğu için kabuk içindekilere erişim. "

Ayrıca echo, bazı sistemlerde bağımsız bir yardımcı program olarak bulunduğunu da unutmayın . İşte Darwin sistemimde sahip olduklarım (MacOSX 10.5.8 - Leopard)

$ uname -a
Darwin host.foo.org 9.8.0 Darwin Kernel Version 9.8.0: Wed Jul 15 16:55:01 PDT 2009; root:xnu-1228.15.4~1/RELEASE_I386 i386
$ bash --version
GNU bash, version 3.2.17(1)-release (i386-apple-darwin9.0)
Copyright (C) 2005 Free Software Foundation, Inc.
$ which echo
/bin/echo

echoayrıca bir yerleşik olarak da bulunur, ancak komut dosyalarım Mac'imde / bin / echo kullanıyor ve Linux ve FreeBSD sistemlerimin çoğunda bir Bash yerleşik kullanıyor. Fakat bunun önemi yok, çünkü senaryolar hala her yerde iyi çalışıyor.


3
Kabuk yerleşiklerinden bahsetmişken, "hangi" yerine "type" kullanıyor olmalısınız.
Teddy

@Teddy'ye teşekkürler. Bunu hatırlamaya başladığımda yapmaya başladım. Hayat sayesinde çok daha iyi type.
Stefan Lasiewski

6

Bhm'in cevabını tamamlamak için, diyelim ki /binyanlışlıkla sizden PATH. Bunu echo $PATHbulabilmek isterdin, değil mi?


2

Her ne kadar çoğu kabuk echobugünlerde yerleşik olsa da, GNU CoreUtils ayrıca bunun bağımsız bir uygulamasını da içerir:

$ which echo
/bin/echo
$ dpkg -S /bin/echo
coreutils: /bin/echo

GNU Coreutils kurulmamış gibi geliyor (çoğu linux tabanlı masaüstü ve sunucu işletim sistemi varsayılan olarak yüklüyse de, gömülü linux veya diğer UNIX yerine alternatif kabuk programları kullanabilirsiniz).

BTW: Eğer bakarsanız Busybox , bunu göreceksiniz ls, psve catorada da komutları dahili vardır (olabilir en azından ya; o gömülmüş sistemler için kullanılan ve ihtiyaç duyulan her şey dışarı bırakılabilir).


3
Orijinal posterin testleri, var olmayan hipotezi desteklemiyor /bin/echo. Onlar sadece yerleşimin PATH'taki herhangi bir echoprogramdan öncelikli olduğunu gösteriyor .
Warren Young

1

İşte echobir kabuk yerleşik neden olmasının gerçek nedeni :

Bir şifreniz olduğunu varsayalım $PASSWORD. Bir dosyaya nasıl yazarsın ./password? Doğal olarak çoğu programcı şunları yazar:

echo "$PASSWORD" >./password

Ancak, eğer echobir kabuk yerleşik olmasaydı, şifre tüm kullanıcılara psbilgi yoluyla sızardı.

Tabii ki, bu konuda zeki olmak istiyorsanız echo, belki başka bir kabuk özelliğinden yararlanmadan bir parola saklamanın bir yolunu bulabilirsiniz :

cat >./password <<EOF
${PASSWORD}
EOF

Ancak, echoyerleşik olarak sahip olmak , bir dosyaya şifre kaydetmenin en açık yolunun da çalışması gerektiği için önemli bir emniyet kemeridir.


3
Yararlı bir yan etki olsa da, bunun sebebi olduğuna şüpheliyim.
plugwash

@DepressedDaniel: Size ne yedekler? Cevabınızı desteklemek için kullandığınız referans nerede?
şakacı
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.