python - 为什么 subprocess.Popen 参数长度限制小于操作系统报告的长度?

标签 python linux python-3.x subprocess command-line-arguments

我在 Linux 3.16.0 上运行 Python 3.4.3。我想使用 subprocess.Popen 运行一个带有长单个参数的命令(一个复杂的 Bash 调用),大约 200KiB。

根据 getconfxargs,这应该在我的限制范围内:

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

然而,Python 失败的限制非常小:

>>> subprocess.Popen('echo %s > /dev/null' % ('a' * (131072-4096)), shell=True, executable='/bin/bash')
<subprocess.Popen object at 0x7f4613b58410>
>>> subprocess.Popen('echo %s > /dev/null' % ('a' * (262144-4096)), shell=True, executable='/bin/bash')
Traceback (most recent call last):
  [...]
OSError: [Errno 7] Argument list too long

请注意,Python 限制与“实际使用”命令缓冲区 xargs 报告大致相同。这表明 xargs 在某种程度上足够聪明,可以从较小的限制开始并根据需要增加它,但 Python 不是。

问题:

  1. 为什么 Python 限制小于 2MiB 的操作系统限制?
  2. 我可以提高 Python 限制吗?
  3. 如果是,怎么做?

最佳答案

单个字符串参数的最大大小限制为131072。与python无关:

~$ /bin/echo "$(printf "%*s" 131071 "a")">/dev/null
~$ /bin/echo "$(printf "%*s" 131072 "a")">/dev/null
bash: /bin/echo: Argument list too long

实际上是 MAX_ARG_STRLEN 决定了单个字符串的最大大小:

And as additional limit since 2.6.23, one argument must not be longer than MAX_ARG_STRLEN (131072). This might become relevant if you generate a long call like "sh -c 'generated with long arguments'". (pointed out by Xan Lopez and Ralf Wildenhues)

参见 this discussion of ARG_MAX ,在“参数数量和一个参数的最大长度”下,以及 this questionunix.stackexchange 上。

可以在binfmts.h中看到:

/*
 * These are the maximum length and maximum number of strings passed to the
 * execve() system call.  MAX_ARG_STRLEN is essentially random but serves to
 * prevent the kernel from being unduly impacted by misaddressed pointers.
 * MAX_ARG_STRINGS is chosen to fit in a signed 32-bit integer.
 */
#define MAX_ARG_STRLEN (PAGE_SIZE * 32)
#define MAX_ARG_STRINGS 0x7FFFFFFF

~$ echo $(( $(getconf PAGE_SIZE)*32 )) 
131072

您可以传递多个长度为 131071 的字符串:

subprocess.check_call(['echo', "a"*131071,"b"*131071], executable='/bin/bash',stdout=open("/dev/null","w"))

但单个字符串 arg 不能超过 131071 字节。

关于python - 为什么 subprocess.Popen 参数长度限制小于操作系统报告的长度?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29801975/

相关文章:

python-3.x - 如何禁用cloudscraper Python中的安全证书检查

python - 大型文本数据库 : Convert to SQL or use as is

java - InstantiationError : org. quartz.JobDetail 使 tomcat9 在 linux 中启动失败但在 windows 中正常

linux - 使用 shell 脚本在当前窗口中打开新选项卡

python - 简单游戏的碰撞检测/物理

python - 在Python中将集合添加到计数器的优雅方法

具有抽象形状马赛克的 Python 照片马赛克

python - python中的模块化加法

python - 这个异步 aiohttp 代码有什么问题?

javascript - 将简单的温度 bash 脚本转换为 javascript