I came across some bash (v5.1.16) behavior today that surprised me:
~ > export TEST=`python -c "print('a'*131067)"` # This works.
~ > export TEST=`python -c "print('a'*131067)"` # This does not.
-bash: /usr/bin/python: Argument list too long
~ > export TEST=`python -c "print('a'*131067)"` # This works.
~ > export TEST=`python -c "print('a'*131067)"` # This does not.
-bash: /usr/bin/python: Argument list too long
Note how the first line succeeds, and the second does not. The behavior repeats reliably: setting TEST
works, then it doesn’t, then it does, then it doesn’t...
This is on Gentoo Linux 5.18.5. Interestingly, 131066
works always; on Mac it’s 259832
that works, and one more fails.
Related perhaps: Difference between single and double quotes in Bash
What’s going on here?
Addendum: Thanks @dave-thompson-085 for your answer below.
With some more digging I found these two related discussions: What is the maximum size of a Linux environment variable value? and How to get around the Linux "Too Many Arguments" limit. Also, reading the docs for execve()
helps, particulalry the section Limits on size of arguments and environment.
CodePudding user response:
Let's look step by step.
dthomps@virt8:~$ export TEST=$(python -c "print 'a'*131067")
dthomps@virt8:~$ echo ${#TEST}
131067
TEST is set to a string with length just short of 128k, and marked for export
dthomps@virt8:~$ echo foo
foo
dthomps@virt8:~$ /bin/echo foo
-bash: /bin/echo: Argument list too long
echo
is a shell builtin and works, but /bin/echo
is a program and trying to run a program fails because the 128k-length environment value can't be passed to the child process
dthomps@virt8:~$ export TEST=$(python -c "print 'a'*131067")
-bash: /usr/bin/python: Argument list too long
dthomps@virt8:~$ echo ${#TEST}
0
python
is also a program and can't run, so it has no output and TEST is now set to empty
dthomps@virt8:~$ /bin/echo foo
foo
dthomps@virt8:~$ export TEST=$(python -c "print 'a'*131067")
dthomps@virt8:~$ echo ${#TEST}
131067
Running any progam -- /bin/echo
or python
-- with TEST=""
works, and now TEST is again set to a long value.
Lather, rinse, repeat.