New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
System.Environment - Writing environment variables on Mac/Linux #21892
Comments
Mono doesn't implement User/Machine. Conceptually I'm OK with trying to expand the support here- it would be cool to get better equivalency. It is, however, out of scope for 2.0. |
I do not think that this works (just tried as well to be sure). |
That's not possible. The environment of a process is determined at process creation (by the parent process). After that, only the process itself can change the environment. |
I assume you meant to say how to set an environment variable that outlives the execution time of the current process. There is no reasonable way to do it on Unix. You need to use some other communication mechanism between child and the parent process - files, pipes, etc. |
@JeremyKuhne Based on my initial misconception on how dotnet could hook into shell builtin functionality to set environment variables in Linux for the parent shell, I think we can scrap that idea. Maybe it's still a good idea to add an extra paragraph within the remarks section for Mac/Linux to the documentation for setting environment variables? Currently, there is no information in there, explaining how this will work when executed on Linux/Mac. -- Some guidance on how to end up with similar behavior to using the "User" scope for setting variables in Windows when trying to get to the same behavior on Linux/Mac might help developers writing cross platform apps using dotnet. On Windows, I can just rely on the User scope for environment variables when I want to persist a value in the environment across executables running in their own process. That'll work fine. On Linux/Mac, you're right, there's no convenient way, but I played with this idea and it works for my purpose (with caveats that can be taken care of):
-- Thoughts? |
Throw PNSE for EnvironmentVariableTarget.{User,Machine} on Unix. |
Agree. We do have improving discoverability/documentation for platform differences on our backlog. |
Seems to me this we should definitely do. @polarapfel any interest in submitting PR for that? The fix is here https://github.com/dotnet/coreclr/blob/master/src/mscorlib/src/System/Environment.cs#L647 and https://github.com/dotnet/coreclr/blob/master/src/mscorlib/src/System/Environment.cs#L757 and a separate PR for tests here https://github.com/dotnet/corefx/blob/master/src/System.Runtime.Extensions/tests/System/Environment.GetEnvironmentVariable.cs |
Why? Arguments in favor of what we currently have:
|
@stephentoub I can see your point about Mono code remaining easily portable. But just silently ignoring unsupported environment scopes leads to situations where a developer familiar with how this works on Windows, wrongfully assumes it works the same way on Mac/Linux. For that reason, I actually think a PNSE makes sense in both CoreFX and Mono's .NET implementation. I think addressing documentation will already help as a first step. I'm happy to look into PR to add PNSE for unsupported scopes. |
I recently added macOS support to ps-nvm, which uses https://github.com/aaronpowell/ps-nvmw/blob/9784e5ada938a7485a6786371ac76b3ed78d37fb/nvm.psm1#L113 The scope argument being present in .netcore and the documentation not mentioning any different behaviour for macOS/Linux, I would have expected it to work on macOS. I don't know what exactly the Windows version does, but I assume it writes the variable to the registry. Therefor I would have expected something equivalent to happen on macOS - e.g. use |
I ran into this same issue, and it took me a while to get through to the root cause. Lack of exceptions or relevant docs was a bit of an issue. I feel a PR is in order, to the code or the docs or both, in order to save the next person their time. @polarapfel have you had the time to work on your PR? If not, I could try to look into that. |
I just ran into this. took few hours to know what was wrong! |
I have moved this issue to the documentation repo: dotnet/docs#6277 |
…nsics.Vector types (#20147) * Renaming Vector64.cs, Vector128.cs, and Vector256.cs to be Vector64_1.cs, etc * Adding some core helper methods to the Vector64, Vector128, and Vecto256 types. * Adding some documentation comments to the System.Runtime.Intrinsics.Vector types * Changing `Set` to `With` Signed-off-by: dotnet-bot <dotnet-bot@microsoft.com>
…nsics.Vector types (#20147) * Renaming Vector64.cs, Vector128.cs, and Vector256.cs to be Vector64_1.cs, etc * Adding some core helper methods to the Vector64, Vector128, and Vecto256 types. * Adding some documentation comments to the System.Runtime.Intrinsics.Vector types * Changing `Set` to `With` Signed-off-by: dotnet-bot <dotnet-bot@microsoft.com>
Hi,
@stephentoub @jkotas @JeremyKuhne @eerhardt
I've been looking at System.Environment and how to read and write Environment variables on Linux/Mac, using the 1.04 release and 2.0 preview currently available. With the 2.0 preview, the APIs expanded to allowing the use of the EnvironmentVariableTarget enum, which features the Process, User and Machine scope where as prior to this, only the Process scope was implemented as a default.
Unfortunately, this is not helpful at all on Linux/Mac. With the current API in 2.0 preview (and prior API versions), setting environment variables on Linux/Mac do not bind to the underlying shell process, they live within the scope of the dotnet process executing the assembly setting the environment variable(s) and stop to exist once dotnet terminates assembly execution. Using other scopes (e.g. User, Machine) on non-Windows platforms) is not mapped in the implementation. This is fairly useless for persisting information to be used by other processes.
Example:
Only FOOBAR_DEFAULT and FOOBAR_CURRENT will be set on Linux while the app executes and running
/bin/bash -c export
after this sample terminated shows that both variables are gone and don't exist anymore.What's the plan here to fix this?
To my knowledge, Mono simply implements reading/writing environment variables on Unix/Linux using the same namespace(s) as in .NET, Mono.Unix.Native/Mono.Posix have nothing added to specifically read and write environment variables. Hence, my expectation would be to have this very basic stuff handled with an identical abstraction in CoreFX that is not platform dependent?
For Linux, there is of course no scope such as "Machine" and "User" would bind to the underlying shell process (and any child process starting after the fact through inheritance).
The current scope of implementation in 2.0 preview should be fixed to make the "User" scope work on Mac/Linux, where it binds to the scope of the underlying shell.
As a workaround to properly set environment variables on Linux/Mac, one could simply query
RuntimeInformation.IsOSPlatform(OSPlatform.Linux)
and use System.IO to check for the presence of any familiar shell (sh, ksh, and bash, maybe also from other shell families such as csh) in the file system and then write simple wrappers calling to their built-in functions to set environment variables correctly such asWhatever the API implementation in CoreFX is going to be (for Mac/Linux), it should work and have the same outcome as making a call to the shell built-ins for managing environment variables.
--
Thanks,
Tobias W.
The text was updated successfully, but these errors were encountered: