Live data from Hacker News

Environment variables are a legacy mess: Let's dive deep into them

allvpv.org

181–190 of 194 posts

Re: Environment variables are a legacy mess: Let's dive deep into them

#181
post #65
post #8

Another legacy mess: Argument list too long It's absolutely crazy that this isn't a dynamically resizable vector.

The xargs command was designed to address this. From this perspective, it is a kludge.

Yes, and xargs isn't the same thing. It splits a single command into multiple commands, which can lead to surprises.

The issue also breaks scripts left and right. It really needs to be solved.

Re: Environment variables are a legacy mess: Let's dive deep into them

#183

I get anxiety whenever I need to set an environment var on Linux. There are (somewhat distro-specific) ways that work properly, but the usual procedures you find online stops working once you reboot (or close the terminal I think?). They should add a simple env var GUI like Windows has that just works , and isn't terminal-specific. Windows has the annoyance of needing to restart the the terminal (or open a new one) f…

...you just put them in your shell RC file??

This is much simpler than having to remember where the dang environment variables button is in "advanced system settings" or whatever awful command prompt syntax sets it permanently.

Re: Environment variables are a legacy mess: Let's dive deep into them

#184
post #164

Earlier quoted context omitted.

Which is why I said > frequency of data Practically, if you're moving enough data through setenv that the memory leaked versus the steady state fluctuation of the program is at all visible, you've got much bigger problems.

You don't need setenv. It's just a particularly broken way of assigning to a global char*.

And I personally don't use it or would be likely to approve a review that uses it.

But it I were implementing POSIX and had to implement it, I would almost certainly make Sun's choice thinking of it as the least evil given the expected use cases.

Re: Environment variables are a legacy mess: Let's dive deep into them

#185

>"Wow, I really enjoyed writing this… …and I hope it wasn’t a boring read." No, it was very interesting actually! An excellent deep-dive into the murky area of Unix/Linux environment variables, how they are set, how they are passed, what's really going on behind the scenes. Basically a must-read for any present or future OS designer... Observation (if I might!) -- environment variables are to programs (especially cha…

> environment variables are to programs (especially chains of programs, parent processes, sub processes and sub-sub processes, etc.) what parameters are to functions -- and/or what command-line parameters are... they're sort of like global variables that get passed around a lot... They're not globals, since they're copied into sub-processes; so mutation doesn't propagate upwards. My own opinion is that environment va…

>They're not globals, since they're copied into sub-processes; so mutation doesn't propagate upwards.

If we broaden our thinking to look at a computer process as a mathematical function, i.e., if we think about a computer process as

y = f(x)

Where y is the behavior of the function (what final state it results in / resolves to), f is the process itself, and x is the parameter or list of parameters that are passed to f, then if that process reads and subsequently alters its behavior in relation to any environment variable, then we should no longer think of that function as merely y = f(x), but as

y = f(x, z)

where Z is the set of environment variables that are consumed by, and subsequently alter the behavior of f, resulting in a different y.

Now not all processes read environment variables and alter their behaviors because of an environment variable being set.

That is true.

Those processes remain as y = f(x).

But if a process does read and does act on an environment variable (usually without the end-users' knowledge, because how many users keep track of which programs read/act on -- which environment variables?), then then this the same as passing extra parameters -- y = f(x, z) -- to the function!

(Sub-observation: A future OS would have an API call to granularly read a single named environment variable at a time (not the entire block of them at once!), and use of this call could be logged and sorted by program, and there would be a user-settable control to granularly determine which environment variables could be read by which programs/processes...)

>They're not globals, since they're copied into sub-processes; so mutation doesn't propagate upwards.

Mutation or non-mutation upwards -- is not the issue.

The issue is: If users run program f and they pass it various command line parameters x, and they want y, then if environment variables are present and if they alter the behavior of that program, then what the users are really getting is y = f(x, z), which may not be the behavior/result they want, because z influences the behavior, and is passed in a not-really-all-that-transparent manner (most people usually don't check, log or modify environment variables nor account for them in the determinism of their programs -- unless something is broken...)

Phrased another way -- a future OS would have some way of logging everything, all state information (including environment variables which includes registry settings) -- that go into any given program.

Now maybe environment variables aren't "globals" in the strictest definition...

But let's see...

In most modern operating systems as of 2025, environment variables can easily be read by most programs, functions/procedures/methods inside of those programs, sub-functions/sub-procedures/sub-methods of those programs, etc., etc., etc.

Once they can be read... they can become the state of one or more variables in that program its functions, sub-functions, etc.

And once it can become the state of those one or more internal variables, the program can alter its behavior / result -- based on them.

Global variables -- can do the same exact same thing to a program.

So I'll leave it as a linguistic/semantic debate to future readers, mathematicians, programmers and OS designers -- as to whether or not environment variables (and related globally readable objects such as the Windows Registry) are global variables...

(You are very much correct about environment variables -- if they are mutated (aka written to/overwritten) by by a sub-process, then that mutation doesn't typically propapagate upwards the parent/creator process chain -- but perhaps in the context of my discussion, I am interested/concerned about -- the global readability/accessibility of environment variables... But you are very much correct in your statement!)

I think the key point that I am trying to make is that more transparency/insight/logging could always be had as to where exactly programs get ALL of their inputs from (this includes environment variables, this includes API calls which may differ machine to machine, etc., etc.), and what average end users are made aware of...

Re: Environment variables are a legacy mess: Let's dive deep into them

#186

Earlier quoted context omitted.

> environment variables are to programs (especially chains of programs, parent processes, sub processes and sub-sub processes, etc.) what parameters are to functions -- and/or what command-line parameters are... they're sort of like global variables that get passed around a lot... They're not globals, since they're copied into sub-processes; so mutation doesn't propagate upwards. My own opinion is that environment va…

>They're not globals, since they're copied into sub-processes; so mutation doesn't propagate upwards. If we broaden our thinking to look at a computer process as a mathematical function , i.e., if we think about a computer process as y = f(x) Where y is the behavior of the function (what final state it results in / resolves to), f is the process itself, and x is the parameter or list of parameters that are passed to…

I think you misunderstand my point. Forget mutation; that was a minor technicality, but isn't important for my point.

My point is that environment variables are "dynamic variables" (AKA they are "dynamically bound", AKA they have "dynamic scope" https://en.wikipedia.org/wiki/Scope_(computer_science)#Dynam... ). That is very much not like globals.

For example, consider the following script:

    #!/usr/bin/env bash
    # The export keyword turns a shell variable into an env var
    export foo='hello'
    echo "BEFORE '$foo'"
    # Invoke the env command as a subprocess, to list all of the
    # environment variables it's inherited. Filter it using grep.
    foo='goodbye' env | grep 'foo='
    echo "AFTER '$foo'"
Our hypothesis will be that env vars are "globals", i.e. that there's a place in memory that all these occurrences of the name `foo` are referring to. Under this hypothesis, there are several plausible outputs that the above script might give:

Perhaps the `foo='hello'` assignment sets the memory referred to by foo to the value `hello`; then the `foo='goodbye'` assignment sets that memory to `goodbye`. In which case we'd expect to see:

    BEFORE 'hello'
    foo=goodbye
    AFTER 'goodbye'
On the other hand, perhaps the `foo='goodbye'` assignment fails (maybe since that memory already contains the value `hello`?), in which case we would expect to see something like:

    BEFORE 'hello'
    foo=hello
    AFTER 'hello'
It might even be the case that some obscure issue causes both assignments to fail; but, by sheer coincidence, the memory `foo` is referring to just-so-happens to already contain the value `goodbye`. In that case, we'd expect to see:

    BEFORE 'goodbye'
    foo=goodbye
    AFTER 'goodbye' 
Now, let's test our hypothesis by performing the experiment, i.e. by executing the script:

    BEFORE 'hello'
    foo=goodbye
    AFTER 'hello'
Uh oh, that doesn't correspond to any of the possibilities I gave! With a little more thought, we might see that this output cannot be produced using a single memory location; since the value `hello` was not "forgotten", even though foo had the value `goodbye`.

The answer is that env vars are not globals; instead, they are "dynamic variables". Normally, programming languages implement dynamic variables internally by traversing the stack; e.g. in Lisp it would look something like:

    (let ((foo "hello"))
      (echo (format "BEFORE '%s'" foo))
      (let ((foo "goodbye"))
        (echo (filter (has-prefix "foo=")
                      (something-like-the-locals-function-in-python)))
      (echo (format "AFTER '%s'" foo)))
However, that wouldn't work across process boundaries; which is why env vars get copied (perhaps with additions/removals) when subprocesses are created.

(I go into more detail in the blog post I linked ;) )

PS: You may be wondering why I wrote a script containing `foo='goodbye'` if I previously said "Forget mutation". That is because we are not mutating the value of `foo`; we are entering a new scope, where `foo` has a different value; but the old scope with the old value still exists; we saw as much when it outputs `AFTER 'hello'`. Similar to how in "lexical scope" (a more common form of scoping, which is different from global scope and from dynamic scope) we can write a whole bunch of functions with arguments called `x`, but that doesn't count as mutating the value of `x`. Or we can even call the same function, perhaps recursively, with different values for the same argument; but those new values are not mutations of the old ones, despite them having the same name and being defined in the same place (like dynamic scope, lexical scope is also typically implemented within a process by using stack frames).

Re: Environment variables are a legacy mess: Let's dive deep into them

#188

Earlier quoted context omitted.

Yes you can? The container should be completely agnostic to the fact that it's running in kubernetes. You can do config the same way. Configmaps are mounted as regular files and environment variables. The application doesn't care if the configmap came from the cluster resource or a file your created on your dev machine with dev credentials. You can mount local files into the container yourself. It's docker run -v "so…

One of you is talking about mapping a secret to an environment variable and the other one of you is talking about having the work load make an API call to retrieve the secret. You’re not even talking about the same thing.

The k8s api server is the thing that's configured to talk to your Thales or whatever. On managed kubernetes, these are usually preconfigured to talk to the vendor -- that's the difference between a secret and a config map. The secret is encrypted when it's stored in etcd.

You'd be forgiven for being mistaken however, because this encryption is handled in a way that's transparent to the application.

If you're talking about your application making a call to the k8s api server, then you shouldn't do that unless you're developing a plugin. The kubelet knows how to retrieve and mount secrets from the k8s api server and display them as environment variables to the application. You just declare it as a part of your deployment in the podspec.

Re: Environment variables are a legacy mess: Let's dive deep into them

#189
post #142

Earlier quoted context omitted.

It's not your (unprivileged user account's) place to decide the security posture of the entire system, that's why you're running into issues with root. Even Yama, an LSM, requires root (or de facto equivalent) for initial setup (as it should). Namespaces, if done incorrectly, can significantly increase the attack surface of the entire system (mount namespaces especially need to be treated with care) and same with reg…

> It's not your (unprivileged user account's) place to decide the security posture of the entire system, that's why you're running into issues with root. Tell that to literally any unprivileged user who would like to run any sort of software without exposing their entire account to any possible code execution bug or malicious code in the software they're running. > The real security barrier on most operating systems…

Isn't this part of what containers/flatpaks solve?

Re: Environment variables are a legacy mess: Let's dive deep into them

#190

Earlier quoted context omitted.

>They're not globals, since they're copied into sub-processes; so mutation doesn't propagate upwards. If we broaden our thinking to look at a computer process as a mathematical function , i.e., if we think about a computer process as y = f(x) Where y is the behavior of the function (what final state it results in / resolves to), f is the process itself, and x is the parameter or list of parameters that are passed to…

I think you misunderstand my point. Forget mutation; that was a minor technicality, but isn't important for my point. My point is that environment variables are "dynamic variables" (AKA they are "dynamically bound", AKA they have "dynamic scope" https://en.wikipedia.org/wiki/Scope_(computer_science)#Dynam... ). That is very much not like globals. For example, consider the following script: #!/usr/bin/env bash # The e…

If I am understanding you correctly, you are stating that a given shell, specifically a subshell -- may not in some cases see the same shell variables as other shells...

That is true.

Subshells may not in some cases see the same shell variables as in other shells.

I'm not contesting this.

But let's suppose that we have not a shell variable, but a socket...

A socket that any program can open -- and retrieve a web page from...

For the simplicity of thought, let's say that the data for that web page is always static.

It always returns the same web page; the same data for that web page...

So now my question to you:

Can that socket, which can be opened by any program, mimic a global variable?

?

Why or why not?

?

Or perhaps an even simpler question...

Let's suppose that there's a file on filesystem... globally accessible to be read and written to by all programs...

Can that file's presence mimic a global variable?

?

Why or why not?

?

Post reply on HN