7

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?

slm
  • 369,824
Yalla T.
  • 181

4 Answers4

5

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.

slm
  • 369,824
  • 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
  • 1
    hash node returns 1 if node is not on PATH, not if it wasn't already hashed. – Lri Apr 23 '13 at 17:48
  • hash node returns 1 if hashing disabled in Bash:) See answer for details. – Evgeny Jul 29 '15 at 11:05
4

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.

Didi Kohen
  • 1,841
1

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.

Anthon
  • 79,293
0

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.

Lri
  • 5,223