perché per loop non genera l'errore "argomento troppo lungo"?


9

Ho scoperto che ciò solleverebbe l'errore "argomento troppo lungo":

ls *.*

E questo non lo solleverebbe:

for file in *.*
do
    echo $file
done

Perché?


Hai usato la stessa shell in entrambi gli esperimenti? Forse /bin/bashvs. /bin/sh(che è forse un collegamento a trattino)?
maxschlepzig,

Sì, ho fatto l'esperimento con 10000 file con nome file che sono piuttosto lunghi. "ls *" non riuscito e "for f in *" riuscito.
lamwaiman1988,

Risposte:


13

L'errore "argomento troppo lungo" viene E2BIGgenerato dalla execvechiamata di sistema se la dimensione totale degli argomenti (più l'ambiente, su alcuni sistemi) è troppo grande. La execvechiamata è quella che avvia processi esterni, in particolare caricando un altro file eseguibile (c'è una chiamata diversa fork, per eseguire un processo separato il cui codice è ancora dallo stesso file eseguibile). Il forciclo è un costrutto di shell interno, quindi non comporta la chiamata execve. Il comando ls *.*genera l'errore non quando il glob viene espanso ma quando lsviene chiamato.

execvefallisce con l'errore E2BIGquando la dimensione totale degli argomenti del comando è maggiore del ARG_MAX limite . Puoi vedere il valore di questo limite sul tuo sistema con il comando getconf ARG_MAX. (È possibile che sia possibile superare questo limite se si dispone di memoria sufficiente; mantenere sotto ARG_MAXgaranzie che execvefunzioneranno fino a quando non si verifica alcun errore non correlato.)


e perché shell non ha un limite?
lamwaiman1988,

1
@ gunbuster363 Il execvelimite viene imposto dal kernel, pone dei limiti perché gli argomenti devono essere copiati tramite la memoria del kernel in un punto e i processi utente non possono richiedere una quantità arbitraria di memoria della shell. All'interno della shell, non c'è motivo di avere limiti, tutto ciò che si adatta alla memoria virtuale va bene.
Gilles 'SO- smetti di essere malvagio' il

5

Suppongo che nel primo esempio lssia eseguito da bashuna chiamata di sistema fork/ execpair, nel secondo, tutto il lavoro è interno bash.

La execchiamata ha dei limiti, il funzionamento interno bashinvece non ha (o meglio, ha limiti diversi che non hanno nulla a che fare con exec, forse la quantità di memoria disponibile).


È possibile trovare il limite a execin /usr/include/linux/limits.hgenere, definito come ARG_MAX.
jw013,

Se utilizziamo la shell per loop, pensi che un grande elenco di elementi consumerà tutta la RAM?
lamwaiman1988,

Questa risposta non è corretta Non è "interno", è solo che i limiti per argomenti e comandi sono diversi.
polinomio,

5

Perché in questo caso lsè un argomento e il numero di argomenti è limitato.

Nel caso del forciclo, è solo un elenco di elementi. Non ci sono limiti (per quanto ne so) per questo.


C'è sicuramente un limite per l'espansione della shell. È molto correlato alla quantità di RAM disponibile. Prova questo; il mio sistema RAM da 4 GB soffia una guarnizione a circa 15,2 milioni di args a 8 byte:for i in {00000001..20000000} ;do ((10#$i==1)) && break; done
Peter.O

4
@fred Non pensavo davvero che fosse necessario menzionare la RAM come limite.
Šimon Tóth,

2
Potrebbe non essere necessario, ma questa è la natura dei commenti .. qualcuno potrebbe trovarlo interessante o addirittura di valore.
Peter.O

@fred: effettivamente sì, se espandere argomenti molto grandi fosse un problema comune, sarebbe possibile implementarlo senza tenere tutto in memoria.
Matteo,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.