Pourquoi suis-je “/bin/sh: liste d'arguments trop longue” lors du passage cité arguments?
Combien de temps peut-être une ligne de commande qui peut être transmis à sh -c ''
? (en bash et en bourne shell)
La limite est beaucoup plus faible que celle de l'OS (en cas de moderne Linux).
Par exemple:
$ /bin/true $(seq 1 100000)
$ /bin/sh -c "/bin/true $(seq 1 100000)"
bash: /bin/sh: Argument list too long
Et comment pourrais-je contourner ce problème?
Mise à jour
Je tiens à souligner que getconf
peut pas aider ici (parce que ce n'est pas une limite du système):
$ seq 1 100000 | wc -c
588895
$ getconf ARG_MAX
2097152
Mise à jour #2
Maintenant, j'ai compris quel est le point ici. Ce n'est pas une coquille limite, qui est un système de limite, mais pour la longueur de chaque argument, et non pour l'ensemble de la arglist.
$ /bin/true $(seq 1 100000)
$ /bin/true "$(seq 1 100000)"
bash: /bin/true: Argument list too long
Merci, CodeGnome, pour l'explication.
Vous devez vous connecter pour publier un commentaire.
TL;DR
Un seul argument doit être plus court que MAX_ARG_STRLEN.
Analyse
Selon ce lien:
C'est exactement le "problème" identifié par l'OP. Alors que le nombre d'arguments permis peut être assez large (voir
getconf ARG_MAX
), lorsque vous passez une commande entre guillemets pour /bin/sh le shell interprète la cité de commande comme une seule chaîne. Dans le cas des OP exemple, c'est cette chaîne unique qui dépasse la MAX_ARG_STRLEN limite, pas la longueur de l'élargissement de la liste d'arguments.De Mise En Œuvre Spécifiques
Argument limites de mise en œuvre spécifiques. Cependant, ce Linux Journal article suggère plusieurs façons de travailler autour d'eux, y compris l'augmentation des limites du système. Cela peut ne pas être directement applicables à l'OP, mais il est cependant utile dans le cas général.
Faire Quelque Chose D'Autre
L'OP problème n'est pas réellement un problème réel. La question est d'imposer une contrainte arbitraire qui ne résout pas un problème réel.
Vous pouvez contourner ce assez facilement par l'aide de boucles. Par exemple, avec Bash 4:
fonctionne très bien. Il sera certainement ralentir, puisque vous êtes à la ponte d'un processus à chaque passage dans la boucle, mais il obtient certainement autour de la ligne de commande limite que vous êtes en train de vivre.
Décrire Votre Problème Réel
Si une boucle ne résout pas votre problème, veuillez mettre à jour la question de décrire le problème que vous êtes en train d'essayer de résoudre à l'aide de très longues listes d'arguments. Explorer arbitraire de la longueur de la ligne de limite est un exercice académique, et non pas sur le sujet pour Stack Overflow.
MAX_ARG_STRLEN
sur un système avec2.6.31
MAX_ARG_STRLEN
(ma et le système de Dennis). Nous devons donc trouver une autre façon de trouver cette valeur.getconf
et il n'est pas danslimits.h
(mais c'est dans leman
page). Merci./usr/src/linux-headers-3.0.0-14/include/linux/binfmts.h
si on a besoin toujours à redéfinir./usr/include/linux/binfmts.h
ARG_MAX
.Je n'ai pas ce message d'erreur. Mon secret? Apostrophes:
Si j'utilise des guillemets, j'obtiens cette erreur à chaque shell:
La liste des arguments obtient élargi dans le shell courant quand les guillemets sont utilisés comme en témoigne le fait que Bash est la délivrance de l'erreur "-bash: ..." quel que soit le shell utilisé pour exécuter la commande. Sur mon système
sh
est le tableau de bord, par la manière.Ceci est vrai même pour les autres "hôte" coquilles":
Patient: Docteur, ça fait mal quand je fais cela."
Médecin: Ne pas le faire.
$(seq 1 100000)
ici uniquement à des fins de démonstration; il n'a pas d'importance comment vous produire cette longue chaîne; bien sûr, j'ai besoin de guillemets ici car j'ai besoin de très longue chaîne. La question principale est de savoir combien de temps peut-être l'argument desh -c ''
/bin/bash -c '/bin/true "$(seq 1 100000)"'
casse trop parce que de la façon dont le shell tokenizes cordes. +1 pour la résolution de problèmes pour Y dans ce X/Y problème, mais--je pense que c'est utile d'avoir publié de la solution des problèmes connexes.Diminution de 100 000 jusqu'à ce que vous obtenez n'est plus l'erreur
etc.
Faire un fichier avec
#!/bin/sh
comme la première ligne, puis le mettre reste de votre commande sur les lignes suivantes? 🙂Plus sérieusement, vous pouvez également lire les commandes provenant de l'entrée standard à l'aide de la
-s
option, de sorte que vous pouvez générer le long de la ligne de commande et le tuyau en/bin/sh -s
-s
; oui, je sais cela; c'est probablement la meilleure solution, à l'exception des situations où vous avez besoin d'utiliser le shell stdin pour autre chose-s
ou avecfor arg in $(</dev/stdin)
) est vraiment la seule façon d'avoir une réelle illimité "argument" de soutien.sur mon os c'est la longueur maximum obtenu par dichotomie
de sorte qu'il donne 131071
mais il n'y a aucune raison d'avoir une ligne de long ; si c'est à cause d'un grand nombre d'arguments, "$@" peut être utilisé à la place; par exemple