Wie kann man einen Ordner gleichzeitig verschieben und neu erstellen?

9

Ich habe einen Ordner statisticsauf einem Ubuntu-Server, in dem regelmäßig Datendateien gespeichert werden. Wie kann ich einen statisticsOrdner umbenennen , backup-xxwährend ich einen Ordner neu erstelle statistics, um neue Dateien zu speichern?

Die Dateien im statisticsOrdner werden von PHP erstellt file_put_contents.

Ich bevorzuge das Umbenennen des Ordners, da sich viele Dateien im statisticsOrdner befinden.

Googlebot
quelle
Zuerst dachte ich, Sie meinten mit "zur gleichen Zeit", dass die Operation "atomar" sein sollte (soweit es möglich ist).
Phk
@phk Ja, genau das habe ich gemeint.
Googlebot
Die richtige Terminologie wäre übrigens "Verzeichnis" und nicht "Ordner".
Berk Özbalcı

Antworten:

7
mv statistics backup-xx && mkdir statistics

Dies würde das vorhandene statisticsVerzeichnis in umbenennen backup-xx, und wenn dies erfolgreich ist, würde es fortfahren, ein neues statisticsVerzeichnis zu erstellen .

Für eine atomarere Operation sollten Sie ein Verzeichnis statistics-001(oder ein ähnliches Verzeichnis , möglicherweise durch Ersetzen durch das 001heutige Datum in einem geeigneten Format) und einen symbolischen Link mit dem Namen erstellen statistics:

mkdir statistics-001
ln -s statistics-001 statistics

Wenn Sie dies "drehen" möchten, damit neue Daten in ein sauberes Verzeichnis gelangen, erstellen Sie zuerst das Verzeichnis und erstellen Sie dann den statisticsLink dazu neu:

mkdir statistics-002
ln -sf statistics-002 statistics

mv statistics-001 backup-001

Auf diese Weise kann jedes Programm Schreiben in das statisticsVerzeichnis (dh das Verzeichnis , dass dieser symbolische Link verweist) wird nie 1 scheitern , es zu finden.

Wenn Sie spezielle Berechtigungen oder Eigentumsrechte für das Verzeichnis benötigen, auf das statisticsverwiesen wird, legen Sie diese fest, bevor Sie den Link (neu) erstellen.

1 Oder besser gesagt, auf diese Weise wird die Zeit, die ein Programm ohne ein gültiges Zielverzeichnis hätte, mit Standard-Unix-Tools so weit wie möglich minimiert.

Kusalananda
quelle
1
Möglicherweise möchten Sie auch chown --reference=backup-xx statistics ; chmod --reference=backup-xx statisticsEigentümer und Berechtigungen festlegen. Idealerweise würden Sie dies vor dem Umbenennen tun, also einen Typprozess mkdir new ; chown ; chmod ; mv stats backup ; mv new stats.
Stephen Harris
@StephenHarris Ja, auf Systemen mit diesen Flags.
Kusalananda
Dies ist jedoch nicht atomar. Es ist nah an atomar, aber nicht ganz.
Ein Lebenslauf
@ MichaelKjörling Behoben.
Kusalananda
ln -sfist nicht atomar. Es ist festgelegt, die Verknüpfung des alten Symlinks aufzuheben und dann einen neuen zu erstellen, der notwendigerweise nicht atomar ist. Stattdessen müssen Sie einen zusätzlichen temporären Symlink erstellen und die renameFunktion ( mvz. B. über den Befehl) verwenden, um die alte atomar zu ersetzen. Siehe meine Herangehensweise hier: git.musl-libc.org/cgit/musl/tree/tools/…
R .. GitHub STOP HELPING ICE
12

Es gibt keine Möglichkeit, ein Verzeichnis atomar durch ein anderes Verzeichnis zu ersetzen. Sie können das alte Verzeichnis verschieben und dann ein neues Verzeichnis erstellen:

mv statistics backup-xx
mkdir statistics

Dies lässt jedoch ein kleines Zeitfenster übrig, in dem statisticses kein existiert. Dies ist ein Problem, wenn ein Prozess jederzeit Dateien im Verzeichnis ablegen kann.

Um ein Verzeichnis effektiv atomar zu ersetzen, müssen Sie symbolische Links verwenden. Erstellen Sie ein Verzeichnis, dessen Name den Zeitraum von Anfang an enthält:

mkdir "statistics-$(date +%Y%m%d)"

(oder wie auch immer Sie die Verzeichnisnamenskonvention wählen möchten). Erstellen Sie eine symbolische Verknüpfung mit einem festen Namen zum aktuellen Speicherort:

ln -s  statistics

Um das Verzeichnis zu ersetzen, erstellen Sie zuerst ein neues Verzeichnis und einen neuen symbolischen Link und verschieben Sie es dann, um den alten symbolischen Link zu überschreiben. Beachten Sie, dass weder eine Ebene mvauf dem symbolischen Link noch eine Ebene dies ln -stun: Sie würden einen Eintrag im Zielverzeichnis erstellen. GNU coreutils ln -snfist auch nicht geeignet, da der vorhandene Symlink entfernt wird, bevor ein neuer erstellt wird. Dadurch bleibt ein kleines Zeitfenster, in dem der Pfad nicht vorhanden ist. Sie können GNU-Coreutils mv -Tfür den neuen symbolischen Link verwenden.

new_dir="statistics-$(date +%Y%m%d)"
mkdir "$new_dir"
ln -s statistics.new
mv -Tf statistics.new statistics
Gilles 'SO - hör auf böse zu sein'
quelle
busybox' ln -sfist auch nicht atomar, ich kenne keine Implementierung, die ist.
Phk
1
Neben den Kommentaren von phk sind Symlinks auch nicht 100% sicher, da ein laufender Prozess möglicherweise noch einen Open Directory-Dateideskriptor (Symlink-Ziel) hat und möglicherweise mehr neue Dateien im umbenannten Verzeichnis erstellt werden (think about openat()oder CWD). Ich würde nur den Inhalt des Verzeichnisses in ein neues verschieben. Das ist in Bezug auf geöffnete Dateien immer noch unsicher, aber ein bisschen besser. Im Zweifelsfall verwenden, logrotatewelche solche Probleme am besten respektieren sollten.
Rudimeier
1
@phk Der symlinkSystemaufruf überschreibt keine vorhandene Datei, daher ist es leider unmöglich, eine symbolische Verknüpfung atomar direkt zu wechseln. Der renameSystemaufruf überschreibt eine vorhandene Datei, aber ärgerlicherweise gibt es keine tragbare Möglichkeit, dies in der Shell zu tun. Dank der -TOption ist dies mit GNU-Coreutils möglich .
Gilles 'SO - hör auf böse zu sein'
3

Benennen Sie das Verzeichnis überhaupt nicht um. Sie sagten, dass Sie es vorziehen, das Verzeichnis umzubenennen, da es viele Dateien enthält. Der einzige Grund, warum ich mir vorstellen kann, dass Sie dies möchten, ist, dass das Kopieren der Dateien zu lange dauern würde. Das Verschieben (dh Umbenennen) der Dateien erfolgt jedoch sofort, solange sie an einen Speicherort im selben Dateisystem verschoben werden. Ich gehe davon aus, dass Sie dies tun müssen, da das Ändern von Dateisystemen mvgenauso viel Zeit in cpAnspruch nimmt, unabhängig davon, ob ein Verzeichnis oder dessen Inhalt verschoben wird.

Also einfach machen:

mkdir backup-xx && mv statistics/* backup-xx

Wenn Sie auch versteckte Dateien benötigen, können Sie Folgendes tun:

mkdir backup-xx && mv statistics/* statistics/.* backup-xx

Oder wenn Sie verwenden bash:

shopt -s dotglob; mkdir backup-xx && mv statistics/* statistics/.* backup-xx

Auf diese Weise ist das Verzeichnis immer vorhanden, aber Sie können den Inhalt dennoch einfach und schnell verschieben.

terdon
quelle
1

Sie können den Inhalt des Statistikordners in ein neu erstelltes Verzeichnis verschieben, anstatt den Ordner selbst zu verschieben. Wenn Sie den gesamten Ordner verschieben, müssen Sie einen anderen Befehl ausführen, um die Verzeichnisberechtigungen zu ändern.

mkdir -p <path>/backup-xxx
mv statistics/* <path>/backup-xxx/.
Kiran Kumar Annam
quelle