【发布时间】:2011-07-01 20:50:51
【问题描述】:
假设我有一个 shell 脚本,其中有如下语句:
a=$(find / -type f)
这表示有一个特定的文件列表及其文件路径将存储在变量“a”中。
它可以存储的最大限制或行数是多少。如何找到它?
【问题讨论】:
假设我有一个 shell 脚本,其中有如下语句:
a=$(find / -type f)
这表示有一个特定的文件列表及其文件路径将存储在变量“a”中。
它可以存储的最大限制或行数是多少。如何找到它?
【问题讨论】:
IIRC,bash 没有限制变量可以存储多少数据。然而,它受到执行 bash 的环境的限制。请参阅this answer 以获得更全面的说明。
【讨论】:
作为数据点,我在 OS X 10.10.5 中尝试了以下脚本,在配备 2.8 GHz Intel Core i7 的 Macbook Pro Retina 上使用内置 bash:
#!/bin/bash
humombo="X"
while true; do
humombo="$humombo$humombo"
echo "Time $(date "+%H:%M:%S"), chars $(echo "$humombo" | wc -c)"
done
结果:大小愉快地一次又一次地翻倍(请注意,大小包括单行结束的额外字节)。当humombo 超过 4MB 时,事情开始放缓;从 256MB 翻倍到 512MB 用时 48 秒,然后脚本就爆炸了:
mbpe:~ griscom$ ./delme.sh
Time 16:00:04, chars 3
Time 16:00:04, chars 5
Time 16:00:04, chars 9
Time 16:00:04, chars 17
Time 16:00:04, chars 33
Time 16:00:04, chars 65
Time 16:00:04, chars 129
Time 16:00:04, chars 257
Time 16:00:04, chars 513
Time 16:00:04, chars 1025
Time 16:00:04, chars 2049
Time 16:00:04, chars 4097
Time 16:00:04, chars 8193
Time 16:00:04, chars 16385
Time 16:00:04, chars 32769
Time 16:00:04, chars 65537
Time 16:00:04, chars 131073
Time 16:00:04, chars 262145
Time 16:00:04, chars 524289
Time 16:00:04, chars 1048577
Time 16:00:04, chars 2097153
Time 16:00:05, chars 4194305
Time 16:00:05, chars 8388609
Time 16:00:07, chars 16777217
Time 16:00:09, chars 33554433
Time 16:00:15, chars 67108865
Time 16:00:27, chars 134217729
Time 16:00:51, chars 268435457
Time 16:01:39, chars 536870913
bash(80722,0x7fff77bff300) malloc: *** mach_vm_map(size=18446744071562072064) failed (error code=3)
*** error: can't allocate region
*** set a breakpoint in malloc_error_break to debug
./delme.sh: xrealloc: cannot allocate 18446744071562068096 bytes
mbpe:~ griscom$
两个音符:
我怀疑崩溃更多是因为整个进程占用了太多内存,而不是我达到了单个变量容量的限制。
在玩这个的时候,我以交互方式运行了相同的命令,当循环退出时,bash 被破坏了;我必须打开一个新的终端窗口才能做任何事情。因此,过多的内存分配会以未知的方式破坏 bash;我的猜测是在脚本中执行此操作会在退出时清理。
编辑:我刚刚在高性能的 Ubuntu 18 系统上尝试了相同的代码:
Time 18:03:02, chars 3
Time 18:03:02, chars 5
Time 18:03:02, chars 9
Time 18:03:02, chars 17
Time 18:03:02, chars 33
Time 18:03:02, chars 65
Time 18:03:02, chars 129
Time 18:03:02, chars 257
Time 18:03:02, chars 513
Time 18:03:02, chars 1025
Time 18:03:02, chars 2049
Time 18:03:02, chars 4097
Time 18:03:02, chars 8193
Time 18:03:02, chars 16385
Time 18:03:02, chars 32769
Time 18:03:02, chars 65537
Time 18:03:02, chars 131073
Time 18:03:02, chars 262145
Time 18:03:02, chars 524289
Time 18:03:02, chars 1048577
Time 18:03:02, chars 2097153
Time 18:03:02, chars 4194305
Time 18:03:02, chars 8388609
Time 18:03:03, chars 16777217
Time 18:03:04, chars 33554433
Time 18:03:07, chars 67108865
Time 18:03:12, chars 134217729
Time 18:03:23, chars 268435457
Time 18:03:43, chars 536870913
./delme.sh: xrealloc: cannot allocate 18446744071562068096 bytes
花了不到一半的时间,死得更干净一些,但字符大小相同。 (顺便说一句,错误消息中的数字,十进制 18446744071562068096,是 0xffff ffff 8000 0080,所以显然我们在这里达到了一些数字容量限制。)
【讨论】:
x=x; n=1; while true; do echo "$(date +%H:%M:%S) length $n"; x="$x$x"; n=$((n * 2)); done
我认为 bash 中的变量大小没有限制,但是您真的希望您的 shell 中有一个 6GB 的变量吗(当然要以ulimit -a 为准)?
命令行当然有限制。 grep <pattern> $TEN_MILLION_FILENAMES 不会工作。事实上,使用$TEN_MILLION_FILES 生成任何命令都非常困难。您需要其他策略,例如按目录或临时文件等。
【讨论】:
据我所知,找到极限的唯一方法是通过经验方法。尝试运行以下 shell 脚本并等待完成:
limit=1
while true
do
limit=`echo 1+$limit|bc`
a=' '$a
echo $limit
done
【讨论】:
Daniel Griscom 的脚本略有改进:
注意:当脚本在 Cygwin 中运行时,“VmPeak”行将有空输出,因为 cygwin 不会完全复制 /proc(基本上“VmPeak”值缺失,但您可以选择“VmSize”在这种情况下?)
$ cat delme.sh
#!/bin/zsh
humombo="X"
pid=$$
while true; do
humombo="$humombo$humombo"
echo "Time $(date "+%H:%M:%S"), chars $(echo "$humombo" | wc -c)"
echo -n "Memory usage: "
grep ^VmPeak /proc/${pid}/status
done
【讨论】:
据我所知,标准没有任何限制。但底层系统可能。我记得我曾经在某些 AIX 上遇到过限制。
您可以像配置检查一样检查最大参数数量 - 尝试直到发现错误。某种带有公式var(i)=concatenation(var(i-1),var(i-1)) 的迭代方法。迟早你会达到限制(至少在处理它时会达到内存限制)。
【讨论】: