Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

So I wanted to install etherpad lite on a linux machine.

If I try to run it, I will get the Error "Please install node.js ( http://nodejs.org )"

the command 'which node' gives me the correct path to node js.

So I went into the .sh File of Etherpad Lite and found this:

    #Is node installed?
  hash node > /dev/null 2>&1 || { 
  echo "Please install node.js ( http://nodejs.org )" >&2
  exit 1 
}

I guess it means: check for node --> if not available print line and exit. But what exactly does this code do? what does hash do? What's with all these & and > ? Anybody who can explain to me this 3 lines would be really appreciated.

share|improve this question
    
Why are you tagging it "bash" if it's a "sh" script? –  Stéphane Chazelas Apr 23 '13 at 15:58
1  
because i dont know the difference, sorry. –  Yalla T. Apr 23 '13 at 16:12

4 Answers 4

up vote 1 down vote accepted

As you type commands within a bash shell, the shell is looking for those commands throughout the $PATH variable. The hash is just a index of which commands you've typed and where they were found to help speed up the finding of them next time.

NOTE: @Anthon's answer gives a good definition of what hash is!

For example, if you run just the command hash with no arguments, you'll get a list of what commands have been found previously along with how many times they've been used (i.e.: hits):

% hash
hits    command
   2    /usr/bin/host
   1    /bin/more
   1    /home/saml/bin/autossh_mail.sh
   3    /usr/bin/zip
   2    /bin/rm
   2    /bin/date
   2    /usr/bin/vim
   1    /usr/bin/htop
   2    /bin/mv
   3    /bin/ps
   8    /usr/bin/ssh
   1    /usr/bin/yum
   1    /usr/bin/xfreerdp
   1    /bin/cp
   2    /bin/mkdir
   4    /usr/bin/man
   1    /usr/bin/gvim
   1    /usr/bin/unzip
   1    /usr/bin/w
   5    /usr/bin/nslookup
  51    /bin/ls
  15    /usr/bin/find

The command hash node returns a status value (0 or 1) depending on whether that value was present on hash's list or not:

hash node isn't on my list

% hash node
bash: hash: node: not found
% echo $?
1

NOTE: The status of any previously run command is temporarily stored in a environment variable $?. This is where the status (0 = success, 1 = failed) is put after every command is executed.

The construct "cmd1" || { "cmd2" ... } is an or statement. Think and/or from logic here. So that means do the first thing, if it fails, then do the second, otherwise don't do the second thing.

A more elaborate example:

% true && echo "1st cmd ret. 1" || echo "1st cmd ret. 0"
1st cmd ret. 1

% false && echo "1st cmd ret. 1" || echo "1st cmd ret. 0"
1st cmd ret. 0

The logic is always confusing (at least to me) because a 1 being returned signifies the command failed, while a 0 being returned signifies that it ran successfully.

share|improve this answer
1  
Allright thanks! Thanks to your answers i did understand this code and I narrowed the problem down to My $PATH is missing the 'node' entry when accessed from the sh file. –  Yalla T. Apr 23 '13 at 16:18
    
hash node returns 1 if node is not on PATH, not if it wasn't already hashed. –  ؘؘؘؘ Apr 23 '13 at 17:48

From the bash manual:

Each time hash is invoked, the full pathname of the command name
is  determined  by searching the directories in $PATH and remembered.  
Any previously-remembered pathname is discarded.

hash is an internal command to bash, used to work with the hash-table bash uses to look up full paths to commands you type.

This script uses it to make sure the node executable is searched for in the path.

share|improve this answer

In addition to the previously posted answers, I would like to add an explanation of the "2>&1" part.

> /dev/null

Is redirecting the output file descriptor (file descriptors are a number the process uses to read and write to files, pipes and the terminal) to the file /dev/null which is a "grabage can" of the system, as it reads whatever is written to it, and discards that data.

2>&1

Redirects the stderr (an output "file" for errors) file descriptor that is numbered 2 to file descriptor 1, which was just redirected to /dev/null, i.e. ignored.

So both of these parts together make sure that no output will be seen from the hash command.

share|improve this answer

hash node searches PATH for the first command named node and adds or updates the location of node on the list of remembered locations or returns 1 if node was not found.

hash is used instead of which because:

  • which is not defined by POSIX.
  • In some environments which is a csh script that can change PATH.
  • For example in bash hash is a builtin but which is not, and hash is usually faster.

As the OP mentioned in a comment, the problem was that node was actually missing from PATH when the script was run. So which node would have had the same result.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.