Neden döngü için "argüman çok uzun" hatası vermiyor?


9

Bunun "argüman çok uzun" hatasını ortaya çıkaracağını buldum:

ls *.*

Ve bu onu yükseltmeyecekti:

for file in *.*
do
    echo $file
done

Neden?


Her iki deneyde de aynı kabuğu kullandınız mı? Belki /bin/bashvs /bin/sh(belki de bir çizgi bağlantısı)?
maxschlepzig

Evet, denemeyi oldukça uzun olan 10000 dosya adıyla yaptım. "ls *" başarısız oldu ve "f in *" için başarılı.
lamwaiman1988

Yanıtlar:


13

"Bağımsız değişken çok uzun" hatası, bağımsız değişkenlerin toplam boyutu (artı bazı sistemlerde ortam) çok büyükse sistem çağrısı E2BIGtarafından ortaya çıkar execve. execveÇağrı, özellikle farklı bir yürütülebilir dosya yükleme, dış işlemleri başlatır biridir (farklı telefon var, fork, kodunu, aynı yürütülebilir dosya hala ayrı bir işlem çalıştırmak için). forBu arama dahil değildir bu yüzden ilmek, bir iç kabuk ve güvenilir olduğu bulunmuştur execve. Komut ls *.*, glob genişletildiğinde değil lsçağrıldığında hatayı yükseltir .

execveE2BIGkomuta argümanların toplam boyutu ARG_MAX sınırdan büyük olduğunda hatayla başarısız olur . Bu sınırın değerini komutuyla sisteminizde görebilirsiniz getconf ARG_MAX. (Yeterli belleğiniz varsa bu sınırı aşmanız mümkündür; ilgisiz hata oluşmadığı sürece çalışacak ARG_MAXgarantiler altında tutmak execve.)


ve kabuğun neden bir sınırı yoktu?
lamwaiman1988

1
@ gunbuster363 execveSınır çekirdek tarafından uygulanır, sınırlar koyar çünkü argümanların bir noktada çekirdek belleği aracılığıyla kopyalanması gerekir ve kullanıcı işlemlerinin rasgele miktarda kabuk belleği istemesine izin verilemez. Kabuğun içinde herhangi bir sınırın olması için hiçbir neden yok, sanal belleğe uyan her şey yolunda.
Gilles 'SO- kötü olmayı bırak'

5

İlk örnekte / pair sistem çağrısı yoluyla lsyürütüldüğünü , ikincisinde ise tüm çalışmaların dahili olduğunu düşünüyorum .bashforkexecbash

execÇağrı iç çalışma, sınırları vardır bashyerine koymamıştır (veya daha iyisi ile ilgisi olmayan farklı sınırlara sahiptir exec, kullanılabilir bellek belki tutar).


Sen sınırı bulabilirsiniz execiçinde /usr/include/linux/limits.hgenellikle, olarak tanımlanır ARG_MAX.
jw013

Kabuğu döngü için kullanırsak, öğenin büyük bir listesinin tüm RAM'i tüketeceğini düşünüyor musunuz?
lamwaiman1988

Bu cevap yanlış. 'İç' değildir, sadece argüman ve komutların sınırları farklıdır.
polinom

5

Çünkü lsbu bir argüman ve argüman sayısı sınırlıdır.

forDöngü durumunda , bu sadece bir öğe listesidir. Bunun için herhangi bir sınırlama yoktur (bildiğim kadarıyla).


Kabuk genişlemesi için kesinlikle bir sınır vardır. Bu, ne kadar RAM'iniz olduğu ile ilgilidir. Bunu deneyin; 4GB RAM sistemim yaklaşık 15.2 milyon 8 baytlık bir for i in {00000001..20000000} ;do ((10#$i==1)) && break; done
argümana

4
@fred RAM'den bir limit olarak bahsetmenin gerçekten gerekli olduğunu düşünmedim.
Šimon Tóth

2
Gerekli olmayabilir, ancak yorumların doğası budur .. birisi onu ilginç, hatta değerli bulabilir.
Peter.O

@fred: aslında evet, eğer çok büyük argümanları genişletmek yaygın bir sorun olsaydı, her şeyi hafızada tutmadan uygulamak mümkün olurdu.
Matteo
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.