vscode: Environment variables defined in `tasks.json::tasks.options.env` do not overwrite existing environment variables
Code: 1.22.2 macOS: 10.13.3
When I create a task, I want to provide a very specific environment (which is why I bother filling out the JSON values). However, if an environment variable is pre-existing, it will not be overwritten in the execution environment of the task.
I am extremely surprised by this behavior. I discovered this by not being able to find a library I was building with a task when specifying DYLD_LIBRARY_PATH
.
A very simple test is to update ~/.bash_profile
to include
export FOO=bar
Then attempt to override it with tasks.json
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "diagnostic",
"type": "shell",
"options": {
"cwd": "${workspaceFolder}/beam",
"env": {
"FOO": "baz",
}
},
"command": "printenv",
"problemMatcher": []
}
]
}
Output:
...
FOO=bar
...
A “task” appears to execute . ~/.bash_profile
to set it’s environment. Since it is already creating a new environment for each execution, it would be nice if I could override the values as I see fit, by specifying the values in tasks.options.env
.
About this issue
- Original URL
- State: closed
- Created 6 years ago
- Reactions: 6
- Comments: 51 (21 by maintainers)
This issue and the handling of “env” options in
tasks.json
is kind of confusing. I am developing on Windows and Linux (and prototyping for the latter on WSL) and adding to what @zfields reported, I have created thistasks.json
.Results (without FOO or BAR set/exported in the parent shell that executes
code
)env{FOO}= env{BAR}= var{BAR}=BAZ
env{FOO}= env{BAR}= var{BAR}=
env{FOO}= env{BAR}= var{BAR}=BAZ
Results (with set/exported FOO=foo BAR=bar in the parent shell that executes
code
)env{FOO}=foo env{BAR}=bar var{BAR}=BAZ
env{FOO}=foo env{BAR}=bar var{BAR}=
env{FOO}=foo env{BAR}=bar var{BAR}=BAZ
I am assuming that Mac OS behaves like Linux.Update 2019/02/13: MacOS behaves like Linux.Tested with Visual Studio Code 1.31.
Bottom line is:
${env:...}
only expands environment variables that were set in the parent shell that rancode
. It doesn’t expand variables set in thetasks.json
env options.%var%
expands env variables from thetasks.json
options when running cmd.exe. So does$var
for real Linux bash. But on WSL,$var
doesn’t expand env variables from thetasks.json
options.%var%
(cmd.exe
) and$var
(Linux bash) may expand to values different from${env:var}
ifvar
was set in code’s parent shell.Is this a bug or by design??
FWIW, I would prefer if
${env:var}
would also expand the env options of thetasks.json
file, superseding everything that was set in the environment ofcode
’s parent shell. If${env:var}
is the standard way to expand environment (and env options) variables, the task’s command may be unified across platforms because there’s no need for$var
vs.%var%
.If not a bug, would that be a feature request?
This deserves reconsideration. Yes, I know the value that’s going to be expanded, but I’d like to not check this value into source code.
I’d really like the ability to run tasks with arguments passed from
launch.json
, but pre-defining my environment or arguments intasks.json
is a non-starter for me. I need a.env
orlocal.settings.json
or equivalent file that I can read from and.gitignore
.NOT ok to close.
How is VSCode setting the environment variables I request in
tasks.options.env
?Yes.
What is the point of specifying
tasks.options.env
, if putting everything in thecommand
string is the only reliable way to ensure the environment variables are getting set?It seems like I have identified a bug for you, and you have identified a solution. However, you are suggesting that I hack it in place, instead of VSCode correctly assembling the command string by prepending the setting of environment variables to the specified
command
.To use your example, VSCode is taking a command string from me, and also has all the environment variables I wish to have set.
Why isn’t VSCode capable of constructing the following string on my behalf, before passing
myCommand
to its internal command line API?Now that we are on the same page with the behavior, shouldn’t this be marked a bug - instead of a feature request?
I specify environment variables in my task, but I do not see them in the environment in which VSCode executes the task.
In other words, the behavior does not meet reasonable expectations, and is impacting my workflow (smells like a bug). The main reason I am pushing for the distinction is because I know “bugs” get prioritized and fixed while “feature requests” get punted.
To provide some context, I work at a cross platform shop, and I’m trying to get them to switch over to VSCode instead of using native IDEs for each platform. As you know, people resist change and things like this make it easy for people to pick apart, even when it is an awesome product. Please help me get this fixed.
Just to confirm…
I cold booted my Mac
Opened VSCode to a new folder on the system
Added a new task “diagnostic”, based on the “Others” template
I execute the task from the “Tasks >> Run Task…” menu
~/.bash_profile
How is this happening, if executing a task from the UI in VSCode is not loading environment varialbes from
~/.bash_profile
?My expectation is as follows. If I am defining environment variables in
tasks.options.env
, then I would expect those environment variables to be available to the task, regardless. In other words,tasks.options.env
should override everything else.Specifically,
DYLD_LIBRARY_PATH
is very important to me. Several of my workflows require my company’s release libraries (i.e.export DYLD_LIBRARY_PATH=/Users/zfields/lib
set in~/.bash*
). However, when I’m in a development environment I will need to override the release libraries with debug versions.../debug/lib
so I can step through and debug.It would be great if I could simply override
DYLD_LIBRARY_PATH
in the task, so I can develop and debug without modifying my file system.Sorry for the short answer. Normally bash defines that
~/.bash_profile
should only be considered when the shell / terminal is a login shell (for example when you login over ssh into a machine). However the standard Mac Terminal application doesn’t stick to this rule and considers the content of~/.bash_profile
for all started shell (hence the behavior you are seeing). When I retested this today I used the standard Mac Terminal as was able to reproduce the behavior you are seeing.No, I wasn’t aware the setting existed, so any behavior is the default behavior of VSCode. Following on, does it stand to reason that VSCode does in fact consume
~/.bash_profile
?If so, are you able to inject the environment variables I have supplied in
tasks.options.env
, AFTER it consumes~/.bash_profile
? If you can, it would truly be helpful when constructing an environment in which to execute a task (the crux of the issue at hand).https://dbj.org/how-to-build-software-and-still-have-some-time-for-programming/
I can confirm this works as expected now, and the point of this original issue has been resolved to my satisfaction.
Thank you!
I will reactive my Mac and will have a look beginning of next week.
@jwmurray Please open a separate issue for your experience, as it is not directly related to this issue. This issue is still open / under investigation, and it took forever for the bug listed above to be recognized and confirmed by Microsoft. I’m sorry to shut you down, but there has been enough confusion on this thread.
@dbaeumer It has been several months since you were going to test again on your Mac, and I am curious if you have been able to land on a solution.
Should this work the same on Windows?
I have the following task:
and get the following output:
Not sure why $message is not expanded to the environment variable that is being set.
@zfields thanks a lot for testing this. I will look into why some of the behavior is unexpected.
Regarding 2.) this is expected in the sense that things from
~/.bashrc
should not influence shells started with -c (which tasks do). If you want a different behavior you need to removefrom the beginning however then exports from the
~/.bashrc
will always win.Can you let me know in terms of variables which once you want to define were and which once should win?
I see your point. On the other hand we need to work around a
bug
caused by another tool 😃.I am still not sure if we should try to fix this on our end since it will for sure introduce another set of problems (command line length if a lot of environment variables are set, …). When reading about it people advised the following trick:
~/.bashrc
with this at the beginning~/.bashrc
fileI haven’t tested this but I think it should work around the problem for now.
This is really strange since values from the profile should only be sourced when
--login
is specified and the rc files usually have interactive check at the beginning. Have you configured anything special on our machine.We don’t inject something into the shell to keep it consistent with the process type were we can’t do such tricks and rely on what the process sees when executed.
I will keep the item open to consider it as a feature request to treat this different for
shells
I tried this on Apple and Linux and in both cases the
~/.bash_profile
was not source for me unless I used a login shell. This is why I ask you what happens for you when you run bash from a different shell or even form a terminal already running bash without--login
. Will the code from~/.bash_profile
be executed.I think we are talking past each other, maybe we should take two steps back…
I have no desire to use a shell. In fact, I ONLY want to use VSCode.
However, when running a “shell task” in VSCode (i.e.
diagnostic
from above), I happened to notice VSCode picks up environment variables that are only set in my~/.bash_profile
. If you are not able to reproduce this on your non-Apple device, then perhaps it IS platform specific.I think we need to make sure we are experiencing the same behavior, before we can attempt to solve this problem.