Was macht `Datum 2 &> $ 0`?

6

Ich schaue mir einen Mitarbeiter-Shell-Code an und habe Folgendes gesehen:

date 2&>$0

Ich weiß, welches Datum es tut, aber was macht 2 &> $ 0? Er ist eine Weile weg, also kann ich ihn nicht fragen, worum es in diesem Teil ging.

j0h
quelle
3
Sind Sie sicher, dass es genau das ist, was es sagt? Das ist nicht normal zu schreiben.
Michael Homer
Ja, ich denke, es ist ein stderr Redirect F * von seiner Seite? Ich bin nur auf der Suche nach einer zweiten Meinung, da ich nicht sicher bin, was genau dort passieren würde.
J0H
Das sieht aus wie eine Knebelschnur (wie die berühmte Gabelbombe). Ich bezweifle ernsthaft, dass dies in einem echten Code auftreten würde (und wenn ja, ist es gefährlich und macht keinen Sinn). Oder es ist möglich, dass er beabsichtigte zu schreiben date 2>/dev/null, um eine fehlerfreie Datumsausgabe zu erzeugen, und fehlgeschlagene Spektren.
Orion
4
Sieht für mich eher nach einem Tippfehler aus, bei dem "Datum 2> & 0" vorgesehen war ...
Brian C

Antworten:

8

Zusammenfassung

Befindet sich bashdieser Befehl in einem Skript, wird die Skriptdatei mit einer Fehlermeldung überschrieben.

Beispiel

Betrachten Sie das Skript:

$ cat test.sh
date 2&>$0

Führen Sie nun das Skript aus:

$ bash test.sh
test.sh: line 2: unexpected EOF while looking for matching ``'
test.sh: line 3: syntax error: unexpected end of file

Beachten Sie den neuen Inhalt des Skripts:

$ cat test.sh
date: invalid date `2'

Erläuterung

Der Befehl date 2&>$0wird wie folgt interpretiert:

  1. Der dateBefehl wird mit Argument ausgeführt2

  2. Alle Ausgaben, sowohl stdout als auch stderr, vom Befehl date werden in die Datei umgeleitet $0. $0ist der Name des aktuellen Skripts.

    Das Symbol >zeigt standardmäßig die Umleitung von stdout an. Als bashErweiterung, das Symbol &>ist eine Verknüpfungsanzeige Umleitung von sowohl stdout und stderr. Folglich werden sowohl stdout als auch stderr in die Datei umgeleitet $0.

  3. Sobald die Skriptdatei überschrieben wurde, ist sie nicht mehr gültig und bashbeschwert sich über die fehlerhaften Befehle.

Unterschied zwischen bashund POSIX-Shells

Bei einer einfachen POSIX-Shell wie dashwird die Verknüpfung &>nicht unterstützt. Daher date 2&>$0leitet der Befehl nur stdout in die Datei um $0. In diesem Fall bedeutet dies, dass die Skriptdatei mit einer leeren Datei überschrieben wird, während die dateFehlermeldung auf dem Terminal angezeigt wird.

John1024
quelle
2
… Aber das macht keinen Sinn ☹
törzsmókus
Ich möchte die wichtige Tatsache hinzufügen, dass der Test auch zeigt, dass bash das Skript "zeilenweise" interpretiert: Die ursprüngliche Zeile ändert das Skript selbst ($ 0), und es scheint, dass bash nicht nur die erste Zeile ausgeführt hat: Es wurde fortgesetzt um den neuen Inhalt des Skripts zu interpretieren (Zeile 1 war die Zeile "Datum ...", Zeile 2 ist wahrscheinlich die neue Zeile 1 im Skript, die Zeile mit der Fehlermeldung des Datums). Wie Sie sehen können: Es hat die Datumsausgabe interpretiert, das Backquote (ungefähr 2) gesehen und nach dem passenden Backquote gesucht!
Olivier Dulac
10

Unter der Annahme, dass der von Ihnen eingegebene Code korrekt ist, ist das, was er tut, sehr seltsam. Es:

  • Läuft date 2, was kein gültiger Aufruf von ist dateund was dann eine Fehlermeldung erzeugt
  • Leitet sowohl die Standardausgabe als auch den Standardfehler um mit&> ,
  • In die Datei, die das ausgeführte Skript enthält ( $0), löschen Sie den vorhandenen Inhalt.

Da Bash das Skript so einliest, dass jeweils eine Zeile aus der Datei entnommen wird, wird die überschriebene Datei unsinnig und wird möglicherweise beendet (weil die Datei auf einen kürzeren Wert als den Punkt gekürzt wurde, an dem diese Zeile angezeigt wurde) oder Angabe eines Syntaxfehlers (wenn das Original sehr kurz war und ein Teil des Fehlers als nächste Zeile eingelesen wird).

Ich kann mir keine einzige legitime Verwendung für diese Zeile vorstellen, aber wie Sie sagen, Sie haben sie genau so angegeben, wie sie geschrieben steht, ist es das, was sie bewirkt.


Genau genommen ist es möglich $0, diesem Code einen anderen Wert zuzuweisen und ihn zerstörungsfrei auszuführen, indem Bash mit der -cOption aufgerufen wird: bash -c "$(<test.bash)" output-fileDie Fehlermeldung wird eingefügt output-file, aber es ist absolut verkehrt, dies zu tun.

Michael Homer
quelle