Problem beim Verstehen des „Hash“-Befehls in einer .sh-Datei

Problem beim Verstehen des „Hash“-Befehls in einer .sh-Datei

Ich wollte Etherpad Lite auf einem Linux-Rechner installieren. Wenn ich versuche, es auszuführen, erhalte ich den Fehler:

"Bitte installieren Sie node.js (http://nodejs.org)"

der Befehl which nodegibt mir den richtigen Pfad zu Node JS. Also ging ich in die .sh-Datei von Etherpad Lite und fand Folgendes:

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

Ich vermute, es bedeutet: Knoten prüfen --> wenn nicht verfügbar, Zeile drucken und beenden. Aber was genau macht dieser Code? Was macht Hash? Was hat es mit all dem &und auf sich >?

Ich wäre sehr dankbar, wenn mir jemand diese drei Zeilen erklären könnte.

Antwort1

Wenn Sie Befehle in einer Bash-Shell eingeben, sucht die Shell in der gesamten $PATH-Variable nach diesen Befehlen. Der Hash ist lediglich ein Index der von Ihnen eingegebenen Befehle und wo sie gefunden wurden, um das Auffinden beim nächsten Mal zu beschleunigen.

NOTIZ: @Anthons Antwortgibt eine gute Definition dessen, was Hash ist!

Wenn Sie beispielsweise nur den Befehl hashohne Argumente ausführen, erhalten Sie eine Liste der zuvor gefundenen Befehle sowie deren Häufigkeit (d. h. Treffer):

% 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

Der Befehl hash nodegibt einen Statuswert (0 oder 1) zurück, je nachdem, ob dieser Wert in der Hash-Liste vorhanden war oder nicht:

hash nodeist nicht auf meiner Liste

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

NOTIZ:Der Status aller zuvor ausgeführten Befehle wird vorübergehend in einer Umgebungsvariable gespeichert$?. Hier wird der Status (0 = erfolgreich, 1 = fehlgeschlagen) nach der Ausführung jedes Befehls eingetragen.

Die Konstruktion "cmd1" || { "cmd2" ... } ist eine Oder-Anweisung. Denken Sie hier logischerweise an und/oder. Das heißt also, führen Sie das Erste aus, und wenn es fehlschlägt, führen Sie das Zweite aus, andernfalls führen Sie das Zweite nicht aus.

Ein ausführlicheres Beispiel:

% 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

Die Logik ist immer verwirrend (zumindest für mich), da die Rückgabe einer 1 bedeutet, dass der Befehl fehlgeschlagen ist, während die Rückgabe einer 0 bedeutet, dass er erfolgreich ausgeführt wurde.

Antwort2

Zusätzlich zu den zuvor geposteten Antworten möchte ich eine Erklärung zum Teil „2>&1“ hinzufügen.

> /dev/null

Leitet den Ausgabedateideskriptor (Dateideskriptoren sind Zahlen, die der Prozess zum Lesen und Schreiben in Dateien, Pipes und das Terminal verwendet) auf die Datei /dev/null um, die eine „Grabberente“ des Systems ist, da sie alles liest, was in sie geschrieben wird, und diese Daten verwirft.

2>&1

Leitet den stderr-Dateideskriptor (eine Ausgabedatei für Fehler) mit der Nummer 2 zum Dateideskriptor 1 um, der gerade nach /dev/null umgeleitet, also ignoriert wurde.

Diese beiden Teile zusammen stellen also sicher, dass vom Hash-Befehl keine Ausgabe angezeigt wird.

Antwort3

Aus dem Bash-Handbuch:

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.

hashist ein interner Befehl für Bash, der zum Arbeiten mit der Hash-Tabelle verwendet wird, bashum vollständige Pfade zu den von Ihnen eingegebenen Befehlen nachzuschlagen.

Dieses Skript stellt damit sicher, dass nodeim Pfad nach der ausführbaren Datei gesucht wird.

Antwort4

hash nodedurchsucht PATH nach dem ersten Befehl mit dem Namen „Node“ und fügt den Speicherort von „Node“ zur Liste der gespeicherten Speicherorte hinzu oder aktualisiert ihn oder gibt 1 zurück, wenn „Node“ nicht gefunden wurde.

Hash wird anstelle von Which verwendet, weil:

  • das von POSIX nicht definiert ist.
  • In einigen Umgebungen ist dies ein CSH-Skript, das den Pfad ändern kann.
  • Beispielsweise ist in Bash Hash integriert, was jedoch nicht der Fall ist, und Hash ist normalerweise schneller.

Wie der OP in einem Kommentar erwähnte, bestand das Problem darin, dass der Knoten tatsächlich im Pfad fehlte, als das Skript ausgeführt wurde. Das which nodehätte also dasselbe Ergebnis gehabt.

verwandte Informationen