Observation: I have an executable named foo, located in /b/foo. It is compiled against an old header of a dynamic library, causing it to segfault when executed:
$ foo
Segmentation fault. // Expected behaviour.
Now, I compile a new version of foo to /a/foo against the new dynamic library that should execute just fine. Directory a/ is in my $PATH before b/, so /a/foo should be selected:
$ which foo
/a/foo
When I execute foo, the following happens:
$ foo
Segmentation fault.
Therefore, it seems that /b/foo gets executed, whereas "which" tells me that /a/foo should be executed. To make things weirder, when I run the full path $(which /a/foo), things run fine:
$ /a/foo
OK!
$ cp /a/foo .
$ ./foo
OK!
To go yet one step further, if I now delete /a/foo:
$ rm /a/foo
Then /b/foo must surely be chosen, right?
$ which foo
/b/foo
$ foo
bash: /a/foo: No such file or directory
$ $(which foo)
Segmentation fault. // Expected result.
Nope!
Fix: Source .bash_profile and .bashrc and the problem disappears.
Reproducibility: Every time. Just remove /a/foo, source ~/.bash_profile, create /a/foo, and the above observation re-occurs.
Question: Does anyone have an idea what went wrong here?
Hypothesis: "which" is up-to-date, but the system chooses based on "what was used to be the case". In my example above, /a/foo did not yet exist when the terminal was opened: I had only just created it. Therefore, when /a/foo was created, "which" did detect /a/foo, but the system still chose /b/foo, because it was somehow out of sync? But why is the system out of sync?
In this case, when you type a command, bash first looks in the cache. If it's not there, it searches the
– Mark Reed Jun 12 '17 at 15:38$PATH
. If it finds it, it stores the result in the cache for next time.