Yürütülmesi için neden lsayrı bir işlem gerekiyor? Gibi komutların cdçatallama mekanizması ile yürütülememesinin nedenini biliyorum ama çatalsız yürütüldüğünde herhangi bir zarar var lsmı?
Yürütülmesi için neden lsayrı bir işlem gerekiyor? Gibi komutların cdçatallama mekanizması ile yürütülememesinin nedenini biliyorum ama çatalsız yürütüldüğünde herhangi bir zarar var lsmı?
Yanıtlar:
Cevap az lsçok harici bir yürütülebilir dosyadır. Konumunu çalıştırarak görebilirsiniz type -p ls.
lsÖyleyse neden kabuğun içinde değil ? Neden olsun ki? Bir kabuğun işi mevcut tüm komutları kapsamak değil, bunları çalıştırabilen bir ortam sağlamaktır. Bazı modern kabuklar var echo, printfve yok builtins, bunların ilk teknik builtins olmak zorunda, ama onlar (öncelikle sıkı döngüler içinde) sürekli olarak çalıştırılır performans nedenleriyle bu yüzden yapılır. Onları yerleşik hale getirmeden, kabuk her bir çağrı için çatallanmalı ve yeni bir süreç yürütmelidir, bu da son derece yavaş olabilir.
En azından, çalıştırılabilir ls, harici bir yürütülebilir dosya, sistem çağrılarının exec ailesinden birini çalıştırmayı gerektirir. Sen olabilir Çatallama olmadan bunu ancak kullandığınız birincil kabuğu yerini alacak. Aşağıdakileri yaparak o örnekte neler olduğunu görebilirsiniz:
exec ls; echo "this never gets printed"
Kabuğunuzun işlem görüntüsü değiştirildiği için, geçerli kabuğa bundan sonra erişilemez. Kabuğun ls çalıştırıldıktan sonra çalışmaya devam edebilmesi için, komut kabuğun içine yerleştirilmelidir.
Forking, birincil kabuğunuz olmayan bir işlemin değiştirilmesine izin verir, bu da daha sonra kabuğunuzu çalıştırmaya devam edebileceğiniz anlamına gelir.
echo, printfvb
cdharici bir yürütülebilir dosya neden olmasın?
cdPOSIX uyumlu işletim sistemlerinde çalıştırılabilir ( burada bakınız ). Mevcut işlemde aslında chdir () yapmak istiyorsanız, kabuğun içine yerleştirilmiş olması gerekir.
Bash devletler:
Yerleşik komutlar, ayrı yardımcı programlarla elde edilmesi imkansız veya uygunsuz işlevsellik uygulamak için gereklidir.
Yani, mermiler yalnızca şu durumlarda yerleşik komutları içerecek şekilde tasarlanmıştır :
lsKomut yukarıdaki requirments herhangi uymuyor.
Bununla birlikte , burada lsyerleşik olarak uygulanmasını engelleyecek , bash yorumlayıcısıyla aynı işlemde çalışan hiçbir programlama kısıtlaması yoktur . Komutlar için tasarım nedenleri değil kabuk yerleşik ins olarak implmented ediliyor şunlardır:
İlk sebeple ilgili - Kabuğun mümkün olduğunca bağımsız ve dirençli olmasını istiyorsunuz. Kabuğun ls"hala denemeye yanıt vermiyor" olan bir NFS yuvasına takılmasını istemezsiniz .
İkinci nedenle ilgili - Birçok durumda, Busybox veya farklı bir lsuygulaması olan diğer dosya sistemi kullanan bir sistem için bir kabuk kullanmak isteyebilirsiniz . Ya da farklı lsuygulamaları olan işletim sistemlerinde aynı kabuk kaynağını kullanın .
Üçüncü sebeple ilgili olarak - Kabuk yorumlayıcıyla aynı süreçte find . -type d | xargs ls -laduygulanması zor veya imkansız gibi bir ifade için ls.
Dördüncü nedenle ilgili - Bazı lskomutların tamamlanması uzun sürebilir. Bu arada kabuğun başka bir şey yapmaya devam etmesini isteyebilirsiniz.
Not: Bkz bu yararlı yazı ile Warren Young benzer bir soruya cevap olarak.
lsharici bir sürece dönüştürmek zorundaysa, kabuğun kaynak kodunun ne kadar karmaşık olacağını düşünürdüm . Bu yapılabilirdi, ama karmaşık olurdu.
bashçıktı alias | grep ls. girişcat /etc/passwd | while read a; do echo "$a"; done
lsayrı bir işlem gerektirmez. Çok az komut aslında ayrı bir işlem gerektirir: sadece ayrıcalıkları değiştirmesi gerekenler.
Kural olarak, kabuklar yalnızca bu komutların yerleşik olarak uygulanması gerektiğinde komutları yerleşik olarak uygular. Komutları gibi alias, cd, exit, export, jobs, ... bu nedenle okumak veya kabuğun bazı iç durumunu değiştirmek ve ihtiyacı ayrı programlar olamaz. Böyle bir gereksinimi olmayan komutlar ayrı komutlar olabilir; bu şekilde herhangi bir kabuktan veya başka bir programdan çağrılabilirler.
Bash içindeki yerleşikler listesine bakıldığında, yalnızca aşağıdaki yerleşikler ayrı komutlar olarak uygulanabilir. Bazıları için hafif bir işlevsellik kaybı olacaktır.
command- ancak PATHdüzgün ayarlanamayacağı ve komut dosyasının commandkurulumun bir parçası olarak kullandığı durumlarda kullanışlılığını kaybeder .echo - verimlilik için bir yerleşiktir.help - ayrı bir veritabanı kullanabilir, ancak yardım metninin kabuk yürütülebilir dosyasına gömülmesi, kabuğun yürütülebilir dosyasını kendi içinde bulundurma avantajına sahiptir.kill - yerleşik bir yapıya sahip olmanın iki avantajı vardır: işlem kimliklerine ek olarak iş tanımlarını tanıyabilir ve ayrı bir işlem başlatmak için yeterli kaynak olmasa bile kullanılabilir.printf- aynı nedenden dolayı echove aynı zamanda -vçıktıyı bir değişkene koyma seçeneğini desteklemek .pwd - yerleşik mantıksal geçerli dizin izleme ek yeteneği sunar (sembolik bağlantıları genişletmek yerine sağlam bırakır).test- verimlilik için bir yerleşiktir (ve bash ayrıca /dev/fd/…bazı işletim sistemlerinde çağrılan dosyalarla biraz sihir yapar ).Birkaç mermi önemli sayıda ek yerleşik yapı sunar. Acil onarımlar için bağımsız bir ikili olarak tasarlanmış bir kabuk olan kanat vardır (bazı harici komutlar kullanılamayabilirse). Yerleşik ls, adı verilen ve ve -lsgibi diğer araçlara sahiptir . Sash'in yerleşikleri tam teşekküllü komutlardan daha az kapasiteye sahiptir. Zsh, zsh / files modülünde benzer yapıları sunar . Sahip değil , joker karakter genişletmesi ( ) ve benzer bir işlevi yerine getirebilir.-grep-tarlsecho *zstat
İnsanların burada eksik olduğu bir şeyin lsLinux'taki GNU programının kesme karmaşıklığı olduğunu düşünüyorum . Yürütülebilir boyutunu karşılaştırılması lsiçin bashve dashbenim Debian sistemine kabukları, bunun oldukça büyük olduğunu görüyoruz:
graeme@graeme:~$ ls -lh /bin/{ls,bash,dash}
-rwxr-xr-x 1 root root 953K Mar 30 2013 /bin/bash
-rwxr-xr-x 1 root root 115K Dec 25 20:25 /bin/dash
-rwxr-xr-x 1 root root 108K Jul 20 22:52 /bin/ls
lsGNU sürümü kadar tam özellikli bir dahil edilmesi bash, yürütülebilir boyutu% 10 artıracaktır. Neredeyse tam dashkabuk ile aynı boyutta !
Çoğu kabuk yerleşkesi, kabukla harici yürütülebilir dosyaların yapamayacağı şekilde entegre oldukları için seçilir (soru işaret eder cd, ancak başka bir örnek killbash iş kontrolüyle entegrasyonun bash sürümüdür ) veya uygulanması çok basit komutlar oldukları için, büyük bir hız vs boyut getirisi ( trueve falseyaklaşık olarak basit).
GNU lsuzun bir geliştirme döngüsüne sahiptir ve sonuçların hangi şekilde / nasıl görüntüleneceğini özelleştirme seçenekleri uygulayabilir. Varsayılan olarak yerleşik bir ls kullanmak bu işlevselliği kaybeder veya kabuk karmaşıklığını ve boyutunu önemli ölçüde artırır.
Aradığınızı yapın:
printf "%s\n" *
Ayrıca dosya adlarını dizide saklayabilirsiniz:
files=(`printf "%s\n" *`) #items are separated by whitespace
echo ${#files[*]} files
for index in ${!a[*]}
do printf "%d: %s\n" $index ${a[$index]};
done
Ama isimlerdeki boşlukları umursamıyor
Bu değişkene geçer ve boşlukları umursar:
printf "%s\n" * | while read a; do echo $a; done
lsHarici bir program olmasına rağmenecho *veyaecho * .*(kabuk seçeneklerine bağlı olarak) dosyaları çatallamadan listelemek için oldukça iyi bir iş çıkarır.