“ Seznam argumentů je příliš dlouhý ”: Jak to zvládnu, aniž bych změnil svůj příkaz?

Když spustím příkaz jako ls */*/*/*/*.jpg, zobrazí se chyba

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

Vím, proč se to děje: je to proto, že v jádře existuje limit na velikost prostoru pro argumenty příkazu. Standardní rada je změnit příkaz, který používám, aby nevyžadovalo tolik prostoru pro argumenty (např. Použijte find a xargs).

Co když nechci příkaz změnit? Co když chci používat stejný příkaz? Jak mohu věci „prostě fungovat“, aniž by se mi zobrazila tato chyba? Jaká řešení jsou k dispozici?

Komentáře

  • Užitečné čtení: Bash FAQ 95 . beze změny příkazu ' toho není mnoho, co můžete udělat, kromě překompilování zvětšit maximální velikost seznamu argumentů nebo změnit strukturu adresáře tak, aby bylo méně souborů.
  • @ jw013 na základě verze linuxového jádra je možné zvětšit seznam argumentů – podrobnosti o změně v unix.stackexchange.com/a/45161/8979 nedávné systémy.
  • @UlrichDangel, jo, je to možné! Viz moje odpověď; moje odpověď ukazuje, jak to udělat (na L inux, s nedávným jádrem).

Odpověď

V systému Linux je maximální prostor pro příkaz argumenty je 1/4 množství dostupného prostoru zásobníku. Řešením je tedy zvětšit množství prostoru dostupného pro zásobník.

Krátká verze: spusťte něco jako

ulimit -s 65536 

Delší verze : Výchozí velikost prostoru dostupného pro zásobník je něco jako 8192 kB. Velikost dostupného prostoru můžete zobrazit následovně:

$ ulimit -s 8192 

Vyberte větší číslo a nastavte velikost dostupného prostoru pro zásobník. Chcete-li například zkusit povolit zásobníku až 65 536 kB, spusťte toto:

$ ulimit -s 65536 

Možná si budete muset pohrát s tím, jak velké to potřebuje být pomocí pokusu a omylu. V mnoha případech se jedná o rychlé a špinavé řešení, které eliminuje potřebu upravit příkaz a vypracovat syntaxi find, xargs atd. (i když si uvědomuji, že to má i jiné výhody).

Věřím, že se jedná o Linux. Mám podezření, že pravděpodobně nepomůže žádnému jinému operačnímu systému Unix (netestováno).

Komentáře

  • Takto můžete ověřit, že to fungovalo : $ getconf ARG_MAX 2097152 $ ulimit -s 65535 $ getconf ARG_MAX 16776960
  • Znamená to, že když udělám neomezenou velikost zásobníku s ulimit -s unlimited velikost příkazového řádku bude neomezený také?

Odpověď

Místo ls */*/*/*/*.jpg, zkuste:

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

xargs (1) ví, jaký je maximální počet argumentů v systému, a rozbije svůj standardní vstup, aby několikrát zavolal na zadaný příkazový řádek bez více argumentů, než je tento limit, ať už je jakýkoli (pomocí -n option).

Předpokládejme například, že limit jsou 3 argumenty a máte pět souborů. V takovém případě xargs provede ls dvakrát:

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

Často je to naprosto vhodné, ale ne vždy – například nemůžete spoléhejte na ls (1) třídění všech položek pro vás správně, protože každá samostatná ls -invocation roztřídí pouze podmnožinu položek, které mu byly přiděleny xargs.

Ačkoli můžete narazit na limit podle doporučení ostatních, stále bude existovat limit – a jednoho dne to vaše sbírka JPG přeroste znovu. Měli byste připravit své skripty, aby se vypořádaly s nekonečným počtem …

Komentáře

  • Díky za nápad! To není špatné řešení. Dvě upozornění: 1. Toto naruší adresáře a názvy souborů, které mají v názvu mezery, takže ' to není dokonalá náhrada. 2. Narazí to na stejný problém s Argument list too long, ale pro echo místo ls na skořápkách, kde echo není vestavěný příkaz prostředí? (Možná to ' ve většině mušlí není problém, takže to ' s není relevantní.)
  • Ano , speciální znaky v názvech souborů jsou problém. Nejlepším řešením je použít find s -print0 predikátem a přesměrovat jeho výstup do xargs s volbou -0.echo je vestavěný shell a netrpí omezením příkazového řádku exec (3).
  • Toto funguje s příkazy, které očekávají argument proměnné jako poslední parametr, například pro ls, ale co mám dělat, když chci mv mnoho souborů do jednoho adresáře, např mv * destdir? Pokud * dá " příliš mnoho chyb ", mohu ' xargs předat cesty jako první na mv nějak, nebo mohu?
  • Zkontrolujte manuálovou stránku xargs ve vašem systému – například na FreeBSD vám pomůže -J vás s tímto úkolem. Pokud ve vašem operačním systému neexistuje žádný způsob, jak ' pro změnu pořadí argumentů napsat vlastní skript. Něco jako: destdir=$1; shift; mv "$@" "$destdir". Poté dejte tento nový skript xargs: .... | xargs newscript $destdir

odpověď

Tento článek Linux Journal obsahuje 4 řešení. Pouze čtvrté řešení nezahrnuje změnu příkazu:

Metoda č. 4 zahrnuje ruční zvýšení počtu stránek, které jsou v jádře přiděleny pro příkazový řádek argumenty. Pokud se podíváte na soubor include / linux / binfmts.h, najdete v horní části následující:

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

Aby se zvětšilo množství paměti vyhrazené pro argumenty příkazového řádku, stačí zadat hodnotu MAX_ARG_PAGES s vyšším číslem. Jakmile je tato úprava uložena, jednoduše ji znovu zkompilujte, nainstalujte a restartujte do nového jádra, jako byste to dělali normálně.

Ve svém vlastním testovacím systému se mi podařilo vyřešit všechny mé problémy zvýšením této hodnoty na 64. Po rozsáhlém testování, nezažil jsem od přepnutí jediný problém. To je zcela očekáváno, protože i při MAX_ARG_PAGES nastaveném na 64 by nejdelší možný příkazový řádek, jaký jsem mohl vyrobit, zabíral pouze 256 kB systémové paměti – dnešními hardwarovými standardy systému to moc není .

Výhody metody č. 4 jsou jasné. Nyní můžete jednoduše spustit příkaz, jako byste normálně, a úspěšně se dokončí. Nevýhody jsou stejně jasné. Pokud zvýšíte množství dostupné paměti na příkazový řádek přesahující množství dostupné systémové paměti, můžete vytvořit útok DOS na svůj vlastní systém a způsobit jeho selhání. Zejména u víceuživatelských systémů může mít i malý nárůst významný dopad, protože každému uživateli je poté přidělen další paměť. Proto vždy důkladně otestujte ve svém vlastním prostředí, protože toto je nejbezpečnější způsob, jak zjistit, zda je pro vás metoda č. 4 životaschopnou volbou.

Souhlasím s tím, že omezení je vážně nepříjemné.

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *