Warum würden Sie "cat / dev / null> / var / log / messages"?

77

Auf dieser Bash-Skript-Beispielseite präsentiert der Autor das folgende Skript:

# Cleanup
# Run as root, of course.

cd /var/log
cat /dev/null > messages
cat /dev/null > wtmp
echo "Log files cleaned up."

Warum würdest du cat /dev/nullauf irgendetwas stehen? Ich kann nicht verstehen , was hier gemeint ist (ist es wie mit while TRUE; sleep 1; elihwfür {some busy program}?). Der Autor nennt es jedoch „nichts Ungewöhnliches“.

Isomorphismen
quelle

Antworten:

41

In der Regel, cat /dev/null > [something]wenn Sie den Dateiinhalt löschen und gleichzeitig sicherstellen möchten, dass das Risiko einer Unterbrechung des tatsächlichen Dateizustands absolut Null ist. Der Inhalt der Datei wird eindeutig von der cat /dev/nullDatei selbst gelöscht. Die Datei selbst, die vorhanden ist und dem Dateisystem, auf dem sie sich befindet, bekannt ist, ist weiterhin mit derselben Inode-Nummer, demselben Besitz und denselben Berechtigungen vorhanden.

Im Fall einer Protokolldatei kann es sein, dass die Protokolldatei selbst von einem anderen Prozess als "in Verwendung" markiert wird. Wenn Sie dies beispielsweise tun, rm /var/log/messages && touch /var/log/messageswürde dies andere Prozesse stören und möglicherweise dazu führen, dass laufende Prozesse ersticken. Das bedeutet, dass ein Prozess, der irgendwie an eine bestimmte Inode-Nummer gebunden ist, die mit der Datei verbunden ist, /var/log/messagesplötzlich in Panik geraten und sagen kann: „Hey! Was ist passiert? /var/log/messages“, Auch wenn die Datei noch vorhanden ist. Ganz zu schweigen von potenziellen Problemen, bei denen Eigentum und Berechtigungen falsch wiederhergestellt werden.

Aufgrund dieser Unsicherheit in Bezug auf die Verwendung / den Status einer Datei wird die Verwendung von cat /dev/null > [something]von Systemadministratoren bevorzugt, die ein Protokoll löschen möchten, aber den Betrieb bereits vorhandener Prozesse nicht potenziell beeinträchtigen möchten .

Auch im Zusammenhang mit der Seite , die Sie verknüpfen den Autor besagt Folgendes:

Hier gibt es nichts Ungewöhnliches, nur eine Reihe von Befehlen, die genauso einfach einzeln über die Befehlszeile auf der Konsole oder in einem Terminalfenster aufgerufen werden konnten. Die Vorteile der Platzierung der Befehle in einem Skript gehen weit über die Notwendigkeit hinaus, sie nicht immer wieder neu eingeben zu müssen.

Das „Nichts Ungewöhnliches“, das der Autor erwähnt, bezieht sich auf das gesamte Konzept dieses speziellen Bash-Skripts: Es handelt sich nur um eine Reihe einfacher Befehle, die genauso einfach über die Befehlszeile ausgeführt werden können, aber in einer Textdatei abgelegt werden vermeiden Sie es, sie immer wieder neu eingeben zu müssen.

JakeGould
quelle
10
@jlliagre Das einzige, was "am Leben erhalten" wird, ist der Kontext der Frage, der sich darauf konzentriert, warum der ursprüngliche Autor das tun würde. Wenn Sie leidenschaftlich daran interessiert sind, den "Mythos" zu zerstreuen, senden Sie bitte eine Antwort, die den Kontext für die Codierungsmethode des ursprünglichen Autors sowie eine Perspektive darüber enthält, warum Sie glauben, dass sie durch andere Methoden ersetzt werden kann.
JakeGould
7
@jlliagre Cyrus 'Antwort geht weder auf die Kernfrage ein, warum der ursprüngliche Autor diese Methode verwendet hätte, noch auf die Argumentation dahinter. Das erwähnte Tutorial ist ziemlich alt und akzeptabel. Es ist weder falsch noch verewigt es eine angebliche "städtische Legende". Vielmehr ist es die Art und Weise, wie eine Person Codes gegen die Art und Weise, wie eine andere Person Codes. So einfach ist das. Dies ist ein Stilproblem, das sich nicht negativ auf die Zuverlässigkeit oder Leistung auswirkt.
JakeGould
3
truncate -s 0würde das gleiche tun und weniger idiomatisch sein. Shell-Programmierer sind jedoch eine konservative Gruppe, und man könnte auf Systeme stoßen, die alt genug oder verrückt genug sind, um diesen Befehl nicht zu haben.
Schwern
5
@skift schneidet cat /dev/null > /foo/bardie Datei ab; echo "" > /foo/barschneidet es ab und schreibt dann ein einzelnes Zeilenumbruchzeichen.
David
2
Ein weiterer Vorteil dieser Methode gegenüber rm & touch ist, dass Eigentumsrechte und Berechtigungen erhalten bleiben.
jjmontes
121

Warum würden Sie / dev / null auf irgendetwas setzen?

Sie tun dies, um den Inhalt einer Datei zu kürzen, während der Inode intakt bleibt. Alle Programme, in denen diese Datei zum Lesen oder Schreiben geöffnet ist, wären nicht betroffen, außer die Dateigröße würde auf Null zurückgesetzt.

Eine falsche Alternative, die oft gefunden wird, ist das Entfernen der Datei und das erneute Erstellen:

rm file
touch file

oder ähnliches:

mv file file.old
gzip file.old
touch file

Das Problem ist, dass diese Methoden nicht verhindern, dass die alte Datei von allen Prozessen geschrieben bleibt, bei denen die gelöschte Datei zum Löschzeitpunkt geöffnet ist. Der Grund, warum Sie unter Unix-Dateisystemen beim Löschen einer Datei nur deren Namen (Pfad) vom Inhalt (Inode) trennen. Die Inode bleibt so lange am Leben, wie es Prozesse gibt, bei denen sie zum Lesen oder Schreiben geöffnet ist.

Dies führt zu mehreren negativen Auswirkungen: Die Protokolle, die nach dem Löschen der Datei geschrieben wurden, gehen verloren, da das Öffnen einer gelöschten Datei nicht auf einfache / tragbare Weise möglich ist. Solange ein Prozess in die gelöschte Datei schreibt, belegt sein Inhalt immer noch Speicherplatz im Dateisystem. Das heißt, wenn Sie die Datei entfernen / erstellen, weil sie Ihren Datenträger gefüllt hat, bleibt der Datenträger gefüllt. Eine Möglichkeit, das letztere Problem zu beheben, besteht darin, die Protokollierungsprozesse neu zu starten. Möglicherweise möchten Sie dies jedoch nicht für kritische Dienste tun, und zwischengeschaltete Protokolle würden definitiv verloren gehen. Es gibt auch Nebenwirkungen, da die von Ihnen erstellte Datei möglicherweise nicht dieselben Berechtigungen, Eigentümer und Gruppen wie die ursprüngliche besitzt. Dies kann beispielsweise dazu führen, dass ein Protokollanalysator die neu erstellte Datei nicht liest oder dass der Protokollierungsprozess keine eigenen Protokolle schreibt.

Die erste Methode, cat /dev/null > fileum das Ziel richtig zu erreichen , macht trotz einer hartnäckigen urbanen Legende cat /dev/nullabsolut nichts Sinnvolles. Es öffnet eine Pseudodatei, die vom Design her leer ist, es kann nichts daraus lesen und wird schließlich einfach beendet. Die Verwendung dieses Befehls ist dann eine Verschwendung von Tastenanschlägen, Bytes, Systemaufrufen und CPU-Zyklen und kann ohne Funktionsänderung durch den zweifellos schnelleren No-Op-Befehl :oder, bei den meisten Shells, durch überhaupt keinen Befehl ersetzt werden.

Lassen Sie mich eine Metapher versuchen, um zu erklären, wie nutzlos es cat /dev/nullist. Nehmen wir an, Ihr Ziel ist es, ein Glas zu leeren.

  • Sie entfernen zuerst die Flüssigkeit. Dies ist ausreichend und genau das, was ( > file) tut, da Umleitungen immer zuerst verarbeitet werden.

  • Dann nimmst du eine leere Flasche ( /dev/null) und gießt sie in das leere Glas ( cat). Dies ist der sinnlose Schritt ...

Wenn Sie Ihr verlinktes Dokument bis zum Ende lesen , werden Sie möglicherweise die Kommentare in dieser Zeile aus der erweiterten Version des Skripts bemerken:

    cat / dev / null> wtmp #   ':> wtmp' und '> wtmp' haben den gleichen Effekt.

Sie haben in der Tat; Schade, cat /dev/nullwurde im Code gehalten.

Das bedeutet, dass der folgende Code für alle gängigen Shells (sowohl cshals auch für shFamilien) funktioniert :

cd /var/log
: > messages
: > wtmp
echo "Log files cleaned up."

und dies wird mit allen Schalen arbeiten , um die Bourne - Syntax, wie ash, bash, ksh, zshund die Gleichen:

cd /var/log
> messages
> wtmp
echo "Log files cleaned up."

Beachten Sie jedoch, dass bei alten Bourne-Shells vor POSIX keiner dieser Befehle, einschließlich cat /dev/null, eine Datei abschneidet, wenn sie anschließend von einem noch laufenden Shellskript geschrieben wird, das daran angehängt wird. Anstelle einer Null-Byte-Datei wäre dies eine Sparse-Datei mit unveränderter Größe. Dasselbe würde passieren, wenn die Datei von einem Prozess geschrieben wird, der vor dem Schreiben nach der Position sucht, die er für die aktuelle hält.

Beachten Sie auch, dass einige alternative Lösungen, die häufig zum Abschneiden einer Datei vorgeschlagen werden, Fehler aufweisen.

  • Die beiden folgenden erledigen den Job einfach nicht. Die resultierende Datei ist nicht leer, sondern enthält eine leere Zeile. Dies würde Protokolldateien beschädigen wtmp, in denen Datensätze mit fester Breite gespeichert sind.

    echo > file
    echo "" > file
    
  • Das nächste, das auf einer BSD- shOption basiert, ist nicht portierbar. POSIX gibt keine zulässigen Optionen für Echo an, sodass Sie möglicherweise eine Datei mit einer Zeile mit " -n" erhalten:

    echo -n > file
  • Dieser ist auch nicht tragbar, wenn eine System V- shEscape-Sequenz verwendet wird. Einige Shells erstellen eine Datei mit einer Zeile " \c":

    echo "\c" > file
  • Dieser verwendet einen Befehl, der für die Ausführung der Aufgabe vorgesehen ist. Das verwendete Problem ist truncatenicht portierbar, da dieser von POSIX nicht angegebene Befehl auf einem Unix / Linux-System möglicherweise fehlt.

    truncate -s 0

Schließlich sind hier einige Alternativen aufgeführt, die portabel sind und die Arbeit ordnungsgemäß erledigen:

  • Explizites Drucken einer leeren Zeichenfolge in die Datei:

    printf "" > file
  • Verwenden Sie den trueBefehl, der genau dem No-Op-Befehl entspricht, :obwohl er besser lesbar ist:

    true > file
jlliagre
quelle
1
@ JonathanLeffler Ich glaube, es ist Teil aller aktuellen cshImplementierungen, obwohl es nicht unbedingt dokumentiert ist. Von der Solaris- csh Handbuchseite : Null command. This command is interpreted, but performs no action.. Ich habe weder in der tcshHandbuchseite noch in der Original-BSD erwähnt csh, dasselbe, aber diese Syntax hat möglicherweise immer funktioniert.
Juli
6
Ein Grund zum Schreiben cat /dev/nullbesteht darin, Ihre Absichten deutlich zu machen.
Davidmh
1
@Davidmh Das wäre sinnvoll, aber Ihre Aussage widersteht keinen Faktenprüfungen. Ich habe dieses Shell-Idiom wahrscheinlich seit ein paar Jahrzehnten beobachtet. Als ich die Gelegenheit hatte, den Autor nach den Hintergründen zu fragen, bekam ich immer wieder unklare Theorien darüber /dev/null, wie man Null Bytes effizient injiziert, jedenfalls zuverlässiger als mit :oder ohne. Auf genau dieser Seite hatte Cyrus Antwort, die knapp, aber direkt auf den Punkt gebracht war, null Stimmen, während JakeGoulds, der die Tatsache cat /dev/nullin Frage stellte, ein No-Op war (siehe unsere Kommentare), bereits mindestens vier Stimmen hatte.
Juli
2
@jlliagre Mein Wissen über die Shell ist ziemlich grundlegend, daher bin ich vielleicht nicht das beste Bevölkerungsziel. aber eine nackte >oder :ist nicht klar. Ich stimme zu, es ist eine Schande, dass Mythen aufgrund ihrer Verwendung verbreitet wurden.
Davidmh
4
@Davidmh Wenn Sie wirklich etwas Explizites vor der Umleitung wollen, würde ich empfehlen, printf "" > filedas sowohl portabel (POSIX) als auch leicht wie eine eingebaute Shell implementiert ist.
Juli
6

Dies ist eine umständliche Methode, um die Datei auf die Größe Null zu bringen.

cd /var/log
> messages
> wtmp
echo "Log files cleaned up."
Cyrus
quelle
Diese Syntax funktioniert nicht in jeder Shell.
reinierpost
2
Richtig. Die Frage ist nur mit "bash" markiert.
Cyrus
@reinierpost Es funktioniert in allen Bourne-Shells, nicht wahr? Machen wir uns keine Sorgen csh.
Barmar
: > messagesfunktioniert auch. :oder truesind die naheliegenderen Optionen für Befehle, die nichts ausgeben und true zurückgeben.
Peter Cordes
-3

So kürzen Sie eine geöffnete Datei. Dies ist äquivalent und verständlicher:

echo -n > /var/log/messages

(Hinzugefügt -n, um den Zeilenumbruch zu vermeiden)

bbaassssiiee
quelle
3
Dies ist zwar nachvollziehbarer, aber leider nicht gleichwertig. Es wird sogar Funktionen wie im wtmpFall brechen . Siehe meine aktualisierte Antwort.
Juli,
echo -n vermeidet Zeilenumbruch.
bbaassssiiee
6
Es wird in der Tat, wenn Sie sicher sind, zu verwenden bash, -nist ansonsten nicht garantiert, dass es in allen Bourne-Shells funktioniert.
Juli