Why don't Go (lang) binaries show up in `which`, `whereis`, and similar tools?

0

I've installed a couple of Go utilities via go get -u github.com/[owner]/[repo] and I don't understand why they don't honor standard shell conventions. The utility I installed had no trace of anything in the directory the command was run from, nor any output indicating anything, so I looked for it via a fairly standard means, and couldn't find it, yet I was always able to run it:

~ $ which hey
~ $ hey
Usage: hey [options...] <url>

Options:
  -n  Number of requests to run. Default is 200.
  -c  Number of requests to run concurrently. Total number of requests cannot be smaller than the concurrency level. Default is 50.
[…]

I only figured it out because I noticed that the tail end of my $PATH includes :~/go/bin, and sure enough the three go utilities I've installed are present there. Saved me from a long winded find search.

How do Go installed binaries escape standard file lookup means, yet remain able to run?

This is occurring on a standard bash shell, as shipped with macOS High Sierra (10.13.6).

~ $ type -a hey
hey is /Users/jsalaz/go/bin/hey
~ $ type -a which
which is /usr/bin/which

VxJasonxV

Posted 2018-07-13T08:57:01.193

Reputation: 2 166

Assuming it's bash, can you show the output of type -a hey and even type -a which? – user1686 – 2018-07-13T09:06:43.123

I really don't use type enough, I think I can count the number of times on one hand. I tend to do direct inspection with ls flags to determine it's attributes. Will definitely store type -a away for future use… – VxJasonxV – 2018-07-13T09:09:35.370

Attributes? That's... not exactly what type is for. – user1686 – 2018-07-13T09:10:17.957

Answers

2

As far as I understand it, using ~/go/bin as a $PATH component relies on a nonstandard (perhaps GNU?) extension.

  • Whenever your shell (bash) searches for binaries, it expands the ~/ prefix to your home directory's path. You can see that type (which is built into the shell) finds the Go program just fine.

  • Meanwhile, the /usr/bin/which command (which is provided by macOS and is not part of the shell) does not perform this expansion, because no such thing was specified in The Open Group's official description of how $PATH should work.

In other words, the ~/ prefix is part of the shell language, but not part of the general OS-wide path syntax. In all other places, including $PATH (which is not limited to shells!), it simply means a directory named ~.

When setting $PATH, you need to make sure the paths are expanded at assignment time:

PATH=$PATH:~/go/bin
PATH=$PATH:$HOME/go/bin
PATH="$PATH:$HOME/go/bin"

This one won't work:

PATH="$PATH:~/go/bin"

user1686

Posted 2018-07-13T08:57:01.193

Reputation: 283 655

That’s, incredible. And true, in the past I’ve always used $HOME in $PATH and any other shell environment variables. This is no doubt another BSD coreutils (which macOS ships) vs GNU coreutils discrepancy. I need to test this on a Linux machine now too. – VxJasonxV – 2018-07-13T10:08:45.527