“ Elenco di argomenti troppo lungo ”: come lo gestisco senza modificare il mio comando?

Quando eseguo un comando come ls */*/*/*/*.jpg, ottengo lerrore

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

So perché questo accade: è perché cè un limite del kernel sulla quantità di spazio per gli argomenti di un comando. Il consiglio standard è di cambiare il comando che utilizzo, per evitare di richiedere così tanto spazio per gli argomenti (ad esempio, usa find e xargs).

E se non volessi cambiare il comando? E se volessi continuare a usare lo stesso comando? Come posso fare in modo che le cose “funzionino” senza ricevere questo errore? Quali soluzioni sono disponibili?

Commenti

  • Letture utili: Bash FAQ 95 . Senza modificare il comando ‘ non puoi fare molto oltre a ricompilare per aumentare la dimensione massima dellelenco di argomenti o modificare la struttura della directory in modo che ci siano meno file.
  • @ jw013 in base alla versione del kernel Linux, potrebbe essere possibile aumentare lelenco degli argomenti – vedere unix.stackexchange.com/a/45161/8979 per i dettagli sulla modifica sistemi recenti.
  • @UlrichDangel, Sì, è possibile! Guarda la mia risposta; la mia risposta mostra come farlo (su L inux, con un kernel abbastanza recente).

Answer

Su Linux, la quantità massima di spazio per il comando argomenti è 1/4 della quantità di spazio disponibile nello stack. Quindi, una soluzione è aumentare la quantità di spazio disponibile per lo stack.

Versione breve: eseguire qualcosa di simile

ulimit -s 65536 

Versione più lunga : La quantità predefinita di spazio disponibile per lo stack è qualcosa come 8192 KB. Puoi vedere la quantità di spazio disponibile, come segue:

$ ulimit -s 8192 

Scegli un numero maggiore e imposta la quantità di spazio disponibile per lo stack. Ad esempio, se vuoi provare a consentire fino a 65536 KB per lo stack, esegui questo:

$ ulimit -s 65536 

Potrebbe essere necessario giocare con quanto grande è necessario essere, usando tentativi ed errori. In molti casi, questa è una soluzione rapida e sporca che eliminerà la necessità di modificare il comando e di elaborare la sintassi di find, xargs, ecc. (anche se mi rendo conto che ci sono altri vantaggi nel farlo).

Credo che questo sia specifico di Linux. Sospetto che probabilmente non sarà daiuto su nessun altro sistema operativo Unix (non testato).

Commenti

  • Puoi verificare in questo modo che ha funzionato : $ getconf ARG_MAX 2097152 $ ulimit -s 65535 $ getconf ARG_MAX 16776960
  • Significa che se imposto dimensioni illimitate con ulimit -s unlimited la dimensione della riga di comando sarà illimitato anche tu?

Risposta

Invece di ls */*/*/*/*.jpg, prova:

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

xargs (1) sa qual è il numero massimo di argomenti nel sistema e interromperà il suo input standard per chiamare più volte la riga di comando specificata senza più argomenti di quel limite, qualunque esso sia (puoi anche impostarlo su un valore inferiore al massimo del sistema operativo utilizzando -n opzione).

Per esempio, supponiamo che il limite sia di 3 argomenti e di avere cinque file. In tal caso, xargs eseguirà ls due volte:

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

Spesso è perfettamente adatto, ma non sempre – ad esempio, non puoi fare affidamento su ls (1) ordinamento di tutte le voci correttamente, perché ogni ls -invocazione separata ordinerà solo il sottoinsieme di voci assegnategli da xargs.

Sebbene tu possa superare il limite come suggerito da altri, ci sarà comunque un limite – e un giorno la tua collezione JPG diventerà di nuovo troppo grande. Dovresti preparare i tuoi script per gestire un numero infinito …

Commenti

  • Grazie per lidea! Questa non è una cattiva soluzione alternativa. Due avvertenze: 1. Questo non funziona con le directory e i nomi di file che hanno spazi nel nome, quindi ‘ non è un sostituto perfetto. 2. Si verificherà lo stesso problema con Argument list too long, ma per echo invece di ls, sulle shell in cui echo non è un comando incorporato della shell? (Forse ‘ non è un problema nella maggior parte delle shell, quindi forse ‘ è irrilevante.)
  • Sì , i caratteri speciali nei nomi dei file sono un problema. La soluzione migliore è utilizzare find con il -print0 predicato e convogliarne loutput in xargs con lopzione -0.echo è una shell incorporata e non soffre dei limiti della riga di comando di exec (3).
  • Funziona con i comandi che prevedono largomento della variabile come ultimo parametro, ad esempio per ls, ma cosa faccio quando voglio mv molti file in una singola directory, ad es mv * destdir? Se * restituisce ” troppi argomenti ” errore, posso ‘ per fare in qualche modo xargs passare i percorsi come primo a mv o posso?
  • Controlla la pagina man per xargs sul tuo sistema – su FreeBSD, ad esempio, -J ti aiuterà tu con questo compito. Se sul tuo sistema operativo non cè modo di farlo, ‘ dovrai scrivere uno script personalizzato per riordinare gli argomenti. Qualcosa come: destdir=$1; shift; mv "$@" "$destdir". Quindi dai questo nuovo script a xargs: .... | xargs newscript $destdir

Rispondi

Questo articolo di Linux Journal fornisce 4 soluzioni. Solo la quarta soluzione non comporta la modifica del comando:

Il metodo n. 4 prevede laumento manuale del numero di pagine allocate nel kernel per la riga di comando argomenti. Se guardi il file include / linux / binfmts.h, troverai quanto segue allinizio:

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

Per aumentare la quantità di memoria dedicato agli argomenti della riga di comando, è sufficiente fornire al valore MAX_ARG_PAGES un numero più alto. Una volta salvata questa modifica, è sufficiente ricompilare, installare e riavviare nel nuovo kernel come faresti normalmente.

Sul mio sistema di test sono riuscito a risolvere tutti i miei problemi aumentando questo valore a 64. Dopo un lungo periodo di tempo test, non ho riscontrato alcun problema dopo il passaggio. Questo è del tutto prevedibile poiché anche con MAX_ARG_PAGES impostato su 64, la riga di comando più lunga possibile che potrei produrre occuperebbe solo 256 KB di memoria di sistema, non molto per gli standard hardware di sistema odierni .

I vantaggi del Metodo n. 4 sono evidenti. Ora puoi semplicemente eseguire il comando come faresti normalmente e si completa con successo. Gli svantaggi sono altrettanto chiari. Se aumenti la quantità di memoria disponibile alla riga di comando oltre la quantità di memoria di sistema disponibile, è possibile creare un attacco DOS sul proprio sistema e provocarne il crash. Sui sistemi multiutente in particolare, anche un piccolo aumento può avere un impatto significativo perché a ogni utente viene quindi assegnato il memoria aggiuntiva. Pertanto, esegui sempre un test approfondito nel tuo ambiente, poiché questo è il modo più sicuro per determinare se il Metodo n. 4 è unopzione praticabile per te.

Sono daccordo che la limitazione è seriamente fastidiosa.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *