CP: Argumente für die maximale Anzahl von Quelldateien für das Kopierdienstprogramm

11

Bedenken Sie, dass sich unter / src / unzählige Dateien befinden

cp /src/* /dst/

Wie viele Dateien cpwerden erfolgreich verarbeitet?

Mike
quelle
2
Wenn die Argumentliste zu lang ist (denken Sie daran, dass * zu einer Liste aller Dateien erweitert wird, die dem Glob entsprechen), können Sie sie umgehen, indem Sie z . B. IFS="\n" for file in /src/*; do mv "$file" /dst/; doneoder verwenden rsync -a /src/ /dst/.
DopeGhoti

Antworten:

18

Dies hängt stark vom System und der Version, von der Anzahl und Größe der Argumente sowie von der Anzahl und Größe der Umgebungsvariablennamen ab.

Traditionell lag das Limit (wie von Unix angegeben getconf ARG_MAX) mehr oder weniger bei der kumulierten Größe von:

  • Die Länge der Argumentzeichenfolgen (einschließlich der Beendigung '\0')
  • Die Länge des Array von Zeigern auf diese Zeichenfolgen, also normalerweise 8 Bytes pro Argument in einem 64-Bit-System
  • Die Länge der Umgebungszeichenfolgen (einschließlich der Beendigung '\0'), wobei eine Umgebungszeichenfolge gemäß Konvention so etwas wie ist var=value.
  • Die Länge des Array von Zeigern auf diese Zeichenfolgen, also normalerweise 8 Bytes pro Argument in einem 64-Bit-System

Denken Sie daran, dass dies cpauch als Argument gilt (ist das erste Argument).

Unter Linux hängt es von der Version ab. Das Verhalten dort hat sich kürzlich geändert, wo es kein fester Raum mehr ist.

Bei der Überprüfung unter Linux 3.11 wird getconf ARG_MAXjetzt ein Viertel des für die Stapelgröße festgelegten Grenzwerts angegeben (128 KB, wenn dies weniger als 512 KB sind).

( zshSyntax unten):

$ limit stacksize
stacksize       8MB
$ getconf ARG_MAX
2097152
$ limit stacksize 4M
$ getconf ARG_MAX
1048576

Diese Grenze liegt in der kumulativen Größe der Argument- und Umgebungszeichenfolgen und in einem gewissen Overhead (ich vermute aufgrund der Berücksichtigung der Ausrichtung an den Seitengrenzen). Die Größe der Zeiger wird nicht berücksichtigt.

Auf der Suche nach dem Limit bekomme ich:

$ /bin/true {1..164686}
$ /bin/true {1..164687}
zsh: argument list too long: /bin/true
$ x= /bin/true {1..164686}
$ x=1 /bin/true {1..164686}
zsh: argument list too long: /bin/true

Die maximale kumulative Größe vor dem Brechen in diesem Fall ist:

$ (env _=/bin/true x=;print -l /bin/true {1..164686}) | wc -c
1044462

Das bedeutet nicht, dass Sie 1 Million leere Argumente übergeben können. Auf einem 64-Bit-System ergeben 1 Million leere Argumente eine Zeigerliste von 8 MB, was über meiner Stapelgröße von 4 MB liegen würde.

$ IFS=:; /bin/true ${=${(l.1000000..:.)${:-}}}
zsh: killed     /bin/true ${=${(l.1000000..:.)${:-}}}

(Sie werden feststellen, dass es sich nicht um einen E2BIG-Fehler handelt. Ich bin mir nicht sicher, an welchem ​​Punkt der Prozess dort abgebrochen wird, wenn er sich innerhalb des execveSystemaufrufs oder später befindet.)

Beachten Sie auch (immer noch unter Linux 3.11), dass die maximale Größe eines einzelnen Arguments oder einer Umgebungszeichenfolge 128 KB beträgt, unabhängig von der Größe des Stapels.

$ /bin/true ${(l.131071..a.)${:-}} # 131072 OK
$ /bin/true ${(l.131072..a.)${:-}} # 131073 not
zsh: argument list too long: /bin/true
$ /bin/true ${(l.131071..a.)${:-}} ${(l.131071..a.)${:-}} # 2x 131072 OK
Stéphane Chazelas
quelle
Kannst du bitte teilen, wie bist du auf die 164686Nummer gekommen? dh wie haben Sie berechnet, dass die Sequenz unter der 2097152Größe ARG_MAX liegen würde ?
Sergiy Kolodyazhnyy
14

Dies hängt vom Wert von ARG_MAX ab, der sich zwischen den Systemen ändern kann. So ermitteln Sie den Wert für Ihren Systemlauf (zeigen Sie das Ergebnis auf meinem als Beispiel):

$ getconf ARG_MAX
2097152

Dies hat nichts mit cpIhrer Shell zu tun. Es ist eine vom Kernel auferlegte Grenze. Es werden keine ( exec()) Befehle ausgeführt, wenn ihre Argumente länger als sind ARG_MAX. Wenn also die Länge der Argumentliste, die Sie angegeben haben, cpgrößer als ARG_MAX ist, wird der cpBefehl überhaupt nicht ausgeführt.

Um Ihre Hauptfrage zu beantworten, cpwerden keine Dateien verarbeitet, da sie niemals mit so vielen Argumenten ausgeführt werden. Ich sollte auch erwähnen, dass dies nicht von der Anzahl der Argumente abhängt, sondern von ihrer Länge. Möglicherweise haben Sie das gleiche Problem mit sehr wenigen, aber sehr langen Dateinamen.


Um diese Fehler zu umgehen, führen Sie Ihren Befehl in einer Schleife aus:

for file in /src/*; do cp "$file" /dst/; done
terdon
quelle
Bedeutet dies, dass auch untergeordnete Sprachen CProbleme mit ARG_MAX und wirklich langen Dateinamen haben können?
Harold Fischer