web-dev-qa-db-fra.com

Quelle est la taille maximale d'une valeur de variable d'environnement?

Y a-t-il une limite à la quantité de données pouvant être stockées dans une variable d'environnement sous Linux, et si oui: qu'est-ce que c'est?

Pour Windows, j'ai trouvé ce qui suit KB article qui se résume à: Windows XP ou version ultérieure: 8191 caractères Windows 2000/NT 4.0: 2047 caractères

67
Gio

Je ne pense pas qu'il y ait une limite de variable par environnement sous Linux. La taille totale de toutes les variables d'environnement réunies est limitée au moment de execve (). Voir "Limites de la taille des arguments et de l'environnement" ici pour plus d'informations.

Un processus peut utiliser setenv () ou putenv () pour faire croître l'environnement au-delà de l'espace initial alloué par exec.

Voici un programme rapide et sale qui crée une variable d'environnement de 256 Mo.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int main(void)
{
    size_t size = 1 << 28; /* 256 MB */
    char *var;

    var = malloc(size);
    if (var == NULL) {
        perror("malloc");
        return 1;
    }

    memset(var, 'X', size);
    var[size - 1] = '\0';
    var[0] = 'A';
    var[1] = '=';

    if (putenv(var) != 0) {
        perror("putenv");
        return 1;
    }

/*  Demonstrate E2BIG failure explained by paxdiablo */
    execl("/bin/true", "true", (char *)NULL);
    perror("execl");   


    printf("A=%s\n", getenv("A"));

    return 0;
}
67
sigjuice

Eh bien, c'est au moins 4M sur ma boîte. À ce moment-là, je me suis ennuyé et je me suis éloigné. J'espère que la sortie du terminal sera terminée avant mon retour au travail lundi :-)

export b1=A
export b2=$b1$b1
export b4=$b2$b2
export b8=$b4$b4
export b16=$b8$b8
export b32=$b16$b16
export b64=$b32$b32
export b128=$b64$b64
export b256=$b128$b128
export b512=$b256$b256
export b1k=$b512$b512
export b2k=$b1k$b1k
export b4k=$b2k$b2k
export b8k=$b4k$b4k
export b16k=$b8k$b8k
export b32k=$b16k$b16k
export b64k=$b32k$b32k
export b128k=$b64k$b64k
export b256k=$b128k$b128k
export b512k=$b256k$b256k
export b1m=$b512k$b512k
export b2m=$b1m$b1m
export b4m=$b2m$b2m
echo $b4m
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
:    :    :    :    :    :    :    :    :    :    :    :
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

Si vous craignez que 4M ne soit pas suffisant pour votre variable d'environnement, vous voudrez peut-être repenser la façon dont vous faites les choses.

Il serait peut-être préférable de placer les informations dans un fichier, puis d'utiliser une variable d'environnement pour référencer ce fichier. J'ai vu des cas où, si la variable est de la forme @/path/to/any/fspec, il obtient les informations réelles du fichier path/to/any/fspec. Si c'est pas commencez par @, il utilise la valeur de la variable d'environnement elle-même.


Chose intéressante, avec toutes ces variables définies, chaque commande commence à se plaindre que la liste d'arguments est trop longue donc, même si elle vous permet de les définir, elle peut ne pas être en mesure de démarrer des programmes après l'avoir fait (car elle doit transmettre l'environnement à ces programmes).

21
paxdiablo

J'ai fait un test rapide sur ma boîte Linux avec l'extrait de code suivant:

a="1"
while true
do
    a=$a$a
    echo "$(date) $(numfmt --to=iec-i --suffix=B --padding=7 ${#a})" 
done

Sur ma box (Gentoo 3.17.8-gentoo-r1) cela se traduit par (dernières lignes de sortie):

Wed Jan  3 12:16:10 CET 2018   16MiB
Wed Jan  3 12:16:11 CET 2018   32MiB
Wed Jan  3 12:16:12 CET 2018   64MiB
Wed Jan  3 12:16:15 CET 2018  128MiB
Wed Jan  3 12:16:21 CET 2018  256MiB
Wed Jan  3 12:16:33 CET 2018  512MiB
xrealloc: cannot allocate 18446744071562068096 bytes

Donc: la limite est assez élevée!

6
cyberbird

Je ne sais pas exactement, mais une expérience rapide montre qu'aucune erreur ne se produit, par exemple avec 64 Ko de valeur:

% Perl -e 'print "#include <stdlib.h>\nint main() { return setenv(\"FOO\", \"", "x"x65536, "\", 1); }\n";'\
| gcc -x c -o envtest - && ./envtest && echo $?
0
1
laalto

J'ai utilisé ce code php très rapide et sale (ci-dessous), en le modifiant pour différentes valeurs, et j'ai constaté qu'il fonctionne pour des longueurs variables jusqu'à 128k. Après cela, pour une raison quelconque, cela ne fonctionne pas; aucune exception n'est déclenchée, aucune erreur n'est signalée, mais la valeur n'apparaît pas dans le sous-shell.

Peut-être que c'est une limite spécifique à php? Peut-être qu'il y a des paramètres php.ini qui pourraient l'affecter? Ou peut-être qu'il y a une limite sur la taille des vars dont un sous-shell héritera? Il existe peut-être des paramètres de configuration du noyau ou du shell pertinents.

Quoi qu'il en soit, par défaut, dans CentOS, la limite pour définir un var dans l'environnement via putenv en php semble être d'environ 128k.

<?php

  $s = 'abcdefghijklmnop';
  $s2 = "";
  for ($i = 0; $i < 8100; $i++) $s2 .= $s;
  $result = putenv('FOO='.$s2);
  print Shell_exec('echo \'FOO: \'${FOO}');
  print "length of s2: ".strlen($s2)."\n";
  print "result = $result\n";
?>

Informations sur la version -

[root@localhost scratch]# php --version
PHP 5.2.6 (cli) (built: Dec  2 2008 16:32:08) 
<..snip..>

[root@localhost scratch]# uname -a
Linux localhost.localdomain 2.6.18-128.2.1.el5 #1 SMP Tue Jul 14 06:36:37 EDT 2009 x86_64 x86_64 x86_64 GNU/Linux

[root@localhost scratch]# cat /etc/redhat-release 
CentOS release 5.3 (Final)
1
Shavais

très utile getconf -a |grep MAX ou xargs --show-limits

1

La ligne de commande (avec tous les arguments) plus la variable d'environnement doit être inférieure à 128 Ko.

0
J-16 SDiZ