减少 bash 环境变量大小

Reduce bash environment variables size

假设我有一个程序接受大量命令行参数或一个非常大的单个命令行参数。假设我的应用程序想要接受一个命令行参数作为 65536 个符号 (64kB) 的字符串。众所周知,使用命令行和环境变量可以传递给处理的字节数是有限制的。

这里有一个小实验:

$ set > t
$ ls -lF | grep "\<t\>"
-rw-r--r--  1 sergey sergey 118737 Oct 14 23:45 t

而这118737字节大约是115kB。头文件 /usr/include/linux/limits.hARG_MAX 是 131072,正好是 128kB。

有没有办法减少用户 bash 会话的环境变量大小?

set | wc -c(这是计算所有 shell 变量大小的一种更简单的方法)无关紧要,因为这些变量中的大部分都不会导出,并且该限制仅适用于导出的变量和命令行参数。

尝试 export | wc -c 以获得真实的视图。在一个 shell 会话中,我碰巧打开了:

$ set | wc -c
241235
$ export | wc -c
4652

您还可以从xargs获得各种有用的信息:

$ xargs --show-limits </dev/null
Your environment variables take up 3730 bytes
POSIX upper limit on argument length (this system): 2091374
POSIX smallest allowable upper limit on argument length (all systems): 4096
Maximum length of command we could actually use: 2087644
Size of command buffer we are actually using: 131072

或来自 getconf 的更简单的报告:

$ getconf ARG_MAX
2097152

您的特定系统很可能允许超过 ARG_MAX 个字节。

如果您想将该路线用作近似值,我认为 export | wc -c 命令是不够的。我使用 bash shell 函数。很多。我导出它们以在 subshells 中可用。这些只能通过 export -f 发现。所以理论上你真的需要两者的输出。

然而,看看我的机器:

$  export -p | wc && export -f | wc              
    147     479    9309
   6940   17029  150917

$  xargs --show-limits </dev/null                        
Your environment variables take up 121160 bytes
POSIX upper limit on argument length (this system): 1973944
POSIX smallest allowable upper limit on argument length (all systems): 4096
Maximum length of command we could actually use: 1852784
Size of command buffer we are actually using: 131072

也许 export 命令的输出可以很好地了解导出变量和函数之间的比率,但它不能反映实际使用的 space (9309 + 150917 != 121160)

这是有道理的。这是我环境中一个随机函数的输出,通过 export -f:

usage_init () 
{ 
    USAGE_OPT_P1="-p pathvar - The envvar to process. Default is";
    USAGE_OPT_P2="             PATH, if -p is not specified.";
    USAGE_OPT_P3="             The '-p' is optional, in which case";
    USAGE_OPT_P4F="             the first ARGUMENT is assumed to be";
    USAGE_OPT_P4O="             the ARGUMENT is assumed to be";
    USAGE_OPT_P5="             the pathvar.";
    USAGE_OPT_S="-s sep - Path element separator. Defaults to ':'.";
    USAGE_OPT_X="-x - Exports 'pathvar'.";
    USAGE_OPT_V="-v - Executes function 'listpath' after assignment.";
    USAGE_OPT_H="-h - Gives usage message.";
    USAGE_OPT_E="-e - 'pathspec' is interpreted as an egrep regexp.";
    USAGE_OPT_N="-n - Add index numbers to the results."
}
declare -fx usage_init

这是从 env

中提取的相同函数
BASH_FUNC_usage_init%%=() {  USAGE_OPT_P1="-p pathvar - The envvar to process. Default is";
 USAGE_OPT_P2="             PATH, if -p is not specified.";
 USAGE_OPT_P3="             The '-p' is optional, in which case";
 USAGE_OPT_P4F="             the first ARGUMENT is assumed to be";
 USAGE_OPT_P4O="             the ARGUMENT is assumed to be";
 USAGE_OPT_P5="             the pathvar.";
 USAGE_OPT_S="-s sep - Path element separator. Defaults to ':'.";
 USAGE_OPT_X="-x - Exports 'pathvar'.";
 USAGE_OPT_V="-v - Executes function 'listpath' after assignment.";
 USAGE_OPT_H="-h - Gives usage message.";
 USAGE_OPT_E="-e - 'pathspec' is interpreted as an egrep regexp.";
 USAGE_OPT_N="-n - Add index numbers to the results."
}

export(我认为 type)似乎在做一些漂亮的展示,这会夸大 wc -c 的价值。