【问题标题】:Shell Variable capacity [duplicate]壳牌可变容量 [重复]
【发布时间】:2011-07-01 20:50:51
【问题描述】:

假设我有一个 shell 脚本,其中有如下语句:

a=$(find / -type f)

这表示有一个特定的文件列表及其文件路径将存储在变量“a”中。

它可以存储的最大限制或行数是多少。如何找到它?

【问题讨论】:

    标签: shell unix scripting


    【解决方案1】:

    IIRC,bash 没有限制变量可以存储多少数据。然而,它受到执行 bash 的环境的限制。请参阅this answer 以获得更全面的说明。

    【讨论】:

      【解决方案2】:

      作为数据点,我在 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
      【解决方案3】:

      我认为 bash 中的变量大小没有限制,但是您真的希望您的 shell 中有一个 6GB 的变量吗(当然要以ulimit -a 为准)?

      命令行当然有限制。 grep <pattern> $TEN_MILLION_FILENAMES 不会工作。事实上,使用$TEN_MILLION_FILES 生成任何命令都非常困难。您需要其他策略,例如按目录或临时文件等。

      【讨论】:

        【解决方案4】:

        据我所知,找到极限的唯一方法是通过经验方法。尝试运行以下 shell 脚本并等待完成:

        limit=1
        while true
        do
          limit=`echo 1+$limit|bc`
          a=' '$a
          echo $limit
        done
        

        【讨论】:

          【解决方案5】:

          Daniel Griscom 的脚本略有改进:

          1. 您可以添加显示脚本正在使用多少内存(请参阅循环中添加的最后一条命令)
          2. 您可以尝试不同的 shell 环境(我的测试表明,对于与 zsh 相同大小的变量,bash 使用的内存大约是 zsh 的 5 倍 - 您可以自己进行以下测试)

          注意:当脚本在 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
          

          【讨论】:

            【解决方案6】:

            据我所知,标准没有任何限制。但底层系统可能。我记得我曾经在某些 AIX 上遇到过限制。

            您可以像配置检查一样检查最大参数数量 - 尝试直到发现错误。某种带有公式var(i)=concatenation(var(i-1),var(i-1)) 的迭代方法。迟早你会达到限制(至少在处理它时会达到内存限制)。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2021-09-20
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2015-09-01
              • 2013-11-09
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多