Baris perintah Bash dan batas input

90

Apakah ada semacam batasan karakter yang diberlakukan di bash (atau shell lain) untuk berapa lama input bisa? Jika ya, berapa batas karakter itu?

Yaitu Apakah mungkin untuk menulis perintah di bash yang terlalu panjang untuk dieksekusi oleh baris perintah? Jika tidak ada batasan yang disyaratkan, apakah ada batasan yang disarankan?

Derek Halden
sumber
2
Batas input sangat berbeda dari batas argumen tingkat OS (perhatikan bahwa beberapa hal selain argumen, seperti variabel lingkungan, juga berlaku untuk yang satu itu). Perintah yang dihasilkan yang diteruskan ke sistem operasi dapat memiliki lebih banyak atau lebih sedikit karakter daripada perintah shell yang membuatnya.
Charles Duffy

Jawaban:

127

Batas panjang baris perintah tidak ditentukan oleh shell, tetapi oleh sistem operasi. Batasan ini biasanya dalam kisaran ratusan kilobyte. POSIX menunjukkan batas ini ARG_MAXdan pada sistem konforman POSIX Anda dapat menanyakannya

$ getconf ARG_MAX    # Get argument limit in bytes

Misalnya pada Cygwin ini adalah 32000, dan pada sistem BSD dan Linux yang berbeda saya menggunakannya antara 131072 sampai 2621440.

Jika Anda perlu memproses daftar file yang melebihi batas ini, Anda mungkin ingin melihat xargsutilitas, yang memanggil program berulang kali dengan subset argumen tidak melebihi ARG_MAX.

Untuk menjawab pertanyaan spesifik Anda, ya, adalah mungkin untuk mencoba menjalankan perintah dengan daftar argumen yang terlalu panjang. Shell akan error dengan pesan bersama "daftar argumen terlalu panjang".

Perhatikan bahwa input ke program (seperti yang dibaca di stdin atau deskriptor file lainnya) tidak dibatasi (hanya oleh resource program yang tersedia). Jadi, jika skrip shell Anda membaca string menjadi variabel, Anda tidak dibatasi oleh ARG_MAX. Pembatasan juga tidak berlaku untuk shell-builtins.

Jens
sumber
Jawaban yang bagus, namun saya ingin klarifikasi. Jika saya mendapatkan konstruksi cmd <<< "$LONG_VAR"dan nilai LONG_VAR melebihi batas, apakah perintah saya akan meledak?
Krzysztof Jabłoński
1
@ KrzysztofJabłoński Tidak mungkin, karena konten LONG_VARdikirimkan pada stdin - dan itu dilakukan seluruhnya di shell; itu tidak diperluas sebagai argumen untuk cmd, sehingga batas ARG_MAX untuk fork () / exec () tidak ikut bermain. Sangat mudah untuk mencoba sendiri: buat variabel dengan konten yang melebihi ARG_MAX dan jalankan perintah Anda.
Jens
2
Berikut klarifikasi, untuk catatan: untuk file m4a 8 megabyte, saya lakukan: blah="$(cat /home/schwager/Music/Recordings/20090420\ 131623.m4a)"; cat <<< $blah >/dev/null. Perhatikan tidak ada kesalahan.
Mike S
3
Peringatan kecil. Variabel lingkungan juga dihitung. sysconf manpage > Sulit untuk menggunakan ARG_MAX karena tidak ditentukan berapa banyak> ruang argumen untuk exec (3) yang dipakai oleh variabel lingkungan> pengguna.
Gerrit
3
@ user188737 Saya merasa ini adalah peringatan yang cukup besar di BUGS . Misalnya xargsdi MacOS 10.12.6 batas berapa banyak ia mencoba untuk dimasukkan ke dalam satu exec()untuk ARG_MAX - 4096. Jadi penggunaan skrip xargsmungkin berhasil, sampai suatu hari ketika seseorang menempatkan terlalu banyak barang di lingkungan. Mengalami ini sekarang (atasi dengan xargs -s ???:).
ahli saraf
44

Oke, Warga. Jadi saya telah menerima batas panjang baris perintah sebagai Injil untuk beberapa waktu. Lantas, apa hubungannya dengan asumsi seseorang? Tentu- periksa mereka.

Saya memiliki mesin Fedora 22 yang dapat saya gunakan (artinya: Linux dengan bash4). Saya telah membuat direktori dengan 500.000 inode (file) di dalamnya masing-masing sepanjang 18 karakter. Panjang baris perintah adalah 9.500.000 karakter. Dibuat demikian:

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

Dan kami mencatat:

$ getconf ARG_MAX
2097152

Catat bagaimanapun saya dapat melakukan ini:

$ echo * > /dev/null

Tapi ini gagal:

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

Saya bisa menjalankan for loop:

$ for f in *; do :; done

yang merupakan shell builtin lain.

Membaca dokumentasiARG_MAX dengan cermat untuk status, Panjang maksimum argumen ke fungsi exec . Artinya: Tanpa menelepon exec, tidak ada ARG_MAXbatasan. Jadi itu akan menjelaskan mengapa bawaan shell tidak dibatasi oleh ARG_MAX.

Dan memang, saya dapat lsdirektori saya jika daftar argumen saya adalah 109948 file, atau sekitar 2.089.000 karakter (memberi atau menerima). Setelah saya menambahkan satu lagi file nama file 18 karakter, maka saya mendapatkan kesalahan daftar Argument terlalu panjang . Begitu ARG_MAXjuga bekerja seperti yang diiklankan: exec gagal dengan lebih dari ARG_MAXkarakter pada daftar argumen - termasuk, harus dicatat, data lingkungan.

Mike S.
sumber
Hmm. Saya belum membaca jawaban yang ada untuk menyiratkan bahwa builtins tunduk pada kendala tersebut, tetapi pasti dapat melihat bagaimana seseorang bisa.
Charles Duffy
6
Ya, menurut saya sulit untuk diingat - terutama untuk pengguna baris perintah yang lebih baru - bahwa situasi pemanggilan bash builtin vs. fork / mengeksekusi perintah berbeda dengan cara yang tidak jelas. Saya ingin menjelaskannya. Satu pertanyaan yang selalu saya dapatkan dalam wawancara kerja (sebagai Linux Sysadmin) adalah, "Jadi saya mendapatkan banyak file dalam sebuah direktori. Bagaimana cara mengulang semuanya ..." Penanya selalu mengarahkan ke baris batas panjang dan menginginkan solusi find / while atau xargs. Di masa depan saya akan berkata, "ah neraka- gunakan saja for loop. Bisa mengatasinya!" :-)
Mike S
@MikeS sementara Anda dapat melakukan perulangan for, jika Anda dapat menggunakan kombo find-xargs, Anda akan memotong jauh lebih sedikit dan akan lebih cepat. ;-)
Lester Cheung
4
@LesterCheung for f in *; do echo $f; donetidak akan bercabang sama sekali (semua bawaan). Jadi saya tidak tahu bahwa kombo find-xargs akan lebih cepat; itu belum diuji. Memang, saya tidak tahu apa set masalah OP itu. Mungkin find /path/to/directorytidak akan berguna baginya karena itu akan mengembalikan nama path file. Mungkin dia menyukai kesederhanaan sebuah for f in *lingkaran. Terlepas dari itu, percakapannya adalah tentang batas input jalur - bukan efisiensi. Jadi mari kita tetap pada topik, yang berkaitan dengan panjang baris perintah.
Mike S
FWIW, masalahnya, seingat saya, hanya mencoba menulis shell di C, dan menentukan berapa lama saya harus mengizinkan input.
Derek Halden
-3

Ada batas buffer seperti 1024. Pembacaan hanya akan menggantung di pertengahan paste atau masukan. Untuk mengatasi ini gunakan opsi -e.

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

-e menggunakan Readline untuk mendapatkan baris dalam shell interaktif

Ubah bacaan Anda menjadi baca -e dan masukan baris yang mengganggu akan hilang.

Paul Kenjora
sumber
1
Ini bukan tentang read: "Yaitu apakah mungkin untuk menulis perintah di bash yang terlalu panjang untuk dieksekusi oleh baris perintah?"
Chai T.Rex
@ ChaiT.Rex Anda agak benar, tetapi inilah masalahnya: coba jalankan Bash secara interaktif tanpa Readline, yaitu bash --noediting, dan pada prompt baru coba jalankan perintah echo somereallylongword, di mana beberapa kata panjang biasanya lebih dari 4090 karakter. Mencoba di Ubuntu 18.04, kata itu terpotong, jadi jelas itu ada hubungannya dengan Readline tidak diaktifkan.
Amir
@Amir Menarik! Anda benar! Saya mencoba untuk mengedit jawabannya, tetapi kemudian saya menyadari bahwa opsi -e tidak berlaku untuk bash dalam konteks ini (dalam bash, ia langsung keluar dari shell saat terjadi kesalahan). Dan saya tidak yakin mengapa Paul berputar untuk membaca. Bagaimanapun, ada batas buffer antara 4-5000 karakter saat bash dimulai dengan --noreadline. Itu adalah efek samping yang tidak saya ketahui atau harapkan.
Mike S