Haben Sie in beiden Experimenten dieselbe Schale verwendet? Vielleicht /bin/bashvs. /bin/sh(was ist vielleicht ein Link zum Bindestrich)?
Maxschlepzig
Ja, ich habe das Experiment mit 10000 Dateien mit Dateinamen durchgeführt, die ziemlich lang sind. "ls *" ist fehlgeschlagen und "for f in *" war erfolgreich.
Lamwaiman1988
Antworten:
13
Der Fehler "Argument zu lang" wird E2BIGvom execveSystemaufruf ausgelöst, wenn die Gesamtgröße der Argumente (plus der Umgebung auf einigen Systemen) zu groß ist. Der execveAufruf ist derjenige, der externe Prozesse startet, insbesondere das Laden einer anderen ausführbaren Datei (es gibt einen anderen Aufruf fork, um einen separaten Prozess auszuführen, dessen Code immer noch aus derselben ausführbaren Datei stammt). Die forSchleife ist ein internes Shell-Konstrukt und beinhaltet keinen Aufruf execve. Der Befehl ls *.*löst den Fehler nicht aus, wenn der Glob erweitert wird, sondern wenn er lsaufgerufen wird.
execveschlägt mit dem Fehler fehl, E2BIGwenn die Gesamtgröße der Argumente für den Befehl größer als das ARG_MAXLimit ist . Mit dem Befehl können Sie den Wert dieses Grenzwerts auf Ihrem System anzeigen getconf ARG_MAX. (Es ist möglich, dass Sie diese Grenze überschreiten können, wenn Sie über genügend Speicher verfügen. Halten Sie die ARG_MAXGarantien ein, execvedie funktionieren, solange kein Fehler auftritt.)
@ gunbuster363 Das execveLimit wird vom Kernel erzwungen, es setzt Limits, da die Argumente an einer Stelle über den Kernelspeicher kopiert werden müssen und Benutzerprozesse keine beliebige Menge an Shell-Speicher anfordern dürfen. Innerhalb der Shell gibt es keinen Grund, ein Limit zu haben. Alles, was in den virtuellen Speicher passt, ist in Ordnung.
Gilles 'SO - hör auf böse zu sein'
5
Ich nehme an, dass im ersten Beispiel über einen / pair-Systemaufruf ausgeführt wird, im zweiten Beispiel lsist die gesamte Arbeit intern .bashforkexecbash
Der execAufruf hat Grenzen, die interne Arbeitsweise bashstattdessen nicht (oder besser gesagt, hat verschiedene Grenzen, die nichts damit zu tun haben exec, vielleicht die Menge des verfügbaren Speichers).
Es gibt definitiv eine Grenze für die Shell-Erweiterung. Es hängt sehr stark davon ab, wie viel RAM Ihnen zur Verfügung steht. Versuchen Sie dies; Mein 4 GB RAM-System bläst eine Dichtung bei etwa 15,2 Millionen 8-Byte-Argumenten:for i in {00000001..20000000} ;do ((10#$i==1)) && break; done
Peter.O
4
@fred Ich dachte nicht wirklich, dass es notwendig ist, RAM als Limit zu erwähnen.
Šimon Tóth
2
Es wird vielleicht nicht benötigt, aber das ist die Natur von Kommentaren. Jemand mag es interessant oder sogar von Wert finden.
Peter.O
@fred: Eigentlich ja, wenn das Erweitern sehr großer Argumente ein häufiges Problem wäre, wäre es möglich, es zu implementieren, ohne alles im Speicher zu behalten.
/bin/bash
vs./bin/sh
(was ist vielleicht ein Link zum Bindestrich)?Antworten:
Der Fehler "Argument zu lang" wird
E2BIG
vomexecve
Systemaufruf ausgelöst, wenn die Gesamtgröße der Argumente (plus der Umgebung auf einigen Systemen) zu groß ist. Derexecve
Aufruf ist derjenige, der externe Prozesse startet, insbesondere das Laden einer anderen ausführbaren Datei (es gibt einen anderen Aufruffork
, um einen separaten Prozess auszuführen, dessen Code immer noch aus derselben ausführbaren Datei stammt). Diefor
Schleife ist ein internes Shell-Konstrukt und beinhaltet keinen Aufrufexecve
. Der Befehlls *.*
löst den Fehler nicht aus, wenn der Glob erweitert wird, sondern wenn erls
aufgerufen wird.execve
schlägt mit dem Fehler fehl,E2BIG
wenn die Gesamtgröße der Argumente für den Befehl größer als dasARG_MAX
Limit ist . Mit dem Befehl können Sie den Wert dieses Grenzwerts auf Ihrem System anzeigengetconf ARG_MAX
. (Es ist möglich, dass Sie diese Grenze überschreiten können, wenn Sie über genügend Speicher verfügen. Halten Sie dieARG_MAX
Garantien ein,execve
die funktionieren, solange kein Fehler auftritt.)quelle
execve
Limit wird vom Kernel erzwungen, es setzt Limits, da die Argumente an einer Stelle über den Kernelspeicher kopiert werden müssen und Benutzerprozesse keine beliebige Menge an Shell-Speicher anfordern dürfen. Innerhalb der Shell gibt es keinen Grund, ein Limit zu haben. Alles, was in den virtuellen Speicher passt, ist in Ordnung.Ich nehme an, dass im ersten Beispiel über einen / pair-Systemaufruf ausgeführt wird, im zweiten Beispiel
ls
ist die gesamte Arbeit intern .bash
fork
exec
bash
Der
exec
Aufruf hat Grenzen, die interne Arbeitsweisebash
stattdessen nicht (oder besser gesagt, hat verschiedene Grenzen, die nichts damit zu tun habenexec
, vielleicht die Menge des verfügbaren Speichers).quelle
exec
in der/usr/include/linux/limits.h
Regel definiert alsARG_MAX
.Denn im Falle
ls
ist es ein Argument, und die Anzahl der Argumente ist begrenzt.Im Falle des
for
Zyklus handelt es sich nur um eine Liste von Elementen. Dafür gibt es (soweit mir bekannt ist) keine Grenzen.quelle
for i in {00000001..20000000} ;do ((10#$i==1)) && break; done