【问题标题】:Setting environment variable to a large value -> "Argument list too long"将环境变量设置为较大的值->“参数列表太长”
【发布时间】:2015-05-06 02:12:00
【问题描述】:

在 bash 脚本中,我设置了一个环境变量来包含一百万个字符的字符串。我是这样做的:

export LG=XXXXXXX # ... 1 million X's

紧接着,我可以毫无问题地回显它,即

echo $LG

但是,我在此之后尝试在脚本中运行的任何其他不相关命令都会失败,并出现“参数列表太长”错误。例如:

cat randomfile.txt
/bin/cat: Argument list too long

我已阅读其他建议使用 xargs 解决此类问题的帖子,但我没有成功。如果我使用除了 echo 之外的任何命令,那么即使我在设置 $LG 变量后实际上并没有使用它,也会收到“参数列表太长”错误。当然我想使用$LG变量,但是设置后不使用也会报错。

任何提示将不胜感激,谢谢!

编辑:

我试图解决的总体问题是这样的:

我有一个文本文件需要尽可能小(即几 MB)。此文本文件包含一组封装在特定网络协议中的消息(即标头、消息长度、消息本身)。消息本身可以是长度为 100 万或更多的字符串。因此,为了保持原始文件较小,而不是在文件中包含多个大消息副本,我使用了映射。 IE。如果我在消息字段中看到字母 A,然后我使用 sed 查找 A 并将其替换为 100 万个 X。像这样:

cat file.txt | sed "s/A/$LG/g"  # Replace A with 1 million X's

我最终会在一个(非常慢的)模拟器中运行它,所以我需要这个操作在尽可能少的周期内完成。换句话说,像 awk 这样的实用程序使用行程计数为 100 万的循环来动态生成 100 万个 X 会太慢。这就是为什么我认为环境变量解决方案是最好的。

【问题讨论】:

  • 这个变量的作用是什么?值得注意的是,只有 environment 变量会占用这个有限的空间池;如果您不需要将此变量导出到环境中,并且可以将其保留在您的 shell 中,那么这个问题很快就会变得没有意义。
  • (...不过,在这一点上——如果你不需要将它导出到环境中,你应该为它选择一个不同的名字;全大写的名字是按照约定保留的环境变量和shell内置)。
  • 这个解释并没有让我明白为什么你需要一个环境变量。 sed "s/A/$LG/g" 不在环境中查找LG 的值;它只是替换了一个常规的 shell 变量;您可以设置 LG=... 而不使用任何 export 并仍然以这种方式使用它。 (请注意,您可能会因为 sed 命令太大而无法存储在命令行上而遇到麻烦,但您可以通过文件描述符将运行脚本传递给 sed 来解决这个问题)。
  • 我更新了我的答案,添加了一个部分,显示了避免依赖命令行该值的环境的建议方法。
  • (顺便说一句,这是我抱怨 shell 中货物崇拜编程盛行的部分——在这种情况下,复制 export 而不知道它的作用以及何时何地使用它——同样重要的是,何时何地不去)。

标签: linux bash shell environment-variables


【解决方案1】:

命令行参数和环境变量都来自同一个空间池。将环境变量设置得太长,并且您不再有用于命令行参数的空间 - 甚至 xargs,它将命令行调用分解为更小的分组以尽可能放入池中,当该池是时无法运行完全满了。

所以:不要那样做。例如,您可以将数据存储在一个文件中,并在环境中导出该文件的路径。


顺便说一句——echo 起作用的原因是它内置在你的 shell 中。因此,

echo "$LG"

...不需要启动外部进程,因此进程启动时参数列表长度和环境大小的限制不适用。

另一方面,如果你跑了

/bin/echo "$LG"

...然后你会再次看到问题。


鉴于已编辑到问题中关于您实际尝试完成什么的解释,让我建议一种既不需要环境空间也不需要命令行空间的方法:

#!/bin/bash
#      ^-- also consider ksh; faster than bash, but also supports <()
#          /bin/sh is not usable here, as POSIX sh does not specify <().

lg=... ## DO NOT USE export HERE!
sed -f <(printf '%s\n' "s/A/$lg/g")

【讨论】:

  • 我现在明白了。我想你的意思是sed -f &lt;(printf '%s\n' "s/A/$lg/g") fileOfMessages.txt?我认为这似乎可以解决问题。非常感谢!
  • 很高兴听到这个成功!随意将答案标记为已接受。 (至于fileOfMessages.txt,您没有在问题中指定是通过标准输入上的流还是通过命名参数提供输入,所以我故意保持答案不可知)。
  • 能知道限制有多大吗?
  • @lindhe, getconf ARG_MAX 显示池的总大小。
猜你喜欢
  • 2020-05-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-21
  • 2021-08-03
  • 1970-01-01
  • 2016-11-15
  • 1970-01-01
相关资源
最近更新 更多