4 Stimmen

Wie kann man eine Datei aus einem Shell-Skript heraus umschreiben, ohne das Risiko einer Trunkierung der Datei bei vollem Speicherplatz?

Wie kann eine Datei aus einem Shell-Skript neu geschrieben werden, ohne die Datei zu beschneiden, wenn der Speicherplatz aufgebraucht ist?

Dieses praktische Perl-One-Liner ersetzt alle Vorkommen von "foo" durch "bar" in einer Datei namens test.txt:

perl -pi -e 's/foo/bar/g' test.txt

Dies ist sehr nützlich, aber ...

Wenn das Dateisystem, auf dem sich test.txt befindet, keinen Speicherplatz mehr hat, wird test.txt zu einer leeren Datei beschnitten.

Gibt es einen einfachen Weg ohne Rennbedingungen, um diese Beschneidung zu vermeiden?

Ich möchte, dass die Datei test.txt unverändert bleibt und der Befehl einen Fehler zurückgibt, wenn das Dateisystem keinen Platz mehr hat.

Die Lösung sollte idealerweise einfach aus einem Shell-Skript verwendet werden können, ohne zusätzliche Software installieren zu müssen (außer den "Standard"-UNIX-Tools wie sed und perl).

Vielen Dank!

4voto

Greg Bacon Punkte 127209

Im Allgemeinen kann dies nicht gemacht werden. Denken Sie daran, dass der Speichermangel überall entlang der Sequenz von Aktionen auftreten kann, die das Aussehen einer Bearbeitung am selben Ort vermitteln. Sobald das Dateisystem voll ist, kann perl möglicherweise vorherige Aktionen nicht rückgängig machen, um den ursprünglichen Zustand wiederherzustellen.

Ein sichererer Weg, den Schalter -i zu verwenden, besteht darin, eine nicht leere Sicherungssuffix zu verwenden, z. B.,

perl -pi.bak -e 's/foo/bar/g' test.txt

So haben Sie im Falle eines Problems immer noch Ihre Originaldaten.

Wenn Sie Ihre eigene Lösung entwickeln möchten, achten Sie darauf, den Rückgabewert des Systemaufrufs close zu überprüfen. Wie auf der Linux-Handbuchseite angegeben,

  

Das Nichtüberprüfen des Rückgabewerts von close() ist ein häufiger, aber dennoch schwerwiegender Programmierfehler. Es ist durchaus möglich, dass Fehler bei einem früheren write(2)-Vorgang erst bei close() gemeldet werden. Das Nichtüberprüfen des Rückgabewerts beim Schließen der Datei kann zum stillen Datenverlust führen. Dies kann insbesondere bei NFS und bei der Festplattenkontingentierung beobachtet werden.

Wie bei allem im Leben, lassen Sie sich mehr Spielraum für Fehler. Festplatten sind billig. Suchen Sie das Kleingeld aus Ihren Sofakissen heraus und kaufen Sie sich etwa eine halbe Terabyte oder so.

3voto

amon Punkte 56276

Von perldoc perlrun:

-i[Erweiterung]

gibt an, dass von der "<>"-Konstruktion bearbeitete Dateien direkt geändert werden sollen. Dies geschieht, indem die Eingabedatei umbenannt wird, die Ausgabedatei unter dem ursprünglichen Namen geöffnet wird und diese Ausgabedatei als Standard für print()-Anweisungen ausgewählt wird. Die Erweiterung, falls angegeben, wird verwendet, um den Namen der alten Datei zu modifizieren und eine Sicherungskopie zu erstellen, unter Beachtung der folgenden Regeln:

Wird keine Erweiterung angegeben, wird keine Sicherungskopie erstellt und die aktuelle Datei wird überschrieben.

[...]

Umschrieben:

  1. Der Name der Sicherungskopie wird anhand des Werts des -i-Schalters bestimmt, falls einer angegeben ist.
  2. Die Originaldatei wird in den neuen Dateinamen umbenannt und für das Skript geöffnet. Die Umbenennung ist auf den meisten Dateisystemen atomar.
  3. Eine Datei mit dem Namen der Originaldatei wird zum Schreiben geöffnet. Die Datei beginnt mit einer Länge von null, ist aber nicht identisch mit der Originaldatei (die jetzt einen anderen Namen hat).
  4. Nachdem das Skript beendet wurde und keine explizite Sicherungskopiererweiterung bereitgestellt wurde, wird die Sicherungskopie gelöscht. Die Originaldatei geht dann verloren.

Sollte das System keinen Speicherplatz mehr haben, ist die neue Datei gefährdet, nicht die Originaldatei, die nie kopiert oder verschoben wurde (zumindest auf Dateisystemen mit einem inode-ähnlichen Konzept).

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X