CP: kopyalama yardımcı programı için maksimum kaynak dosya sayısı bağımsız değişkenleri


11

/ Src / altında sayısız dosya olduğunu düşünün

cp /src/* /dst/

Kaç dosya cpbaşarıyla işlenir?


2
Argüman listesi çok uzunsa (unutmayın, * ne yaparsa glob ile eşleşen tüm dosyaların listesine genişletilir), örn. IFS="\n" for file in /src/*; do mv "$file" /dst/; doneVeya rsync -a /src/ /dst/.
DopeGhoti

Yanıtlar:


18

Bu büyük ölçüde sisteme ve sürüme, bağımsız değişkenlerin sayısına ve boyutuna ve ortam değişkeni adlarının sayısına ve boyutuna bağlıdır.

Geleneksel olarak Unix'te, sınır (tarafından bildirildiği gibi getconf ARG_MAX), aşağıdakilerin kümülatif boyutunda aşağı yukarı idi:

  • Bağımsız değişken dizelerinin uzunluğu (sonlandırma dahil '\0')
  • Bu dizelere işaretçi dizisinin uzunluğu, yani 64 bitlik bir sistemde bağımsız değişken başına 8 bayt
  • Ortam dizelerinin uzunluğu (sonlandırma dahil '\0'), bir ortam dizesi konvansiyona benzer bir şeydir var=value.
  • Bu dizelere işaretçi dizisinin uzunluğu, yani 64 bitlik bir sistemde bağımsız değişken başına 8 bayt

Hatırda tutarak cpbağımsız değişken olarak da sayıları (ilk argümandır).

Linux'ta, sürüme bağlıdır. Oradaki davranış, artık sabit bir alan olmadığı yerde değişti.

Linux 3.11 üzerinde kontrol, getconf ARG_MAXartık yığın boyutunda belirlenen sınırın dörtte birini veya 512kiB'den küçükse 128kiB'yi bildiriyor).

( zshaşağıdaki sözdizimi):

$ limit stacksize
stacksize       8MB
$ getconf ARG_MAX
2097152
$ limit stacksize 4M
$ getconf ARG_MAX
1048576

Bu sınır, argümanın ve ortam dizgilerinin kümülatif boyutu ve bazı ek yükler üzerindedir (sayfa sınırlarındaki hizalama nedeniyle şüpheleniyorum). İşaretçilerin boyutu dikkate alınmaz.

Sınırı ararken, şunu elde ederim:

$ /bin/true {1..164686}
$ /bin/true {1..164687}
zsh: argument list too long: /bin/true
$ x= /bin/true {1..164686}
$ x=1 /bin/true {1..164686}
zsh: argument list too long: /bin/true

Bu durumda kırılmadan önceki maksimum kümülatif boyut:

$ (env _=/bin/true x=;print -l /bin/true {1..164686}) | wc -c
1044462

Artık bu, 1 milyon boş argüman aktarabileceğiniz anlamına gelmiyor. 64 bit sistemde, 1 milyon boş argüman 8 MB'lık bir işaretçi listesi oluşturur, bu da 4MiB yığın boyutumun üstünde olur.

$ IFS=:; /bin/true ${=${(l.1000000..:.)${:-}}}
zsh: killed     /bin/true ${=${(l.1000000..:.)${:-}}}

(bunun bir E2BIG hatası olmadığını fark edeceksiniz. execveSistem çağrısında veya daha sonra olsa, işlemin orada hangi noktada öldürüldüğünden emin değilim ).

Ayrıca (hala Linux 3.11'de), tek bir argümanın veya ortam dizesinin maksimum boyutunun, yığının boyutuna bakılmaksızın 128kiB olduğunu unutmayın.

$ /bin/true ${(l.131071..a.)${:-}} # 131072 OK
$ /bin/true ${(l.131072..a.)${:-}} # 131073 not
zsh: argument list too long: /bin/true
$ /bin/true ${(l.131071..a.)${:-}} ${(l.131071..a.)${:-}} # 2x 131072 OK

Paylaşır mısın lütfen, 164686numarayı nasıl buldun ? yani bu dizinin 2097152ARG_MAX boyutunun altında olacağını nasıl hesapladınız ?
Sergiy Kolodyazhnyy

14

Bu, sistemler arasında değişebilen ARG_MAX değerine bağlı olacaktır. Sistem çalıştırmanızın değerini bulmak için (sonucu benimki örnek olarak gösteren):

$ getconf ARG_MAX
2097152

Bunun cpveya kabuğunuzla ilgisi yoktur , çekirdek tarafından dayatılan bir sınırdır exec(), argümanları daha uzunsa ( ) komutlarını yürütmez ARG_MAX. Dolayısıyla, verdiğiniz bağımsız değişken listesinin cpuzunluğu ARG_MAX'tan büyükse, cpkomut hiç çalışmaz.

O zaman ana sorunuzu cevaplamak için cphiçbir dosya işlenmeyecektir çünkü hiçbir zaman bu kadar çok argümanla yürütülmeyecektir. Ayrıca bunun argüman sayısına değil uzunluğuna bağlı olduğunu da belirtmeliyim. Muhtemelen çok az ama çok uzun dosya adlarıyla aynı sorunu yaşayabilirsiniz.


Bu hataların üstesinden gelmenin yolu, komutunuzu bir döngüde çalıştırmaktır:

for file in /src/*; do cp "$file" /dst/; done

Bu, daha düşük seviyeli dillerin bile CARG_MAX ve gerçekten uzun dosya adlarıyla ilgili sorunlara sahip olabileceği anlamına mı geliyor ?
Harold Fischer
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.