“ Lista de argumente prea lungă ”: Cum mă descurc, fără să-mi schimb comanda?

Când execut o comandă precum ls */*/*/*/*.jpg, primesc eroarea

-bash: /bin/ls: Argument list too long 

Știu de ce se întâmplă acest lucru: se datorează faptului că există o limită de kernel pentru cantitatea de spațiu pentru argumentele unei comenzi. Sfatul standard este să schimb comanda pe care o folosesc, pentru a evita necesitatea unui spațiu atât de mare pentru argumente (de exemplu, utilizați find și xargs).

Ce se întâmplă dacă nu vreau să schimb comanda? Ce se întâmplă dacă vreau să continui să folosesc aceeași comandă? Cum pot face ca lucrurile să funcționeze doar fără a primi această eroare? Ce soluții sunt disponibile?

Comentarii

  • Lectură utilă: FAQ Bash 95 . Fără să vă modificați comanda ‘ nu puteți face prea multe în afară de recompilare pentru a crește dimensiunea maximă a listei de argumente sau pentru a vă schimba structura directorului astfel încât să existe mai puține fișiere.
  • @ jw013 pe baza versiunii kernel-ului Linux, poate fi posibilă mărirea listei de argumente – consultați unix.stackexchange.com/a/45161/8979 pentru detalii despre modificarea sisteme recente.
  • @UlrichDangel, Da, este posibil! Vedeți răspunsul meu; răspunsul meu arată cum să o faceți (pe L inux, cu un nucleu suficient de recent).

Răspuns

Pe Linux, cantitatea maximă de spațiu pentru comandă argumentele reprezintă 1/4 din cantitatea de spațiu disponibilă în stivă. Deci, o soluție este creșterea spațiului disponibil pentru stivă.

Versiune scurtă: rulați ceva de genul

ulimit -s 65536 

Versiune mai lungă : Cantitatea implicită de spațiu disponibil pentru stivă este ceva de genul 8192 KB. Puteți vedea cantitatea de spațiu disponibil, după cum urmează:

$ ulimit -s 8192 

Alegeți un număr mai mare și setați spațiul disponibil pentru stivă. De exemplu, dacă doriți să încercați să permiteți până la 65536 KB pentru stivă, rulați acest lucru:

$ ulimit -s 65536 

Poate că va trebui să vă jucați cu cât de mare are acest lucru a fi, folosind încercări și erori. În multe cazuri, aceasta este o soluție rapidă și murdară care va elimina necesitatea de a modifica comanda și de a stabili sintaxa find, xargs etc. (deși îmi dau seama că există și alte avantaje în a face acest lucru).

Cred că acesta este specific Linux. Bănuiesc că probabil nu va ajuta pe niciun alt sistem de operare Unix (nu a fost testat).

Comentarii

  • Puteți verifica astfel că a funcționat : $ getconf ARG_MAX 2097152 $ ulimit -s 65535 $ getconf ARG_MAX 16776960
  • Asta înseamnă că dacă fac dimensiunea stacks nelimitată cu ulimit -s unlimited dimensiunea liniei de comandă va fi și nelimitat?

Răspuns

În loc de ls */*/*/*/*.jpg, încercați:

echo */*/*/*/*.jpg | xargs ls 

xargs (1) știe, care este numărul maxim de argumente pe sistem și va rupe intrarea sa standard pentru a apela linia de comandă specificată de mai multe ori fără mai multe argumente decât acea limită, oricare ar fi aceasta (puteți, de asemenea, să o setați mai jos decât sistemul de operare „maxim folosind -n opțiune).

De exemplu, să presupunem că limita este de 3 argumente și aveți cinci fișiere. În acest caz, xargs va executa ls de două ori:

  1. ls 1.jpg 2.jpg 3.jpg
  2. ls 4.jpg 5.jpg

Adesea acest lucru este perfect potrivit, dar nu întotdeauna – de exemplu, nu puteți mizați pe ls (1) sortând toate intrările pentru dvs. în mod corespunzător, deoarece fiecare ls -invocation va sorta numai subsetul de intrări dat de xargs.

Deși puteți limita limita așa cum sugerează alții, va exista totuși o limită – iar într-o zi, colecția dvs. JPG o va depăși din nou. Ar trebui să vă pregătiți scriptul (scripturile) pentru a face față unui număr infinit …

Comentarii

  • Vă mulțumim pentru idee! Aceasta nu este o soluție proastă. Două avertismente: 1. Acest lucru se aplică directoarelor și numele fișierelor care au spații în numele lor, deci ‘ nu este un substitut perfect. 2. Va întâlni aceeași problemă cu Argument list too long, dar pentru echo în loc de ls, pe shell-uri unde echo nu este o comandă încorporată în shell? (Poate că ‘ nu este o problemă în majoritatea shell-urilor, deci poate că ‘ este irelevant.)
  • Da , caracterele speciale din numele fișierelor reprezintă o problemă. Cel mai bun pariu este să utilizați find cu predicatul -print0 – și să introduceți ieșirea în xargs cu opțiunea -0.echo este un shell încorporat și nu suferă de limitarea liniei de comandă a exec (3).
  • Acest lucru funcționează cu comenzi care așteaptă ca argumentul variabilei să fie ultimul parametru, cum ar fi pentru ls, dar ce trebuie să fac când vreau să mv multe fișiere într-un singur director, de ex mv * destdir? Dacă * dă ” prea multe argumente ” eroare, pot ‘ nu faceți ca xargs să treacă căile ca primul la mv cumva, sau pot?
  • Verificați pagina de manual pentru xargs pe sistemul dvs. – pe FreeBSD, de exemplu, -J vă va ajuta tu cu această sarcină. Dacă pe sistemul dvs. de operare nu există nicio modalitate de a face acest lucru, ‘ va trebui să scrieți un script personalizat pentru a reordona argumentele. Ceva de genul: destdir=$1; shift; mv "$@" "$destdir". Apoi dați acest nou script xargs: .... | xargs newscript $destdir

Răspuns

Acest articol din Jurnalul Linux oferă 4 soluții. Doar a patra soluție nu implică schimbarea comenzii:

Metoda # 4 implică creșterea manuală a numărului de pagini alocate în nucleu pentru linia de comandă argumente. Dacă vă uitați la fișierul include / linux / binfmts.h, veți găsi următoarele în partea de sus:

/* * MAX_ARG_PAGES defines the number of pages allocated for arguments * and envelope for the new program. 32 should suffice, this gives * a maximum env+arg of 128kB w/4KB pages! */ #define MAX_ARG_PAGES 32 

Pentru a crește cantitatea de memorie dedicat argumentelor din linia de comandă, trebuie pur și simplu să furnizați valoarea MAX_ARG_PAGES cu un număr mai mare. Odată ce această editare este salvată, pur și simplu recompilați, instalați și reporniți în noul kernel așa cum ați face în mod normal.

Pe propriul meu sistem de testare am reușit să-mi rezolv toate problemele ridicând această valoare la 64. După extinderea testare, nu am experimentat o singură problemă de la comutare. Acest lucru este în întregime așteptat, deoarece chiar și cu MAX_ARG_PAGES setat la 64, cea mai lungă linie de comandă posibilă pe care aș putea să o produc ar ocupa doar 256 KB de memorie de sistem – nu prea mult până la standardele hardware de sistem de astăzi .

Avantajele Metodei # 4 sunt clare. Acum puteți rula pur și simplu comanda așa cum ați face în mod normal și se finalizează cu succes. Dezavantajele sunt la fel de clare. Dacă creșteți cantitatea de memorie disponibilă la linia de comandă dincolo de cantitatea de memorie de sistem disponibilă, puteți crea un atac DOS pe propriul sistem și îl puteți prăbuși. În special pe sistemele multi-utilizator, chiar și o mică creștere poate avea un impact semnificativ, deoarece fiecărui utilizator i se alocă apoi memorie suplimentară. Prin urmare, testați întotdeauna extensiv în propriul mediu, deoarece acesta este cel mai sigur mod de a determina dacă Metoda # 4 este o opțiune viabilă pentru dvs.

Sunt de acord că limitarea este foarte enervantă.

Lasă un răspuns

Adresa ta de email nu va fi publicată. Câmpurile obligatorii sunt marcate cu *