“ Argumentenlijst te lang ”: Hoe ga ik ermee om zonder mijn opdracht te wijzigen?

Wanneer ik een commando als ls */*/*/*/*.jpg uitvoer, krijg ik de foutmelding

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

Ik weet waarom dit gebeurt: het is omdat er een kernellimiet is voor de hoeveelheid ruimte voor argumenten voor een commando. Het standaardadvies is om het commando dat ik gebruik te wijzigen, om te voorkomen dat er zoveel ruimte nodig is voor argumenten (gebruik bijvoorbeeld find en xargs).

Wat moet ik doen als ik het commando niet wil wijzigen? Wat moet ik doen als ik hetzelfde commando wil blijven gebruiken? Hoe kan ik ervoor zorgen dat de dingen “gewoon werken”, zonder deze foutmelding te krijgen? Welke oplossingen zijn beschikbaar?

Reacties

  • Nuttig lezen: Bash FAQ 95 . Zonder je commando te wijzigen er ‘ is niet veel dat je kunt doen behalve hercompileren om de maximale grootte van je argumentlijst te vergroten, of je directorystructuur veranderen zodat er minder bestanden zijn.
  • @ jw013 gebaseerd op de linux-kernelversie kan het mogelijk zijn om de argumentlijst te vergroten – zie unix.stackexchange.com/a/45161/8979 voor details over de wijziging in recente systemen.
  • @UlrichDangel, Ja, het is mogelijk! Zie mijn antwoord; mijn antwoord laat zien hoe het moet (op L inux, met een kernel die recent genoeg is).

Answer

Onder Linux is de maximale hoeveelheid ruimte voor het commando argumenten is 1 / 4e van de beschikbare stapelruimte. Dus een oplossing is om de hoeveelheid beschikbare ruimte voor de stapel te vergroten.

Korte versie: voer zoiets uit

ulimit -s 65536 

Langere versie : De standaard hoeveelheid beschikbare ruimte voor de stapel is ongeveer 8192 KB. U kunt de beschikbare hoeveelheid ruimte als volgt zien:

$ ulimit -s 8192 

Kies een groter aantal en stel de hoeveelheid beschikbare ruimte voor de stapel in. Als u bijvoorbeeld wilt proberen om tot 65536 KB toe te staan voor de stapel, voert u dit uit:

$ ulimit -s 65536 

Het kan zijn dat u moet spelen met hoe groot dit nodig is met vallen en opstaan. In veel gevallen is dit een snelle oplossing waardoor de opdracht niet meer hoeft te worden aangepast en de syntaxis van find, xargs, enz. (hoewel ik me realiseer dat er andere voordelen aan verbonden zijn).

Ik geloof dat dit Linux-specifiek is. Ik vermoed dat het waarschijnlijk “niet zal helpen op een ander Unix-besturingssysteem (niet getest).

Opmerkingen

  • Je kunt op deze manier verifiëren dat het werkte : $ getconf ARG_MAX 2097152 $ ulimit -s 65535 $ getconf ARG_MAX 16776960
  • Betekent dit dat als ik de stapelgrootte onbeperkt maak met ulimit -s unlimited de grootte van de opdrachtregel zal zijn ook onbeperkt?

Answer

In plaats van ls */*/*/*/*.jpg, probeer:

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

xargs (1) weet wat het maximum aantal argumenten op het systeem is, en zal zijn standaardinvoer verbreken om de opgegeven opdrachtregel meerdere keren aan te roepen zonder meer argumenten dan die limiet, wat het ook is (je kunt het ook lager instellen dan het OS “maximum met behulp van de -n optie).

Stel dat de limiet 3 argumenten is en dat je vijf bestanden hebt. In dat geval zal xargs ls twee keer uitvoeren:

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

Vaak is dit perfect geschikt, maar niet altijd – u kunt bijvoorbeeld niet vertrouw op ls (1) sorteren alle ingangen correct voor u, omdat elk ls -invocation sorteert alleen de subset van items die eraan zijn gegeven door xargs.

Hoewel je de limiet kunt verhogen zoals voorgesteld door anderen, zal er nog steeds een limiet zijn – en op een dag zal je JPG-collectie er weer uit groeien. Je moet je script (s) voorbereiden om met een oneindig aantal om te gaan …

Reacties

  • Bedankt voor het idee! Dit is geen slechte oplossing. Twee kanttekeningen: 1. Dit breekt mappen en bestandsnamen met spaties in hun naam, dus het is ‘ geen perfecte vervanging. 2. Komt dat hetzelfde probleem tegen met Argument list too long, maar voor echo in plaats van ls, op shells waar echo geen in de shell ingebouwd commando is? (Misschien is dat ‘ geen probleem in de meeste shells, dus misschien is dat ‘ niet relevant.)
  • Ja , zijn speciale tekens in bestandsnamen een probleem. U kunt het beste find gebruiken met het -print0 -predikaat – en de uitvoer naar xargs met -0 optie.echo is een ingebouwde shell en heeft geen last van de opdrachtregelbeperking van exec (3).
  • Dit werkt met opdrachten die het variabele-argument verwachten als de laatste parameter, zoals voor ls, maar wat moet ik doen als ik mv veel bestanden naar een enkele map, bijv mv * destdir? Als * de ” te veel args ” -fout geeft, kan ik ‘ t make xargs om de paden als eerste door te geven aan mv op de een of andere manier, of kan ik?
  • Controleer de man-pagina voor xargs op uw systeem – op FreeBSD, bijvoorbeeld, de -J zal helpen u met deze taak. Als er op uw besturingssysteem geen manier is om dit te doen, moet u ‘ een aangepast script schrijven om de argumenten opnieuw te ordenen. Iets als: destdir=$1; shift; mv "$@" "$destdir". Geef dit nieuwe script vervolgens aan xargs: .... | xargs newscript $destdir

Antwoord

Dit Linux Journal-artikel geeft 4 oplossingen. Alleen de vierde oplossing omvat niet het wijzigen van de opdracht:

Methode # 4 omvat het handmatig verhogen van het aantal paginas dat binnen de kernel is toegewezen voor de opdrachtregel argumenten. Als je naar het include / linux / binfmts.h-bestand kijkt, zul je het volgende bovenaan vinden:

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

Om de hoeveelheid geheugen te vergroten toegewijd aan de opdrachtregelargumenten, hoeft u alleen de waarde MAX_ARG_PAGES een hoger nummer te geven. Zodra deze bewerking is opgeslagen, hercompileer, installeer en start u opnieuw op in de nieuwe kernel zoals u normaal zou doen.

Op mijn eigen testsysteem slaagde ik erin al mijn problemen op te lossen door deze waarde te verhogen naar 64. Na uitgebreide testen, heb ik sinds de overstap geen enkel probleem ondervonden. Dit is volledig te verwachten, want zelfs met MAX_ARG_PAGES ingesteld op 64, zou de langst mogelijke opdrachtregel die ik kon produceren slechts 256 KB systeemgeheugen in beslag nemen – niet erg veel volgens de huidige hardwarestandaarden .

De voordelen van methode # 4 zijn duidelijk. U kunt nu de opdracht gewoon uitvoeren zoals u normaal zou doen, en deze wordt met succes voltooid. De nadelen zijn even duidelijk. Als u de hoeveelheid beschikbaar geheugen verhoogt aan de opdrachtregel voorbij de beschikbare hoeveelheid systeemgeheugen, kunt u een DOS-aanval op uw eigen systeem uitvoeren en ervoor zorgen dat het crasht. Vooral op systemen met meerdere gebruikers kan zelfs een kleine toename een aanzienlijke impact hebben omdat elke gebruiker dan de extra geheugen. Test daarom altijd uitgebreid in uw eigen omgeving, aangezien dit de veiligste manier is om te bepalen of methode # 4 een haalbare optie voor u is.

Ik ben het ermee eens dat de beperking ernstig vervelend is.

Geef een reactie

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *