“ Argumentlisten er for lang ”: Hvordan håndterer jeg den uden at ændre min kommando?

Når jeg kører en kommando som ls */*/*/*/*.jpg, får jeg fejlen

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

Jeg ved, hvorfor dette sker: det er fordi der er en kernelgrænse for mængden af plads til argumenter til en kommando. Standardrådet er at ændre den kommando, jeg bruger, for at undgå at kræve så meget plads til argumenter (f.eks. Brug find og xargs).

Hvad hvis jeg ikke vil ændre kommandoen? Hvad hvis jeg vil fortsætte med at bruge den samme kommando? Hvordan kan jeg få tingene til at “bare fungere” uden at få denne fejl? Hvilke løsninger er tilgængelige?

Kommentarer

  • Nyttig læsning: Bash FAQ 95 . Uden at ændre din kommando der er ' ikke meget, du kan udover genkompilere for at øge din maksimale størrelse på argumentlisten eller ændre din bibliotekstruktur, så der er færre filer.
  • @ jw013 baseret på Linux-kerneversionen kan det være muligt at øge argumentlisten – se unix.stackexchange.com/a/45161/8979 for detaljer om ændringen i nylige systemer.
  • @UlrichDangel, Yup, det er muligt! Se mit svar; mit svar viser, hvordan man gør det (på L inux, med en nyere kerne).

Svar

På Linux er den maksimale plads til kommando argumenter er 1/4 af mængden af tilgængelig stakplads. Så en løsning er at øge mængden af ledig plads til stakken.

Kort version: kør noget som

ulimit -s 65536 

Længere version : Standardmængden af ledig plads til stakken er omtrent 8192 KB. Du kan se mængden af ledig plads som følger:

$ ulimit -s 8192 

Vælg et større antal, og indstil den tilgængelige plads til stakken. Hvis du f.eks. Vil prøve at tillade op til 65536 KB til stakken, skal du køre dette:

$ ulimit -s 65536 

Det kan være nødvendigt at lege med, hvor stort dette har brug for at være ved hjælp af prøve-og-fejl. I mange tilfælde er dette en hurtig og snavset løsning, der eliminerer behovet for at ændre kommandoen og udarbejde syntaksen for find, xargs osv. (selvom jeg er klar over, at der er andre fordele ved at gøre det).

Jeg mener, at dette er Linux-specifikt. Jeg formoder, at det sandsynligvis ikke hjalp noget andet Unix-operativsystem (ikke testet).

Kommentarer

  • Du kan bekræfte, at det fungerede sådan : $ getconf ARG_MAX 2097152 $ ulimit -s 65535 $ getconf ARG_MAX 16776960
  • Betyder dette, at hvis jeg gør stacksstørrelsen ubegrænset med ulimit -s unlimited, vil kommandolinjestørrelsen være også ubegrænset?

Svar

I stedet for ls */*/*/*/*.jpg, prøv:

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

xargs (1) ved, hvad det maksimale antal argumenter er på systemet, og bryder sin standardindgang for at kalde den angivne kommandolinje flere gange uden flere argumenter end den grænse, uanset hvad den er (du kan også indstille den lavere end OS “maksimum ved hjælp af -n option).

Antag for eksempel, at grænsen er 3 argumenter, og du har fem filer. I så fald udfører xargs ls to gange:

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

Dette er ofte perfekt, men ikke altid – for eksempel kan du ikke stole på ls (1) sortering alle poster for dig korrekt, fordi hver separat ls -invokation vil kun sortere delsættet af poster, der gives til det af xargs.

Selvom du kan støde på grænsen som foreslået af andre, vil der stadig være en grænse – og en dag vil din JPG-samling vokse ud igen. Du skal forberede dine script (er) til at håndtere et uendeligt antal …

Kommentarer

  • Tak for ideen! Dette er ikke en dårlig løsning. To forbehold: 1. Dette bryder på mapper og filnavne, der har mellemrum i deres navn, så det ' er ikke en perfekt erstatning. 2. Vil det løbe ind i det samme problem med Argument list too long, men for echo i stedet for ls, på skaller hvor echo ikke er en shell-indbygget kommando? (Måske er ' ikke et problem i de fleste skaller, så måske er det ' irrelevant.)
  • Ja , specialtegn i filnavne er et problem. Dit bedste valg er at bruge find med -print0 predikatet – og rør dets output i xargs med -0 mulighed.echo er en indbygget shell og lider ikke under kommandolinjebegrænsningen på exec (3).
  • Dette fungerer med kommandoer, der forventer variabelargumentet som den sidste parameter, f.eks. for ls, men hvad skal jeg gøre, når jeg vil mv mange filer til en enkelt dir, f.eks mv * destdir? Hvis * giver " for mange args " fejl, kan jeg ' t gør xargs til at passere stierne som første til mv på en eller anden måde, eller kan jeg?
  • Kontroller man-siden for xargs på dit system – på FreeBSD vil f.eks. -J hjælpe dig med denne opgave. Hvis der ikke er nogen måde at gøre dette på dit operativsystem, skal du ' skal skrive et brugerdefineret script for at omarrangere argumenterne. Noget som: destdir=$1; shift; mv "$@" "$destdir". Giv derefter dette nye script til xargs: .... | xargs newscript $destdir

Svar

Denne Linux Journal-artikel giver 4 løsninger. Kun den fjerde løsning involverer ikke ændring af kommandoen:

Metode # 4 involverer manuelt at øge antallet af sider, der er allokeret inden for kernen til kommandolinje argumenter. Hvis du ser på filen include / linux / binfmts.h, finder du følgende tæt på toppen:

/* * 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 

For at øge mængden af hukommelse dedikeret til kommandolinjeargumenterne, skal du blot angive MAX_ARG_PAGES-værdien med et højere tal. Når denne redigering er gemt, skal du blot kompilere, installere og genstarte i den nye kerne, som du normalt ville.

På mit eget testsystem lykkedes det mig at løse alle mine problemer ved at hæve denne værdi til 64. Efter omfattende testning, jeg har ikke oplevet et eneste problem siden skiftet. Dette forventes fuldstændigt, da selv med MAX_ARG_PAGES indstillet til 64, ville den længst mulige kommandolinje, jeg kunne producere, kun optage 256 KB systemhukommelse – ikke meget efter nutidens systemhardwarestandarder .

Fordelene ved metode nr. 4 er klare. Du er nu i stand til simpelthen at køre kommandoen som normalt, og den fuldføres med succes. Ulemperne er lige så klare. Hvis du hæver den tilgængelige hukommelse til kommandolinjen ud over mængden af tilgængelig systemhukommelse, kan du oprette et DOS-angreb på dit eget system og få det til at gå ned. På især system med flere brugere kan selv en lille stigning have en betydelig indvirkning, fordi hver bruger derefter tildeles ekstra hukommelse. Test derfor altid udførligt i dit eget miljø, da dette er den sikreste måde at afgøre, om metode nr. 4 er en levedygtig mulighed for dig.

Jeg er enig i, at begrænsningen er alvorligt irriterende.

Skriv et svar

Din e-mailadresse vil ikke blive publiceret. Krævede felter er markeret med *