go icon indicating copy to clipboard operation
go copied to clipboard

proposal: cmd/go: add a way to query for non-defaults in the env

Open mvdan opened this issue 6 years ago • 16 comments

It's common to ask users to provide go version and go env when they report a bug. There is one problem with that, though - the output is getting huge, and most of it is generally useless. For example:

$ go version
go version devel +b38be35e4c Tue Sep 10 09:12:32 2019 +0000 linux/amd64
$ go env
GO111MODULE="on"
GOARCH="amd64"
GOBIN="/home/mvdan/go/bin"
GOCACHE="/home/mvdan/go/cache"
GOENV="/home/mvdan/.config/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GONOPROXY="brank.as/*"
GONOSUMDB="brank.as/*"
GOOS="linux"
GOPATH="/home/mvdan/go"
GOPRIVATE="brank.as/*"
GOPROXY="https://proxy.golang.org"
GOROOT="/home/mvdan/tip"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/home/mvdan/tip/pkg/tool/linux_amd64"
GCCGO="gccgo"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/dev/null"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build021884514=/tmp/go-build -gno-record-gcc-switches"

What's special about my environment? You can easily spot GO111MODULE or GOBIN as they are commonly set, and they are near the top. But what variables have I actually modified from the defaults on my system?

It would be useful to quickly see what Go env variables were specifically modified by a user. That is, what could be special about the user's environment, that could help in reproducing a bug they're running into.

I can kind of get that right now with a bit of shell hackery, showing the changes between my go env and the same go env with an empty environment:

$ diff <(env -i /usr/bin/go env) <(/usr/bin/go env) | grep '^>'
> GO111MODULE="on"
> GOBIN="/home/mvdan/go/bin"
> GOCACHE="/home/mvdan/go/cache"
> GOENV="/home/mvdan/.config/go/env"
> GONOPROXY="brank.as/*"
> GONOSUMDB="brank.as/*"
> GOPATH="/home/mvdan/go"
> GOPRIVATE="brank.as/*"
> GOPROXY="https://proxy.golang.org"
> GOMOD="/dev/null"
> GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build040980257=/tmp/go-build -gno-record-gcc-switches"

This is much better. It even has some surprises - I botched my GOPROXY by forgetting ,direct, for example. And I'm not sure why GOGCCFLAGS is different. GONOPROXY and GONOSUMDB are also a bit redundant as they simply follow GOPRIVATE here, but that's a minor thing.

It would be useful to be able to print a summary like the above, perhaps with go env -diff or go env -changed. Note that the idea is to show what's different from the defaults on that machine, so usually GOARCH and GOOS wouldn't be included.

mvdan avatar Sep 10 '19 14:09 mvdan

This got no attention, so I'm rewriting it into a proposal.

mvdan avatar Jan 27 '20 11:01 mvdan

I think this is a good idea, both because it helps us and because it might help the user with "bugs" that are really misconfigurations. Would it make sense to simply enhance the existing output with a trailing shell comment for the modified ones, that way it still copy-pastes as environment variable settings? E.g.

$ go env
GO111MODULE="on"                   # instead of ""
GOARCH="amd64"
GOBIN="/home/mvdan/go/bin"
GOCACHE="/home/mvdan/go/cache"
GOENV="/home/mvdan/.config/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GONOPROXY="brank.as/*"             # instead of ""
GONOSUMDB="brank.as/*"             # instead of ""
GOPROXY="https://proxy.golang.org" # instead of "https://proxy.golang.org,direct"
(etc)

dr2chase avatar Jan 28 '20 16:01 dr2chase

That would work for me too. Though that might be a little too close to shell syntax for people's comfort :)

I also wonder if backwards compatibility would be a problem. For example, export $(go env) could break if we add that output, as we'd go from export FOO=x BAR=y to export FOO=x #instead of "" BAR=y. So we'd need a new "be helpful and show me the non-defaults" flag for humans.

mvdan avatar Jan 28 '20 16:01 mvdan

We briefly discussed this in today's tools call. @jayconrod mentioned comments, but I'm still a bit worried about those in case anyone is expecting simple export word list syntax instead of the full source shell syntax supporting comments.

Another idea that came out during the call would be extending go env -json. In theory, that would allow us to add extra information without breaking any previous users. Unfortunately, the format of the output is just map[string]string with each key-value being each of the variable names and values, so we can't fit any more information there easily. Unless we go for something a bit funky like adding a second json object at the end of the output, like:

$ go env -json
{
    "FOO": "bar",
    [...]
}
{
    "nonDefaults": ["FOO"]
}

cc @bcmills

mvdan avatar Sep 16 '20 18:09 mvdan

what about explaining where each value comes from?

$ go env -src
GO111MODULE="on"                   # default
GOARCH="amd64"                     # environment, default "arm64"
GOBIN="/home/mvdan/go/bin"         # GOENV, default ""
GOCACHE="/home/mvdan/go/cache"     # GOROOT/go.env, default ""
GOENV="/home/mvdan/.config/go/env" # default

seankhliao avatar May 20 '23 16:05 seankhliao

I see why this could possibly be useful but it's also a giant pain. I am not sure the benefit is worth the effort.

rsc avatar Dec 04 '23 16:12 rsc

Does someone want to prototype this to see if there is a simple implementation?

rsc avatar Dec 06 '23 18:12 rsc

This proposal has been added to the active column of the proposals project and will now be reviewed at the weekly proposal review meetings. — rsc for the proposal review group

rsc avatar Dec 09 '23 18:12 rsc

Placed on hold. — rsc for the proposal review group

rsc avatar Feb 08 '24 23:02 rsc

Does someone want to prototype this to see if there is a simple implementation?

I have been working on one. The proposal has been placed on hold though. Are there any further details that can be shared about that?

suntala avatar Feb 10 '24 08:02 suntala

We place proposals on hold if we think they may be valuable but want more information before committing to a decision. In this case we'd like to see an implementation and its effect on cmd/go.

seankhliao avatar Feb 10 '24 11:02 seankhliao

I wrote a prototype for this proposal that will work well on my computer. output in my computer:

go env -changed
set GO111MODULE=auto
set GOCACHE=D:\file\go-build
set GOPATH=D:\file\gofile
set GOPROXY=https://goproxy.cn,direct
set GOSUMDB=sum.golang.org
set GOTOOLCHAIN=local
set GOAMD64=v3
set CGO_ENABLED=1

qiulaidongfeng avatar Feb 11 '24 05:02 qiulaidongfeng

Change https://go.dev/cl/563137 mentions this issue: cmd/go: add -chaged to query for non-defaults in the env

gopherbot avatar Feb 11 '24 05:02 gopherbot

@seankhliao, I think a flag for the source of the setting would be useful (like git config --show-origin), but probably shouldn't be the default (it complicates the parsing).

An interesting related question, though, is: what should go env -changed do for positional arguments? (Probably print a blank line for each unchanged variable named on the command line?)

bcmills avatar Feb 14 '24 20:02 bcmills

This proposal has been added to the active column of the proposals project and will now be reviewed at the weekly proposal review meetings. — rsc for the proposal review group

rsc avatar Feb 14 '24 23:02 rsc

Probably print a blank line for each unchanged variable named on the command line?

I think go env -changed only prints the non-default values of the environment variables that go env will print. For example:

$ set GOTOOLCHAIN=local
(Other environment variables are unchanged)
$ go env -changed
$ set GOTOOLCHAIN=local

See https://github.com/golang/go/issues/34208#issue-491707830

It's common to ask users to provide go version and go env when they report a bug. There is one problem with that, though - the output is getting huge, and most of it is generally useless.

If print blank line, Once the go env -changed is use in the future in https://github.com/golang/go/issues/new?assignees=&labels=&projects=&template=00-bug.yml&title=import%2Fpath%3A+issue+title Empty lines take up space in the browser display, but do not help with handle bugs.

qiulaidongfeng avatar Feb 15 '24 02:02 qiulaidongfeng

The question is what happens with 'go env -changed GOPATH GOROOT GOMODCACHE' for example. Without -changed, this would print

% go env GOROOT GOPATH GOMODCACHE
/Users/rsc/go
/Users/rsc
/Users/rsc/pkg/mod
% 

In this case, GOROOT is arguably unchanged, as is GOMODCACHE; but GOPATH is changed. So is this what it prints?

% go env -changed GOROOT GOPATH GOMODCACHE
/Users/rsc
% 

If so, how do you know which of the three values got printed?

This is why @bcmills recommended the blank line, which makes sense to me:

% go env -changed GOROOT GOPATH GOMODCACHE

/Users/rsc

% 

Only programs are likely to use this anyway, and they can read the blank lines well enough.

The usage of go env in issues would be unaffected: we all agree that plain go env -changed does not print blank lines, because it is printing name=value pairs, so there is no ambiguity about what the environment variable names are.

rsc avatar Mar 01 '24 17:03 rsc

use https://go.dev/cl/563137

my machine

in windows

$ go env -changed GOPATH GOROOT GOMODCACHE
set GOPATH=D:\file\gofile

in wsl2

$ go env -changed GOPATH GOROOT GOMODCACHE
GOPATH='/mnt/d/file/gofile/'

Because the print format can always be name=value, so I don't think I need to print empty lines.

qiulaidongfeng avatar Mar 02 '24 03:03 qiulaidongfeng

OK, this seems fine.

rsc avatar Mar 13 '24 17:03 rsc

Have all remaining concerns about this proposal been addressed?

The proposal is to add a new flag to go env: ‘go env -changed’.

With no other flags or arguments, ‘go env -changed’ prints all non-default settings in the form key=value, one per line, same as ‘go env’ does (just fewer lines).

When there are command-line arguments, as in ‘go env -changed X Y Z’, the command behaves exactly like ‘go env -changed’ except it limits the consideration to X, Y, and Z. It still omits default settings. This output has a different form from ‘go env X Y Z’ in that it includes the ‘key=’ prefixes (or ‘set key=’ on Windows).

When using ‘go env -json -changed’, the JSON only includes the changed values. ‘go env -json -changed X Y Z’, similarly limits the consideration to X, Y, and Z.

rsc avatar Mar 15 '24 01:03 rsc

Based on the discussion above, this proposal seems like a likely accept. — rsc for the proposal review group

The proposal is to add a new flag to go env: ‘go env -changed’.

With no other flags or arguments, ‘go env -changed’ prints all non-default settings in the form key=value, one per line, same as ‘go env’ does (just fewer lines).

When there are command-line arguments, as in ‘go env -changed X Y Z’, the command behaves exactly like ‘go env -changed’ except it limits the consideration to X, Y, and Z. It still omits default settings. This output has a different form from ‘go env X Y Z’ in that it includes the ‘key=’ prefixes (or ‘set key=’ on Windows).

When using ‘go env -json -changed’, the JSON only includes the changed values. ‘go env -json -changed X Y Z’, similarly limits the consideration to X, Y, and Z.

rsc avatar Mar 27 '24 18:03 rsc

I think this would solve the problem I was having here as well where I didn't realize i was setting an empty string which was different than the default.

https://github.com/golang/go/issues/62485

nemith avatar Mar 28 '24 20:03 nemith

No change in consensus, so accepted. 🎉 This issue now tracks the work of implementing the proposal. — rsc for the proposal review group

The proposal is to add a new flag to go env: ‘go env -changed’.

With no other flags or arguments, ‘go env -changed’ prints all non-default settings in the form key=value, one per line, same as ‘go env’ does (just fewer lines).

When there are command-line arguments, as in ‘go env -changed X Y Z’, the command behaves exactly like ‘go env -changed’ except it limits the consideration to X, Y, and Z. It still omits default settings. This output has a different form from ‘go env X Y Z’ in that it includes the ‘key=’ prefixes (or ‘set key=’ on Windows).

When using ‘go env -json -changed’, the JSON only includes the changed values. ‘go env -json -changed X Y Z’, similarly limits the consideration to X, Y, and Z.

rsc avatar Apr 04 '24 21:04 rsc

Change https://go.dev/cl/586095 mentions this issue: cmd/go/internal/envcmd: fix showing GODEBUG env value

gopherbot avatar May 16 '24 14:05 gopherbot

Change https://go.dev/cl/586241 mentions this issue: cmd/go: print not-defaults arch-env

gopherbot avatar May 18 '24 03:05 gopherbot