2U1C1D3
Anmeldungsdatum: 20. Februar 2011
Beiträge: 339
|
Hallo beinand! Eine Frage zum Dateien verschieben: Ich habe für nen Verein eine Cloud aufgesetzt. Ein Ordner auf den jedes Mitglied zugreifen darf ist dafür da, dass Fotos oder Videos hochgeladen werden. Allerdings, aufgrund der gesetzlichen Datenschutzregeln, darf ich die Dateien da nicht liegen lassen bis ein Admin / Moderator mal Zeit hat sich den Dateien anzunehmen. Es wäre sonst die Möglichkeit gegeben, das andere Mitglieder die Dateien runterladen oder auch löschen. Das können wir nicht zulassen, aufgrund des zu erwartenden Inhalts der Bilder, bzw. Videos. Ich habe auf der Cloud ein Script laufen, welches im Minutentakt nachsieht ob in dem Ordner eine Datei liegt und diese, wenn eine vorhanden ist, in ein sicheres Verzeichnis verschiebt. Für das Verschieben verwende ich derzeit folgenden Befehl:
| find /LAUFWERK/Upload/* -cmin +1 -exec mv {} /LAUFWERK/sicheresVerzeichnis \;
|
Jetzt hab ich zwei Probleme:
Wird die Datei im Ordner "Upload" nach dem Verschieben nicht entfernt, also sie wird eigentlich nur kopiert, obwohl der User der das Script ausführt rwx-Berechtigungen hat und Bei größeren Dateien das Script trotz -cmin +1 noch während dem Upload der Datei ausgeführt wird.
Hab ich bei dem Befehl einen Denkfehler? Bearbeitet von rklm: Aufzählung
|
hapeck
Anmeldungsdatum: 17. Mai 2007
Beiträge: 80
|
Das lässt sich relativ einfach lösen.
Zwei Szenarien: A)
Das Zielverzeichnis liegt auf dem gleichen Laufwerk wie das Upload-Verzeichnis: Dann gibt es kein Timingproblem, weil der mv dann nichts physisch verschiebt, sondern nur den Eintrag in der Verzeichnisstruktur umhängt, also wie ein Umbenennen funktioniert. B)
Wenn das Zielverzeichnis auf einem anderen Laufwerk liegt, dann legt man neben dem Uploadverzeichnis ein Tempverzeichnis an (am besten nicht im Uploadverzeichnis) und schiebt die angekommenen Dateien zunächst dahin. Das Verschieben in das eigentliche Zielverzeichnis ist dann nicht mehr zeitkritisch, das kann man dann in einem zweiten, unabhängigen Task (Script) machen, bei dem man ein ausreichend langes Intervall wählt.
Das Script kann man dann auch absolut sicher machen, indem man es zuerst die zu verschiebenden Dateien mit einem Prefix oder Suffix umbenennt und dann diese verschiebt und dabei sicherstellt, dass dieses Script die Dateien mit dem Prefix oder Suffix nicht anpackt, wenn es gestartet wird, bevor die vorige Instanz fertig ist. HTH
|
2U1C1D3
(Themenstarter)
Anmeldungsdatum: 20. Februar 2011
Beiträge: 339
|
hapeck schrieb: A)
Das Zielverzeichnis liegt auf dem gleichen Laufwerk wie das Upload-Verzeichnis: Dann gibt es kein Timingproblem, weil der mv dann nichts physisch verschiebt, > sondern nur den Eintrag in der Verzeichnisstruktur umhängt, also wie ein Umbenennen funktioniert.
Ja, nee, eben anscheinend nicht. Sobald das Script ausgeführt wird und der Client ist noch mit dem Upload beschäftigt, kommt spätestens bei der Verifizierung der hochgeladenen Datei beim Client eine Fehlermeldung. Egal ob ich da WebDAV oder SFTP oder was auch immer benutze (bei SMB, was ich nicht möchte, gibt's keine Fehlermeldung im Client, sondern eine Fehlermeldung vom Script...)
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 12527
|
Ich würde das mit dem find etwas anders machen: | find /LAUFWERK/Upload -type f -cmin +1 -exec mv -t /LAUFWERK/sicheresVerzeichnis {} +
|
Wenn man schon find benutzt, dann braucht man das Globbing nicht. Wenn das Verschieben schon während des Uploads passiert, dann ist eventuell "-cmin +1" zu kurz. Ggf. hast Du auch das Problem, dass zwei Durchläufe des Skriptes parallel passieren. Da müsste man dann etwas mit flock bauen. z.B.: | #!/bin/sh
flock -n "$0" find /LAUFWERK/Upload -type f -cmin +1 -exec mv -t /LAUFWERK/sicheresVerzeichnis {} +
|
Noch schlauer als Pollen ist aber Pushen: | #!/bin/sh
inotifywait --monitor --recursive --event CLOSE_WRITE --format '%w%f' /LAUFWERK/Upload \
| while read -r file; do [ -f "$file" ] && mv -t /LAUFWERK/sicheresVerzeichnis "$file"; done
|
Das Event CLOSE_WRITE kommt, nachdem die Datei komplett geschrieben wurde. Dann kann man sicher sein, dass sie erst verschoben wird, wenn sie komplett geschrieben worden ist. Dieses Skript nicht regelmäßig ausführen sondern einmal.
|
2U1C1D3
(Themenstarter)
Anmeldungsdatum: 20. Februar 2011
Beiträge: 339
|
rklm schrieb: Dieses Skript nicht regelmäßig ausführen sondern einmal.
Das ist ein interessanter Ansatz. Aber woher soll das Script dann wissen, dasses jetzt benötigt wird? Wenn ich das richtig deute, dann liegt das Script in "Lauerstellung". Heißt mit anderen Worten, ich muss konsequent überwachen, dass das Script aktiv ist... Mit nem regelmäßig wiederkehrenden Job (der nicht ausgeführt wird wenn noch jemand die Finger an der Datei hat), isses doch nicht so aufwendig, oder?
|
Doc_Symbiosis
Anmeldungsdatum: 11. Oktober 2006
Beiträge: 4212
|
Schau Dir mal inotify oder incron oder auch systemd/Path Units an.
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 12527
|
2U1C1D3 schrieb: rklm schrieb: Dieses Skript nicht regelmäßig ausführen sondern einmal.
Das ist ein interessanter Ansatz. Aber woher soll das Script dann wissen, dasses jetzt benötigt wird?
Das Skript muss immer laufen. Also, beim Booten starten, beim Herunterfahren terminieren.
Wenn ich das richtig deute, dann liegt das Script in "Lauerstellung". Heißt mit anderen Worten, ich muss konsequent überwachen, dass das Script aktiv ist...
Ja, das kann Systemd sicherstellen.
Mit nem regelmäßig wiederkehrenden Job (der nicht ausgeführt wird wenn noch jemand die Finger an der Datei hat), isses doch nicht so aufwendig, oder?
Bin mir nicht sicher, dass ich verstehe, was Du meinst. Dein Skript wird ja immer (also regelmäßig, ohne weitere Bedingungen) ausgeführt, weil man halt vorher nicht weiß, ob eine Datei gerade noch geschrieben wird. Doc_Symbiosis schrieb: Schau Dir mal [...] systemd/Path Units an.
Ich habe keine Möglichkeit gefunden, wie man das genannte Szenario damit erledigen kann. Es gibt nur PathExistsGlob, um auf beliebige Dateien in einem Verzeichnis zu reagieren, aber das reagiert nicht, wenn eine Datei fertig geschrieben wurde. Andererseits gibt es PathChanged, was reagiert, wenn einen Datei geschrieben wurde, aber dafür muss man den Dateinamen kennen. Im aktuellen Beispiel sollen ja beliebige Dateien, deren Namen vorher unbekannt sind, überwacht werden (siehe Manpage). Wie sieht Deine Lösung aus?
|
Doc_Symbiosis
Anmeldungsdatum: 11. Oktober 2006
Beiträge: 4212
|
Also ich nutze auf einem Nextcloud-Server die incrontab, um Aktionen auszulösen, nachdem eine Datei vollständig hochgeladen wurde. Der Nachteil von der Incrontab ist halt, dass sie nicht rekursiv arbeitet und keine Kommentare in diese eingefügt werden dürfen. Ein Eintrag in der incrontab sieht dann z.B. so aus:
/var/data/eb1f134c-c573-1039-8ece-219645dcdac8/files/ IN_CLOSE_WRITE /opt/nextcloud/trigger_jenkins_job "$@" "$#" Also vorne steht das zu überwachende Verzeichnis, als zweites die Datei-Operation (in diesem Fall der Abschluß des Uploads), danach das auszuführende Skript, dem dann noch Parameter übergeben werden.
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 12527
|
Doc_Symbiosis schrieb: Also ich nutze auf einem Nextcloud-Server die incrontab, um Aktionen auszulösen, nachdem eine Datei vollständig hochgeladen wurde. Der Nachteil von der Incrontab ist halt, dass sie nicht rekursiv arbeitet und keine Kommentare in diese eingefügt werden dürfen. Ein Eintrag in der incrontab sieht dann z.B. so aus:
/var/data/eb1f134c-c573-1039-8ece-219645dcdac8/files/ IN_CLOSE_WRITE /opt/nextcloud/trigger_jenkins_job "$@" "$#" Also vorne steht das zu überwachende Verzeichnis, als zweites die Datei-Operation (in diesem Fall der Abschluß des Uploads), danach das auszuführende Skript, dem dann noch Parameter übergeben werden.
Aber wenn das nicht rekursiv geht, wie funktioniert das dann? CLOSE_WRITE bezieht sich dann doch nur auf das Verzeichnis. Oder erfasst das alle Dateien, innerhalb des Verzeichnisses? Ah! Wenn ich mir die Beispielsektion in der Manpage anschaue, dann ist Rekursion der Standard (5. Beispiel).
|
2U1C1D3
(Themenstarter)
Anmeldungsdatum: 20. Februar 2011
Beiträge: 339
|
Tut mir leid, hat mal wieder ein bisschen gedauert... Ich glaube, dass das von Doc_Symbiosis der Ansatz ist, den ich suche. IN_CLOSE_WRITE ist gem. der Manpage der Parameter, der das Ganze so lange ausbremst bis die Datei in Ruhe gelassen wird. Was ist aber "trigger_jenkins_job"?
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 12527
|
2U1C1D3 schrieb:
Ich glaube, dass das von Doc_Symbiosis der Ansatz ist, den ich suche. IN_CLOSE_WRITE ist gem. der Manpage der Parameter, der das Ganze so lange ausbremst bis die Datei in Ruhe gelassen wird. Was ist aber "trigger_jenkins_job"?
Ein Beispiel.
|
noisefloor
Ehemaliger
Anmeldungsdatum: 6. Juni 2006
Beiträge: 28316
|
Hallo,
Andererseits gibt es PathChanged, was reagiert, wenn einen Datei geschrieben wurde, aber dafür muss man den Dateinamen kennen.
Also laut Doku 🇬🇧 PathChanged eine Datei oder ein Verzeichnis übergeben - letzteres ist doch das, was du brauchst? Selber ausprobiert habe ich das aber auch noch nicht. Gruß, noisefloor
|
Doc_Symbiosis
Anmeldungsdatum: 11. Oktober 2006
Beiträge: 4212
|
Das /opt/nextcloud/trigger_jenkins_job ist das Skript, was aufgerufen wird, sobald der Upload abgeschlossen ist, "$@" und "$#" sind die Parameter, $@ ist der Name des Upload-verzeichnisses, $# der Name der neu hochgeladenen Datei.
|