Kích thước tối đa của giá trị biến môi trường là bao nhiêu?


83

Có giới hạn nào về số lượng dữ liệu có thể được lưu trữ trong một biến môi trường trên Linux không, và nếu có: thì đó là gì?

Đối với Windows, tôi đã tìm thấy bài viết KB sau đây tóm tắt thành: Windows XP trở lên: 8191 ký tự Windows 2000 / NT 4.0: 2047 ký tự


Giới hạn thực tế trên các cửa sổ là 31,767. Bạn đọc về setlệnh, lệnh này có giới hạn dòng lệnh là 8191 ký tự. Xem bài viết này trên msdn Tuy nhiên, vẫn là một giới hạn ngẫu nhiên.
Christopher Currens

5
8191 đó không phải là ngẫu nhiên. Bây giờ là 2 ^ 13 - 1
Barnaby Dawson

AWS Lambda: tổng kích thước của tập hợp [biến môi trường] không vượt quá 4 KB ( nguồn )
Martin Thoma

1
@BarnabyDawson có lẽ Christopher muốn nói nó theo nghĩa là nó độc đoán?
0xC0000022L

Câu trả lời:


75

Tôi không nghĩ rằng có giới hạn biến cho mỗi môi trường trên Linux. Tổng kích thước của tất cả các biến môi trường gộp lại với nhau bị giới hạn tại execve()thời điểm. Xem "Giới hạn về kích thước của đối số và môi trường" tại đây để biết thêm thông tin.

Một quy trình có thể sử dụng setenv()hoặc putenv()để phát triển môi trường vượt quá không gian ban đầu được cấp bởi người thực thi.

Đây là một chương trình nhanh và bẩn tạo biến môi trường 256 MB.

#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;
}

5
+1 cho thông tin thi hành (). Bạn thực sự có thể thêm các biến môi trường lên đến (ít nhất) 8M nhưng các lệnh gọi thực thi () sẽ không hoạt động. Điều này thể hiện trong bash là "danh sách đối số quá dài" bất cứ khi nào bạn cố gắng chạy một lệnh.
paxdiablo

1
Cũng lưu ý rằng POSIX yêu cầu ARG_MAX ít nhất phải là _POSIX_ARG_MAX, phải là 4096.
ninjalj

10
Câu trả lời hàng đầu (của Chipaca) trên askUbuntu thảo luận về việc sử dụng xargs --show-limitsđể biết thêm thông tin.
DocSalvager,

Tôi thấy giới hạn mỗi chuỗi arg quá - "Bên cạnh đó, giới hạn mỗi chuỗi là 32 trang (hằng số hạt nhân MAX_ARG_STRLEN)"
kiran01bm

24

Chà, ít nhất là 4 triệu trên hộp của tôi. Đến đó, tôi cảm thấy buồn chán và bỏ đi. Hy vọng rằng đầu ra của thiết bị đầu cuối sẽ hoàn thành trước khi tôi trở lại làm việc vào thứ Hai :-)

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

Nếu bạn lo lắng rằng 4M có thể không đủ cho biến môi trường của bạn, bạn có thể muốn xem xét lại cách bạn đang làm mọi thứ.

Có lẽ sẽ là một ý tưởng tốt hơn nếu bạn đưa thông tin vào một tệp và sau đó sử dụng một biến môi trường để tham chiếu đến tệp đó. Tôi đã gặp những trường hợp, nếu biến có dạng @/path/to/any/fspec, nó sẽ lấy thông tin thực tế từ tệp path/to/any/fspec. Nếu nó không bắt đầu bằng @, nó sử dụng giá trị của chính biến môi trường.


Điều thú vị là, với tất cả các biến đó được đặt, mọi lệnh bắt đầu phàn nàn rằng danh sách đối số quá dài, vì vậy, mặc dù nó cho phép bạn đặt chúng, nó có thể không thể khởi động chương trình sau khi bạn đã thực hiện xong (vì nó phải truyền môi trường cho các chương trình đó).


1
Tôi hy vọng bạn đã sử dụng một tập lệnh và không gõ tất cả điều này bằng tay!
Chris Huang-Leaver,

2
Không, do đó hơi "chán". Việc chỉnh sửa dòng lệnh Vi-mode đã làm cho nó dễ dàng hơn một chút nhưng tôi nghĩ nó có thể thất bại trước khi tôi đạt đến mốc 4M. C'est la vie.
paxdiablo


@ LưuVĩnhPhúc: vì chương trình có giới hạn. Chúng có thể là các giới hạn tùy ý hoặc chúng có thể dựa trên các nguồn lực sẵn có, nhưng các giới hạn vẫn tồn tại. Hoàn toàn có thể DavidK giả vỏ của ông sẽ không được (mis-) được sử dụng bởi người điên người nên biết tốt hơn :-)
paxdiablo

7

Tôi đã thực hiện một bài kiểm tra nhanh trên hộp Linux của mình với đoạn mã sau:

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

Trên hộp của tôi (Gentoo 3.17.8-gentoo-r1), kết quả là (dòng cuối cùng của đầu ra):

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

Vì vậy: giới hạn là khá cao!


1
18446744071562068096 byte là khoảng 15 exabyte. :) Đó có vẻ như là một bước nhảy lớn từ 512MiB.
Marcus

1
@Marcus: nó là ... Tôi đoán rằng bằng cách nào đó 1Gb tức là 1073741824 byte tức là 2 ^ 30 byte tràn ở đâu đó. Số byte trong lỗi 18446744071562068096 khá gần với 2 ^ 64 tức là 18446744073709551616
cyberbird

1
Tôi có kỹ năng C / gdb hạn chế nhưng tôi nghĩ vấn đề là ở tệp nguồn bash subst.c. Hàm sub_append_string (dòng 726) sử dụng biến int có dấu được gọi là n để tính kích thước mới. Kích thước mới (2 ^ 31) sẽ phù hợp nhưng có một phép tính căn chỉnh: n = (n + DEFAULT_ARRAY_SIZE) - (n % DEFAULT_ARRAY_SIZE); và tôi nghi ngờ phần: (n + DEFAULT_ARRAY_SIZE)tràn. Tất cả đều rất tốt nhưng tất nhiên chúng tôi đang vượt qua mọi giới hạn lành mạnh ở đây ..
cyberbird

3

Đây là hai lệnh hữu ích:

  • getconf -a |grep MAX

  • true | xargs --show-limits


Biến nào trong số ~ 100 biến có liên quan? Chúng được ghi lại ở đâu?
ingomueller.net

1

Không biết chính xác nhưng một thử nghiệm nhanh cho thấy không có lỗi nào xảy ra, ví dụ: với giá trị 64kB:

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

1

Tôi đã sử dụng mã php rất nhanh và bẩn này (bên dưới), sửa đổi nó cho các giá trị khác nhau và nhận thấy rằng nó hoạt động với độ dài thay đổi lên đến 128k. Sau đó, vì lý do gì, nó không hoạt động; không có ngoại lệ nào được nêu ra, không có lỗi nào được báo cáo, nhưng giá trị không hiển thị trong vỏ con.

Có thể đây là một giới hạn dành riêng cho php? Có thể có cài đặt php.ini có thể ảnh hưởng đến nó? Hoặc có thể có một giới hạn về kích thước của vars mà một vỏ con sẽ kế thừa? Có thể có các cài đặt cấu hình kernel hoặc shell liên quan ..

Dù sao, theo mặc định, trong CentOS, giới hạn để thiết lập var trong môi trường thông qua putenv trong php dường như là khoảng 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";
?>

Thông tin phiên bản -

[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)

0

Dòng lệnh (với tất cả đối số) cộng với biến môi trường phải nhỏ hơn 128k.


11
Cần trích dẫn
rr- Ngày
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.