Bash komut satırı ve giriş sınırı


91

Bash'de (veya diğer kabuklarda) bir girişin ne kadar uzun olabileceği için bir tür karakter sınırı var mı? Eğer öyleyse, bu karakter sınırı nedir?

Yani bash'de komut satırının yürütmesi için çok uzun bir komut yazmak mümkün müdür? Gerekli bir limit yoksa önerilen bir limit var mı?


2
Giriş limiti çok farklıdır OS düzeyinde argüman sınırı (örneğin ortam değişkenleri olarak argümanlar dışında bazı şeyler de o biri doğru geçerli olduğunu not). İşletim sistemine iletilen oluşturulan komut, onu oluşturan kabuk komutundan daha fazla veya daha az karaktere sahip olabilir.
Charles Duffy

Yanıtlar:


129

Bir komut satırının uzunluğu için sınır, kabuk tarafından değil, işletim sistemi tarafından belirlenir. Bu sınır genellikle yüz kilobayt aralığındadır. POSIX bu sınırı belirtir ARG_MAXve POSIX uyumlu sistemlerde sorgulayabilirsiniz.

$ getconf ARG_MAX    # Get argument limit in bytes

Örneğin Cygwin'de bu 32000'dir ve kullandığım farklı BSD'ler ve Linux sistemlerinde 131072'den 2621440'a kadar herhangi bir yerdedir.

Bu sınırı aşan bir dosya listesini işlemeniz gerekiyorsa xargs, bir programı aşmayan bir bağımsız değişken alt kümesiyle tekrar tekrar çağıran yardımcı programa bakmak isteyebilirsiniz ARG_MAX.

Özel sorunuzu cevaplamak için, evet, çok uzun bir argüman listesiyle bir komutu çalıştırmayı denemek mümkündür. Kabuk, "argüman listesi çok uzun" boyunca bir mesajla hata verecektir.

O Not girişi bir programa (stdin veya başka bir dosya tanımlayıcı okumak gibi) olduğu değil (sadece mevcut programı kaynakları ile) sınırlı. Dolayısıyla, kabuk betiğiniz bir dizgeyi bir değişkene okursa, kısıtlanmazsınız ARG_MAX. Kısıtlama, kabuk yerleşikler için de geçerli değildir.


Güzel cevap, yine de bir açıklama istiyorum. Bir yapı cmd <<< "$LONG_VAR"alırsam ve LONG_VAR değeri sınırı aşarsa, komutumu bozar mı?
Krzysztof Jabłoński

1
@ KrzysztofJabłoński Muhtemel değildir, çünkü içeriği LONG_VARstdin üzerinden aktarılır - ve bu tamamen kabukta yapılır; argüman olarak genişletilmez cmd, dolayısıyla fork () / exec () için ARG_MAX sınırı devreye girmez. Kendinizi denemek kolaydır: ARG_MAX'ı aşan içeriğe sahip bir değişken oluşturun ve komutunuzu çalıştırın.
Jens

2
İşte kayıt için açıklama verilmiştir: 8 megabayt m4a dosya için, yaptım: blah="$(cat /home/schwager/Music/Recordings/20090420\ 131623.m4a)"; cat <<< $blah >/dev/null. Hata olmadığını unutmayın.
Mike S

4
Küçük uyarı. Ortam değişkenleri de önemlidir. sysconf manpage > ARG_MAX'ı kullanmak zordur çünkü exec (3) için argüman alanının ne kadar> kullanıcının> çevre değişkenleri tarafından tüketildiği belirtilmemiştir.
Gerrit

3
böyle @ user188737 ben hissediyorum içinde oldukça büyük bir uyarıdır HATALAR . Örneğin xargsbu olanınıtakabilecek çalışır ne kadar MacOS 10.12.6 limitleri exec()için ARG_MAX - 4096. Dolayısıyla xargs, bir gün birileri ortama çok fazla şey koyana kadar komut dosyaları kullanmak işe yarayabilir. Şimdi bununla karşılaşıyorum (bunun üzerine çalışın :) xargs -s ???.
neuralmer

45

Tamam, Denizens. Bu yüzden uzun bir süredir komut satırı uzunluk sınırlarını müjde olarak kabul ettim. Öyleyse, kişinin varsayımlarıyla ne yapılmalı? Doğal olarak kontrol edin.

Elimde bir Fedora 22 makinesi var (anlamı: bash4 ile Linux). Her biri 18 karakter uzunluğunda 500.000 düğüm (dosya) içeren bir dizin oluşturdum. Komut satırı uzunluğu 9.500.000 karakterdir. Bu şekilde oluşturuldu:

seq 1 500000 | while read digit; do
    touch $(printf "abigfilename%06d\n" $digit);
done

Ve şunu not ediyoruz:

$ getconf ARG_MAX
2097152

Ancak şunu yapabilirim:

$ echo * > /dev/null

Ancak bu başarısız olur:

$ /bin/echo * > /dev/null
bash: /bin/echo: Argument list too long

Bir for döngüsü çalıştırabilirim:

$ for f in *; do :; done

başka bir kabuk yerleşik olan.

Durumlar için belgelerinARG_MAX dikkatli okunması , exec işlevlerine maksimum argüman uzunluğu . Bu şu anlama gelir: Aramadan exec, ARG_MAXsınırlama yoktur . Bu yüzden kabuk yerleşiklerinin neden kısıtlanmadığını açıklayabilir ARG_MAX.

Ve gerçekten, lsbağımsız değişken listem 109948 dosya uzunluğunda veya yaklaşık 2.089.000 karakter (ver veya al) ise dizinimi yapabilirim. Yine de 18 karakterlik bir dosya adı dosyası ekledikten sonra, Argüman listesi çok uzun bir hata alıyorum. Yani ARG_MAXreklamı olarak çalışıyor: exec daha fazlası ile başarısız oluyor ARG_MAXdahil listesi-argüman üzerinde karakterlerin, bu, çevre verilerini unutulmamalıdır.


Hmm. Yerinlerin söz konusu kısıtlamaya tabi olduğunu ima etmek için mevcut cevabı okumamıştım, ancak birinin nasıl yapabileceğini kesinlikle görebiliyordum.
Charles Duffy

6
Evet, özellikle yeni komut satırı meraklıları için, bir bash yerleşik olarak çağırma / fork / bir komutu yürütme durumunun bariz olmayan şekillerde farklı olduğunu hatırlamanın zor olduğunu düşünüyorum. Bunu netleştirmek istedim. Bir iş görüşmesinde (bir Linux Sysadmin olarak) her zaman aldığım bir soru, "Bu yüzden bir dizinde bir sürü dosya var. Hepsinin üzerinden nasıl geçebilirim ..." uzunluk sınırı ve find / while veya xargs çözümü istiyor. Gelecekte, "ah lanet olsun - sadece bir for döngüsü kullanın. Bunu halledebilir!" :-)
Mike S

@MikeS for döngüsü yapabilirken, find-xargs combo kullanırsanız, çok daha az çatallanır ve daha hızlı olursunuz. ;-)
Lester Cheung

4
@LesterCheung for f in *; do echo $f; donehiç çatallanmayacak (tüm yerleşikler). Bu yüzden find-xargs combo'nun daha hızlı olacağını bilmiyorum; test edilmedi. Doğrusu, OP'nin problem setinin ne olduğunu bilmiyorum. Belki find /path/to/directoryonun için yararlı olmayacaktır çünkü dosyanın yol adını döndürecektir. Belki bir for f in *döngünün basitliğinden hoşlanıyor . Her şeye rağmen, konuşma verimlilikle değil hat giriş sınırı ile ilgilidir. Öyleyse, komut satırı uzunluğuyla ilgili olan konuya devam edelim.
Mike S

FWIW, hatırladığım kadarıyla sorun, sadece C'de bir kabuk yazmaya ve girdilerin ne kadar süre kalmasına izin vermem gerektiğini belirlemeye çalışmaktı.
Derek Halden

-3

1024 gibi bir arabellek sınırı vardır. Okuma, yapıştırma veya girişin ortasında asılı kalacaktır. Bunu çözmek için -e seçeneğini kullanın.

http://linuxcommand.org/lc3_man_pages/readh.html

-e satırı etkileşimli bir kabukta elde etmek için Readline'ı kullanın

Okumanızı -e olarak değiştirin ve can sıkıcı satır giriş askıda kalması ortadan kalkar.


1
Bu readşununla ilgili değil : "Yani bash'de komut satırının yürütmesi için çok uzun bir komut yazmak mümkün müdür?"
Chai T. Rex

@ ChaiT.Rex, biraz haklısınız, ama mesele şu: Bash'i Readline olmadan etkileşimli olarak çalıştırmayı deneyin, yani bash --noeditingyeni komut isteminde bir echo somereallylongwordmiktar uzun sözcüğün 4090 karakterden uzun olduğu komutu çalıştırmayı deneyin . Ubuntu 18.04'te denendi, kelime kesildi, bu yüzden açık bir şekilde Readline'ın etkinleştirilmemesiyle bir ilgisi var.
Amir

@Amir İlginç! Haklısın! Cevabı düzenlemeye çalıştım, ancak sonra -e seçeneğinin bu bağlamda bash için geçerli olmadığını fark ettim (bash'da, hata durumunda kabuktan hemen çıkar). Ve Paul'ün neden okumak için döndüğünden emin değilim. Her neyse, bash --noreadline ile başlatıldığında 4-5000 karakter arasında bir arabellek sınırı vardır. Bu bilmediğim veya beklemediğim bir yan etki.
Mike S
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.