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:
-
ls 1.jpg 2.jpg 3.jpg
-
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 voorecho
in plaats vanls
, op shells waarecho
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 naarxargs
met-0
optie.echo
is een ingebouwde shell en heeft geen last van de opdrachtregelbeperking vanexec
(3). - Dit werkt met opdrachten die het variabele-argument verwachten als de laatste parameter, zoals voor
ls
, maar wat moet ik doen als ikmv
veel bestanden naar een enkele map, bijvmv * destdir
? Als*
de ” te veel args ” -fout geeft, kan ik ‘ t makexargs
om de paden als eerste door te geven aanmv
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 aanxargs
:.... | 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.