Home > Net >  Setting env variable to a large value succeeds, then fails
Setting env variable to a large value succeeds, then fails

Time:09-10

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.

  • Related