Bash-Skript - cp-Befehl verzögern, bis das Schreiben der Datei abgeschlossen ist

cp /Folder1/*.mov /Folder2/
cp /Folder1/*.mov /Folder3
rm /Folder1/*.mov

Dies wird alle 60 Sekunden mit Chron ausgeführt, das eine beliebige *.mov-Datei von einem Ordner in 2 andere Ordner kopiert und dann die Datei entfernt.

Wenn das Schreiben der Datei länger als 60 Sekunden dauert, wird das Skript ausgeführt und alles im Ordner kopiert und beschädigt. (Oder wenn das Skript gerade ausgeführt wird, wenn eine Datei geschrieben wird.)

Wie kann ich eine bedingte Anweisung machen, damit das Skript wartet, bis das Schreiben der Datei abgeschlossen ist?

Vielleicht stattdessen Ordneraktionen verwenden? Zum Beispiel: simplehelp.net/2007/01/30/… Sie können sie mit Automator.app erstellen
Kopieren Sie die Dateien in dasselbe Dateisystem?
Ich würde rsync statt cp (oder sogar nur mv) verwenden
Dies ist Teil eines Systems, das wir verwenden, um externen Kunden zu ermöglichen, Vorschau-Renderings von Projekten anzuzeigen. Die Idee ist, dass wir eine *.mov-Datei in diesem Ordner ablegen und sie in einen anderen Ordner kopieren, den Adobe Media Encoder überwacht, und dann automatisch eine kleinere Datei codiert und diese Datei dann in einen Dropbox-Ordner kopiert, damit Clients eine Vorschau anzeigen können.
Gleiches Dateisystem, ich habe versucht, Automator zu verwenden, aber ohne viel Glück ...
Die beste Option, die ich bisher gesehen habe, ist die Verwendung von LSOF. Aber mein Code-foo ist schwach und ich weiß nicht, wie ich diese Befehle mit LSOF in eine bedingte Schleife setzen soll.
Eine letzte Frage: Ist das Dateisystem HFS+?
Dies ist auf einem XSAN-Fibre-Channel-System. Ich bin mir nicht sicher, ob das die Frage richtig beantwortet ... Ich glaube nicht, dass XSAN HFS verwendet. Mein Wissen ist begrenzt.
Warum nicht mv verwenden - data wird nur der Zeiger auf die Datei kopiert und läuft daher in weniger als 60 Sekunden
Ich würde den folgenden Algorithmus vorschlagen, um Ihre Anforderung besser zu verstehen. Machen Sie einen Schnappschuss der .mov-Dateien, die in Ordner1 verfügbar sind, und verschieben Sie sie in einen temporären Ordner (Hinweis: Verwenden Sie find). Dateien werden dann aus dem temporären Ordner in ihre jeweiligen Ordner kopiert, und die Verknüpfung des temporären Ordners und seiner Dateien wird dann aufgehoben. Dies sollte jede Kollision verhindern, wenn cron (beachten Sie die Schreibweise) eine andere Instanz Ihres Cron-Skripts startet.
Danke fd0, das hört sich gut an und würde wahrscheinlich mein Problem lösen. Ich denke, mein Problem ist, dass ich nicht wirklich weiß, wie ich das implementieren soll. Die Idee, die ich hatte, war, lsof zu verwenden, um eine solche bedingte Schleife zu erstellen? Wenn ein Prozess eine Datei im X-Ordner verwendet, geben Sie "10 Sekunden warten ..." aus, warten Sie 10 Sekunden, sonst führen Sie cp cp rm aus

Antworten (1)

Datei sperren

Erwägen Sie, eine Sperre zu erstellen, um die laufende Kopie zu notieren, siehe Ihr Skript sperren (gegen parallele Ausführung) :

#!/bin/sh

# Path to a lock folder
LOCK_PATH="/tmp/copying.lock"

# Ensure the lock is removed should the copy fail
trap 'rmdir "/tmp/copying.lock"; exit' 1 6 15

if mkdir "$LOCK_PATH"; then
    # Lock file did not exist and was created

    # Perform commands
    cp /Folder1/*.mov /Folder2/
    cp /Folder1/*.mov /Folder3
    rm /Folder1/*.mov   

    # Remove the lock
    rmdir "$LOCK_PATH"
fi

Das obige Skript kopiert nur, wenn kein Ordner unter existiert /tmp/copying.lock.

Kopieren und verschieben

Anstatt direkt an den endgültigen Speicherort zu kopieren, sollten Sie die Kopie an einem temporären Speicherort erstellen. Verschieben Sie dann die Dateien. Eine Bewegung ist schnell, tendenziell atomar und beschädigt die Dateien weniger wahrscheinlich.

Alternativ können Sie mit einem Tool kopieren, rsyncdas Flags zum Schutz vor diesen Problemen enthält.

Ihrem Skript fehlt ein Trap oder das Skript könnte blockiert werden, wenn es nicht normal beendet wird. Etwas wietrap 'rmdir /tmp/copy.lock; exit' 1 6 15
Danke @fd0. Bitte zögern Sie nicht, die Zeile zu bearbeiten und hinzuzufügen.
Ich werde das mal ausprobieren und in Kürze berichten. Danke Graham, fd0 und anderen, die geholfen haben! Hier geht!
Hey Leute, ich habe es ausprobiert, aber vielleicht mache ich etwas falsch. Es läuft nicht so, wie ich es habe, es sei denn, ich erstelle manuell den Ordner /tmp/ im Verzeichnis.
Auch der Ordner /copying.lock wird nicht gelöscht, vielleicht zeige ich falsch auf die Variable?
Ah ok, die Trap-Zeile wurde aktualisiert, um 'rmdir "$LOCK_PATH" zu trappen; exit' 1 6 15 und das hat es teilweise behoben, aber aus irgendeinem Grund funktioniert rm -f "$LOCK_PATH" nicht ...
Versuchen Sie zunächst, die trapLinie vollständig zu entfernen. Es ist nur bei Problemen da. Das Finale rm -fist für das Entfernen des Ordners zuständig – nach dem erfolgreichen Kopieren.
Um das Debuggen zu erleichtern, erstellen Sie eine Textdatei, die Ihr vollständiges Skript enthält, und fügen Sie das Suffix hinzu .command. Doppelklicken Sie als Nächstes auf die Textdatei, um sie in Terminal.app zu starten. Sie sollten in der Lage sein, Probleme besser zu sehen. Wenn das funktioniert, können Sie es in Chron integrieren. Alternativ kann ich das mit einem Power Manager Event lösen – das ich geschrieben habe.
Sperrdatei existierte nicht und wurde erstellt, Kopieren... cp: /Volumes/PROOFS_WATCH/*.mov: Keine solche Datei oder Verzeichnis cp: /Volumes/PROOFS_WATCH/*.mov: Keine solche Datei oder Verzeichnis rm: /Volumes/ PROOFS_WATCH/*.mov: Keine solche Datei oder Verzeichnis rm: /Volumes/PROOFS_WATCH/copy.lock: ist ein Verzeichnis Logout [Vorgang abgeschlossen]
#!/bin/bash # Pfad zu einem Sperrordner LOCK_PATH="/Volumes/PROOFS_WATCH/copy.lock" # trap 'rmdir "$LOCK_PATH"; exit' 1 6 15 if mkdir "$LOCK_PATH"; then echo "Datei sperren existierte nicht und wurde erstellt, Kopieren..." # Befehle ausführen cp /Volumes/PROOFS_WATCH/*.mov /Volumes/PROOFS_WATCH/AME_Processing/ cp /Volumes/PROOFS_WATCH/*.mov /Volumes/PROOFS_TV rm /Volumes/PROOFS_WATCH/*.mov # Entferne die Sperre rm -f "$LOCK_PATH" fi
Bitte können Sie eine neue Frage beginnen. Das hilft bei der Formatierung und erregt mehr Aufmerksamkeit.
Sicher, kein Problem, ziemlich neu in Sachen Scripting und Stack-Austausch...