“ Argumentlisten er for lang ”: Hvordan takler jeg det uten å endre kommandoen?

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

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

Jeg vet hvorfor dette skjer: det er fordi det er en kjernegrense på mengden plass for argumenter til en kommando. Standardrådet er å endre kommandoen jeg bruker, for å unngå å kreve så mye plass for argumenter (f.eks. Bruk find og xargs).

Hva om jeg ikke vil endre kommandoen? Hva om jeg vil fortsette å bruke den samme kommandoen? Hvordan kan jeg få ting til å «bare fungere» uten å få denne feilen? Hvilke løsninger er tilgjengelige?

Kommentarer

  • Nyttig lesing: Vanlige spørsmål om Bash 95 . Uten å endre kommandoen det er ' ikke mye du kan gjøre foruten å kompilere for å øke argumentlistens maksimale størrelse, eller endre katalogstrukturen slik at det blir færre filer.
  • @ jw013 basert på Linux-kjerneversjonen kan det være mulig å øke argumentlisten – se unix.stackexchange.com/a/45161/8979 for detaljer om endringen i nylige systemer.
  • @UlrichDangel, Yup, det er mulig! Se svaret mitt; svaret mitt viser hvordan du gjør det (på L inux, med en nylig nok kjerne).

Svar

På Linux er maksimum plass for kommando argumenter er 1/4 av mengden tilgjengelig stabelplass. Så, en løsning er å øke mengden tilgjengelig plass for stakken.

Kortversjon: kjør noe sånt som

ulimit -s 65536 

Lengre versjon : Standard plass tilgjengelig for stakken er omtrent 8192 KB. Du kan se hvor mye plass som er tilgjengelig, som følger:

$ ulimit -s 8192 

Velg et større tall, og angi hvor mye plass som er tilgjengelig for stakken. Hvis du for eksempel vil prøve å tillate opptil 65536 kB for stakken, kan du kjøre denne:

$ ulimit -s 65536 

Du må kanskje leke med hvor stort dette trenger å være, ved hjelp av prøving og feiling. I mange tilfeller er dette en rask og skitten løsning som vil eliminere behovet for å endre kommandoen og utarbeide syntaksen til find, xargs osv. (selv om jeg er klar over at det er andre fordeler ved å gjøre det).

Jeg tror at dette er Linux-spesifikt. Jeg mistenker at det sannsynligvis ikke vil hjelpe på noe annet Unix-operativsystem (ikke testet).

Kommentarer

  • Du kan bekrefte at dette fungerte : $ getconf ARG_MAX 2097152 $ ulimit -s 65535 $ getconf ARG_MAX 16776960
  • Betyr dette at hvis jeg gjør stakkstørrelsen ubegrenset med ulimit -s unlimited vil kommandolinjestørrelsen være ubegrenset også?

Svar

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

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

xargs (1) vet, hva det maksimale antallet argumenter er på systemet, og vil bryte opp standardinngangen for å ringe den angitte kommandolinjen flere ganger uten flere argumenter enn den grensen, uansett hva den er (du kan også sette den lavere enn OS «maksimum ved hjelp av -n alternativ).

Anta for eksempel at grensen er 3 argumenter og at du har fem filer. I så fall vil xargs utføre ls to ganger:

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

Dette er ofte perfekt, men ikke alltid – for eksempel kan du ikke stole på ls (1) sortering alle oppføringene for deg riktig, fordi hver separate ls -innkalling vil bare sortere delsettet av oppføringene gitt av xargs.

Selv om du kan støte på grensen som foreslått av andre, vil det fortsatt være en grense – og en dag vil JPG-samlingen din vokse ut igjen. Du bør forberede skriptet ditt for å takle et uendelig antall …

Kommentarer

  • Takk for ideen! Dette er ikke en dårlig løsning. To forbehold: 1. Dette bryter på kataloger og filnavn som har mellomrom i navnet sitt, så det ' er ikke en perfekt erstatning. 2. Skal det løpe inn i det samme problemet med Argument list too long, men for echo i stedet for ls, på skjell der echo ikke er en innebygd shell-kommando? (Kanskje det ikke er ' i de fleste skjell, så kanskje det er ' som ikke er relevant.)
  • Ja , spesialtegn i filnavn er et problem. Det beste alternativet er å bruke find med -print0 predikatet – og rør utgangen til xargs med -0 alternativ.echo er et innebygd skall og lider ikke av kommandolinjebegrensningen til exec (3).
  • Dette fungerer med kommandoer som forventer variabelargumentet som siste parameter, for eksempel for ls, men hva gjør jeg når jeg vil mv mange filer til en enkelt dir, f.eks mv * destdir? Hvis * gir " for mange args " feil, kan jeg ' t får xargs til å passere stiene som første til mv på en eller annen måte, eller kan jeg?
  • Sjekk man-siden for xargs på systemet ditt – på FreeBSD, for eksempel, vil -J hjelpe deg med denne oppgaven. Hvis det ikke er noen måte å gjøre dette på operativsystemet ditt, må du ' skrive et tilpasset skript for å omorganisere argumentene. Noe som: destdir=$1; shift; mv "$@" "$destdir". Gi deretter dette nye skriptet til xargs: .... | xargs newscript $destdir

Svar

Denne Linux Journal-artikkelen gir 4 løsninger. Bare den fjerde løsningen innebærer ikke å endre kommandoen:

Metode # 4 innebærer manuelt å øke antall sider som er tildelt i kjernen for kommandolinje argumenter. Hvis du ser på include / linux / binfmts.h-filen, finner du følgende nær 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 å øke mengden minne dedikert til kommandolinjeargumentene, trenger du bare å oppgi MAX_ARG_PAGES-verdien med et høyere tall. Når denne redigeringen er lagret, er det bare å kompilere på nytt, installere og starte på nytt i den nye kjernen som du ville gjort normalt.

På mitt eget testsystem klarte jeg å løse alle problemene mine ved å heve denne verdien til 64. Etter omfattende testing har jeg ikke opplevd et eneste problem siden byttet. Dette er helt forventet siden selv med MAX_ARG_PAGES satt til 64, ville den lengst mulige kommandolinjen jeg kunne produsere bare oppta 256 kB systemminne – ikke veldig mye av dagens systemhardwarestandarder .

Fordelene med metode nr. 4 er tydelige. Du kan nå bare kjøre kommandoen som normalt, og den fullføres vellykket. Ulempene er like klare. Hvis du øker mengden tilgjengelig minne til kommandolinjen utover mengden tilgjengelig systemminne, kan du opprette et DOS-angrep på ditt eget system og få det til å krasje. På spesielt flerbrukssystemer kan til og med en liten økning ha en betydelig innvirkning fordi hver bruker deretter tildeles ekstra minne. Test derfor alltid omfattende i ditt eget miljø, da dette er den tryggeste måten å avgjøre om Metode # 4 er et levedyktig alternativ for deg.

Jeg er enig i at begrensningen er alvorlig irriterende.

Legg igjen en kommentar

Din e-postadresse vil ikke bli publisert. Obligatoriske felt er merket med *