[SOLVED] Does bash remember where it found an executable ?
Linux - NewbieThis Linux forum is for members that are new to Linux.
Just starting out and have a question?
If it is not in the man pages or the how-to's this is the place!
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
I'm currently experimenting with firejail. It's a tool that can put applications in a sandbox. It comes with lots of predefined profiles for standard applications like firefox (hence the name), geany, meld, ...
However, I'm not happy with some of the profiles, e.g. for geany (a text editor) and meld (a diff/merge tool). I'm still learning to configure firejail, but in the meantime I prefer to disable it for those applications. Disabling works by removing a symlink from /usr/local/bin. During my experiments, I'm removing and re-adding the symlink back and forth.
( For those who are interested in more detail, the symlink points to /usr/bin/firejail, which in turn checks with which name it was called, then reads the corresponding profile, and starts the application with the same name in a sandbox. )
And here comes the problem:
Once bash had found e.g. meld in /usr/local/bin (the symlink), it will only look for it it there. If I remove the symlink try to start meld, bash will complain about /usr/local/bin/meld not found. But the original is still in /usr/bin. And $PATH is /usr/local/bin:...:/usr/bin:... so I thought it should work.
At least
Code:
which meld
says
Code:
/usr/bin/meld
Does bash remember where it once found "meld" and refuse other locations from that moment on ?
And is there a way to make it forget that location (other than starting a new shell) ?
Bash will keep a history of the interactive session. See "man bash" for the built-in command history and the file ~/.bash_history in the section "SHELL BUILTIN COMMANDS" and the whole section "HISTORY"
Also look at the content of the environment variable $PATH. It is described in the manual page's sub section "Shell Variables".
I don't think it's about the history. I did not start meld including the path (like /usr/local/bin/meld) but only typed "meld", so the history only contains "meld".
To my undrstanding, typing "meld" (without any path) again should search the whole $PATH but it doesn't.
As I wrote in my original post, $PATH contains /usr/local/bin as well as /usr/bin.
Ah. I understand now. I'm not sure of a solution, but I see that when an executable disappears or is moved, Bash keeps looking for it in the old location rather than re-checking $PATH for it. This might be a bug.
Ah. I understand now. I'm not sure of a solution, but I see that when an executable disappears or is moved, Bash keeps looking for it in the old location rather than re-checking $PATH for it. This might be a bug.
I would say this is the usual cache problem: commands are cached to be able to find and execute them faster, but sometimes the cache will be outdated....
The "hash" command is listed under the Bourne/POSIX built-in section, so is not Bash specific (nobody actually said it was, but I somehow made that assumption).
Quote:
hash [-r] [-p filename] [-dt] [name]
Each time hash is invoked, it remembers the full pathnames of the commands specified as name arguments, so they need not be searched for on subsequent invocations. The commands are found by searching through the directories listed in $PATH. Any previously-remembered pathname is discarded. The -p option inhibits the path search, and filename is used as the location of name. The -r option causes the shell to forget all remembered locations. The -d option causes the shell to forget the remembered location of each name. If the -t option is supplied, the full pathname to which each name corresponds is printed. If multiple name arguments are supplied with -t, the name is printed before the hashed full pathname. The -l option causes output to be displayed in a format that may be reused as input. If no arguments are given, or if only -l is supplied, information about remembered commands is printed. The return status is zero unless a name is not found or an invalid option is supplied.
In addition to the mentioned "set +h" there is also a "shopt checkhash" option that appears to be subtly different:
Quote:
-h
Locate and remember (hash) commands as they are looked up for execution. This option is enabled by default.
Quote:
checkhash
If this is set, Bash checks that a command found in the hash table exists before trying to execute it. If a hashed command no longer exists, a normal path search is performed.
From those descriptions, it sounds like the latter might maintain some performance benefits of avoiding path lookups, though I'm not sure there'd be a noticeable difference for most scripts, unless PATH happens to be really long and/or reference a slow filesystem.
From those descriptions, it sounds like the latter might maintain some performance benefits of avoiding path lookups, though I'm not sure there'd be a noticeable difference for most scripts, unless PATH happens to be really long and/or reference a slow filesystem.
or I'd think for loop that's run a million times?
Back in the day before even Perl was a normal thing, a lot of 'glue' was written using $<shell>, so on an old school prod box, that (hash) would have been beneficial in getting the work done noticeably faster.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.