If you installed a program (with apt, yum, or compiled it and then installed – or whatever) and then you try to run it.

# gem

but you get the error (even though you know gem exists in one of your PATH directories):

-bash: /usr/bin/gem: No such file or directory

What you need to do to fix this is run (THE SOLUTION)

hash -r

A close look at how this happens by example

What happened is this, lets take a look at example above. Im trying to run “gem” which is a program that comes with “ruby”. First I have installed ruby 1.9.1

apt-get install ruby

And that installed it (ruby, gems, and other executables) to its various directories (such as /usr/bin/). After running ruby I noticed it wasnt new enough (however at this point bash remembered that ruby and gem are all located in /usr/bin and it saved it into its “hash” table – the bash hash table is a list of program names and the locations from where they are run from) However I realized after that ruby 2.1.2 exist. And that I need to compile it and install it. So I delete my current ruby

apt-get remove ruby

Then I download ruby 2.1.2 and I untar it, and I run the typical

./configure && make && make install

which if you understand that linux compiling process, make install will copy all of the compiled executables (in this case ruby, and gems and the like) to its install folder. Which happened to be /usr/local/bin/.

The problem is that bash looks for apps in the following order:

1. thru its hash table (for quickest look up)

2. thru the folders in PATH variable (can be seen with echo $PATH)

Example:

# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

We have bash thinking gem and ruby are running from /usr/bin because of the original install of ruby1.9.1 (specifically the first time we run an app thats not in the hash table it looks thru the PATH, then it puts its path in the hash table – so if somethings in the hash table it can skip doing the PATH lookup to save time). So after uninstalling ruby1.9.1 and installing the new ruby2.1.2 (which saved to a different location), bash doesnt know that and bash keeps trying the old location of /usr/bin. So to fix that you can simply clear the hash table with hash -r (note that hash is a built in bash command). so clearing the full table, will now make bash look for gem or ruby through all of the paths in PATH and it will find its new location.

Note the hash table also keeps track of the number of times the command is run.

# hash
hits command
1 /usr/bin/which
3 /usr/local/bin/gem
1 /bin/ls

From below website: http://ss64.com/bash/hash.html

hash

Remember the full pathnames of commands specified as name arguments, so they need not be searched for on subsequent invocations.

SYNTAX
      hash [-r] [-p filename] [name] 

OPTIONS
      -r   Reset (causes the shell to forget all remembered locations)
      -p   Use filename as the location of name (don't search $PATH)

The commands are found by searching through the directories listed in $PATH.

If no arguments are given, information about remembered commands is printed.

The return status is zero unless a name is not found or an invalid option is supplied.

hash is a bash built in command.

“I spent most of the eighties, most of my life, riding around in somebody else’s car, in possession of, or ingested of, something illegal, on my way from something illegal to something illegal with many illegal things happening all around me” ~ Iggy Pop

Here is an example of a hash table

Leave a Reply

Your email address will not be published. Required fields are marked *