Avez-vous utilisé le même shell dans les deux expériences? Peut-être /bin/bashvs /bin/sh(qui est peut-être un lien vers un tiret)?
maxschlepzig
Oui, j'ai fait l'expérience avec 10000 fichiers avec des noms de fichiers assez longs. "ls *" a échoué et "pour f dans *" a réussi.
lamwaiman1988
Réponses:
13
L'erreur «argument trop long» est déclenchée E2BIGpar l' execveappel système si la taille totale des arguments (plus l'environnement, sur certains systèmes) est trop grande. L' execveappel est celui qui démarre les processus externes, en particulier le chargement d'un fichier exécutable différent (il existe un appel différent fork, pour exécuter un processus distinct dont le code provient toujours du même fichier exécutable). La forboucle est une construction de shell interne, elle n'implique donc pas d'appel execve. La commande ls *.*déclenche l'erreur non pas lorsque le glob est développé mais quand lsest appelé.
execveéchoue avec l'erreur E2BIGlorsque la taille totale des arguments de la commande est supérieure à la ARG_MAXlimite . Vous pouvez voir la valeur de cette limite sur votre système avec la commande getconf ARG_MAX. (Il est possible que vous puissiez dépasser cette limite si vous avez suffisamment de mémoire; garder sous des ARG_MAXgaranties qui execvefonctionneront tant qu'aucune erreur non liée ne se produit.)
@ gunbuster363 La execvelimite est appliquée par le noyau, elle impose des limites car les arguments doivent être copiés via la mémoire du noyau à un moment donné et les processus utilisateur ne peuvent pas être autorisés à demander une quantité arbitraire de mémoire shell. À l'intérieur du shell, il n'y a aucune raison d'avoir une limite, tout ce qui tient dans la mémoire virtuelle est très bien.
Gilles 'SO- arrête d'être méchant'
5
Je suppose que dans le premier exemple lsest exécuté à partir d' bashun appel système fork/ execpair, dans le second, tout le travail est interne à bash.
L' execappel a des limites, le fonctionnement interne de bashn'a pas (ou mieux, a des limites différentes qui n'ont rien à voir avec exec, peut-être la quantité de mémoire disponible).
Il y a certainement une limite à l'expansion du shell. Cela dépend beaucoup de la quantité de RAM dont vous disposez. Essayez ceci; mon système de 4 Go de RAM souffle un joint à environ 15,2 millions d' for i in {00000001..20000000} ;do ((10#$i==1)) && break; done
arguments de
4
@fred Je ne pensais pas vraiment qu'il soit nécessaire de mentionner la RAM comme limite.
Šimon Tóth
2
Ce n'est peut-être pas nécessaire, mais c'est la nature des commentaires .. quelqu'un peut le trouver intéressant, ou même de valeur.
Peter.O
@fred: en fait oui, si l'expansion de très gros arguments était un problème courant, il serait possible de l'implémenter sans tout garder en mémoire.
/bin/bash
vs/bin/sh
(qui est peut-être un lien vers un tiret)?Réponses:
L'erreur «argument trop long» est déclenchée
E2BIG
par l'execve
appel système si la taille totale des arguments (plus l'environnement, sur certains systèmes) est trop grande. L'execve
appel est celui qui démarre les processus externes, en particulier le chargement d'un fichier exécutable différent (il existe un appel différentfork
, pour exécuter un processus distinct dont le code provient toujours du même fichier exécutable). Lafor
boucle est une construction de shell interne, elle n'implique donc pas d'appelexecve
. La commandels *.*
déclenche l'erreur non pas lorsque le glob est développé mais quandls
est appelé.execve
échoue avec l'erreurE2BIG
lorsque la taille totale des arguments de la commande est supérieure à laARG_MAX
limite . Vous pouvez voir la valeur de cette limite sur votre système avec la commandegetconf ARG_MAX
. (Il est possible que vous puissiez dépasser cette limite si vous avez suffisamment de mémoire; garder sous desARG_MAX
garanties quiexecve
fonctionneront tant qu'aucune erreur non liée ne se produit.)la source
execve
limite est appliquée par le noyau, elle impose des limites car les arguments doivent être copiés via la mémoire du noyau à un moment donné et les processus utilisateur ne peuvent pas être autorisés à demander une quantité arbitraire de mémoire shell. À l'intérieur du shell, il n'y a aucune raison d'avoir une limite, tout ce qui tient dans la mémoire virtuelle est très bien.Je suppose que dans le premier exemple
ls
est exécuté à partir d'bash
un appel systèmefork
/exec
pair, dans le second, tout le travail est interne àbash
.L'
exec
appel a des limites, le fonctionnement interne debash
n'a pas (ou mieux, a des limites différentes qui n'ont rien à voir avecexec
, peut-être la quantité de mémoire disponible).la source
exec
en/usr/include/linux/limits.h
général, définie commeARG_MAX
.Parce que dans le cas
ls
c'est un argument, et le nombre d'arguments est limité.Dans le cas du
for
cycle, c'est juste une liste d'articles. Il n'y a pas de limites (à ma connaissance) à cela.la source
for i in {00000001..20000000} ;do ((10#$i==1)) && break; done