Wenn ständig in eine Datei geschrieben wird und ich die Kontrolle über die Datei mit root übernehmen möchte, könnte ich Folgendes tun:
sudo rm somefile; sudo touch somefile
Kann der Anhängevorgang zwischen diesen beiden Befehlen an die Datei anhängen? Wenn ja, gibt es eine Möglichkeit, um sicherzustellen, dass kein anderer Befehl dazwischen ausgeführt wird?
Antworten:
Eine verkettete Befehlszeile ist im Grunde ein kleines Shell-Skript. Der erste Befehl wird mit der üblichen fork + exec-Prozedur ausgeführt, auf das Beenden gewartet und der zweite auf die gleiche Weise ausgeführt. Zwischen den beiden Befehlen gibt es eine beliebige Zeitspanne, die die Shell für ihre Buchhaltung und Verarbeitung benötigt, während der gewöhnliche Mehrfachverarbeitung stattfindet und beliebige andere Prozesse beliebige andere Dinge tun können. Die Antwort lautet also "Nein". (Wenn Sie dies tatsächlich tun, werden Sie feststellen, dass der Verzeichniseintrag für
somefile
verschwindet, aber die Datei selbst bleibt (da sie von einem Prozess geöffnet wird), bis sie geschlossen wird. Der von der Datei verwendete Speicherplatz wird erst dann zurückgefordert Dertouch
Befehl erstellt eine neue, nicht verwandte Datei mit demselben Namen und Pfad.)Wenn Sie den Besitz der Datei in root ändern möchten, tun Sie dies einfach
sudo chown root:root somefile
(obwohl ich nicht sicher bin, wie sich dies auf Prozesse mit einem geöffneten Dateihandle auswirkt). Wenn Sie den aktuellen Dateiinhalt zerstören möchten, versuchen Sie estruncate -s 0 somefile
(der laufende Prozess wird weiterhin an die jetzt leere Datei angehängt). Wenn es etwas anderes ist, klären Sie vielleicht, was Sie tun möchten.quelle
chown
Einige Dateien wirken sich nicht auf Prozesse aus, die ein Dateihandle für eine Datei haben.exec 3>somefile; sudo chmod 0600 somefile; echo hello world >&3; sudo cat somefile; exec 3>&-
.Nein. Ein
rm
Befehl, dem ein Befehl folgt,touch
ist überhaupt nicht atomar. Es wird eine lange Zeit zwischen den beiden Befehlen dauern - möglicherweise im Millisekundenbereich. In dieser Zeit kann viel passieren. Wenn Sie Pech haben, laufen Ihre Sudo-Anmeldeinformationen möglicherweise sogar ab.Ein einzelnes Programm, das die Aufrufe
unlink
undopen
aufruft, würde ein viel kürzeres Fenster für ein Rennen lassen, aber es könnte immer noch passieren.Ein sicherer Ansatz wäre, die neue Datei mit einem temporären Namen zu erstellen und den
rename
Systemaufruf zu verwenden. Das "Überschreiben" eines Namens mit demrename
Systemaufruf ist garantiert atomar. Dies könnte mittouch
und erreicht werdenmv
.Ein Prozess, der die alte Datei zum Schreiben geöffnet hat, kann jedoch noch lange nach dem Löschen darauf schreiben. Dies ist sowohl für eine mit
unlink
als auch für eine gelöschte Datei der Fallrename
.quelle
Sobald ein Prozess ein Dateihandle zum Lesen geöffnet hat, spielt es keine Rolle, was Sie mit dem Besitz oder den Berechtigungen tun: Der Prozess kann weiterhin auf die Datei zugreifen. Sie können die Datei sogar löschen und der Prozess kann weiterhin über das Dateihandle darauf zugreifen.
Betrachten Sie die Berechtigungen als Steuergatter zum Abrufen eines Dateihandles.
Wenn Sie eine Datei atomar erstellen möchten, gehen Sie stattdessen folgendermaßen vor:
Sie könnten dies in Betracht ziehen:
das wird atomar ersetzen
somefile
mitanotherfile
. (Ich hätte es vorgezogen, zu verwenden,mv -f
aber ich kann keine Anweisung finden, die garantiert, dass dies denrename(2)
Systemaufruf aufruft .Vielleicht könnten Sie Ihre Frage aktualisieren, um zu erklären, was Sie unter "Kontrolle über die Datei übernehmen" verstehen. Möglicherweise haben Sie hier ein XY-Problem .
quelle
mv -f
diese Option , um einenrename(2)
Systemaufruf zu erhalten . Sie haben Recht, dasln
wird nicht, weil es immer denlink(2)
Systemaufruf verwendet, der nicht atomar ersetzt werden kann.ln -f
tut nur zuerstunlink(2)
auf das Ziel.ln
im Gehirn. Ich war mir nicht sicher, wie ichrename(2)
garantiertmv
"Aktionen ausführen soll, die" entsprechenrename(old, new)
. pubs.opengroup.org/onlinepubs/9699919799/utilities/mv.html .mv -f
wirkt wiemv -i
wenn das Ziel nicht beschreibbar ist, aber es ist nicht wiecp -f
oderln -f
wo es zuerst entkoppeln wird.Nein, aber
sudo rm somefile; sudo touch somefile
ist in den meisten Situationen sicher.
Die meisten Prozesse öffnen Dateien und verwenden dann den erfassten Dateideskriptor, um auf den Dateiinhalt zuzugreifen.
Wenn ein Prozess eine Datei öffnet, in sh:
Dann kann ein anderer Prozess die Verknüpfung einer Datei aufheben (= entfernen), und der Dateiskriptor, auf dem eine Datei beim ersten Prozess geöffnet war (in diesem Fall 3), verweist weiterhin auf den ursprünglichen Inhalt einer Datei, die jetzt eine Datei in der Schwebe ist.
erstellt eine neue, nicht verwandte Somefile, und alle Prozesse, bei denen die alte Somefile geöffnet war und die jetzt nur einen Dateideskriptor verwenden, um darauf zu verweisen, sind nicht betroffen, da sie auf eine andere Datei verweisen - eine, die sich jetzt in der Schwebe befindet.
Wenn ein Nicht-Root-Prozess versucht, auf eine Datei mit Namen zu verweisen, wird ein EPERM-Fehler angezeigt, da sich die neue Somefile im Root-Besitz befindet.
Wenn Sie verhindern möchten, dass mehrere Prozesse unter demselben Benutzer (z. B. root) eine Datei beschädigen, verfügt Linux über eine obligatorische und empfohlene Dateisperrung. Sie können den
flock
Befehl in Shell-Skripten zum Sperren von Hinweisdateien verwenden (weitere Informationen finden Sie in der Manpage).quelle