2016-07-04 17 views
2

In einer Linux-Shell möchte ich einen Ordner wie eine Tüte mit Dateien behandeln. Es gibt einige Prozesse, die Dateien in diese Tasche legen. Es gibt genau einen Prozess, der in entweder einer der beiden folgenden Zustände:bash - Wählen Sie Dateien aus dem Ordner, Prozess, löschen

  1. Prozess ein Dokument, dann
  2. Wait Löschen für ein beliebiges Dokument in dem Ordner existieren, dann verarbeiten

Es spielt keine Rolle, in welcher Reihenfolge die Dokumente verarbeitet werden oder wie sie heißen.

Was würde der einzigartige Prozess, Dateien aus dem Ordner zu nehmen, in bash aussehen? Verarbeitung bedeutet, ein anderes Programm mit dem Dateinamen als Argument aufzurufen.

Beachten Sie, dass dieser eindeutige Prozess erst manuell beendet wird.

+0

Ich kann nur über eine Lösung denken, eine externe Datei zu haben, die den Status speichert, andernfalls wenn Sie 2 Prozesse laufen haben In demselben Ordner verarbeiten Sie die gleiche Datei entweder zweimal oder entfernen sie während der Verarbeitung mit dem anderen Thread. – Yaron

+0

Nein, es gibt nur einen Prozess, der Dateien herausnimmt. Es gibt mehrere Putting-Dateien, aber nur ein Prozess wird aus dem Ordner entfernt. –

Antwort

0

Wie wäre es damit:

while true; do 
    files=($(ls)); 
    if [[ ${#files[@]} -eq 0 || (`lsof -c write_process -- ${files[0]}`)]]; then 
     sleep 5; 
    else 
     process ${files[0]}; 
     rm ${files[0]}; 
    fi; 
done 

... oder diese (möglicherweise ungesund sein):

while true; do 
    files=($(ls)); 
    if [ ${#files[@]} -ne 0 && ! (`lsof -c write_process -- ${files[0]}`)]; then 
     process ${files[0]}; 
     rm ${files[0]}; 
    fi; 
done 

Wo, wie wurde darauf hingewiesen, ich habe, um sicherzustellen, dass die Datei vollständig in den Ordner geschrieben. Ich tue dies, indem ich lsof nach dem Prozess suche, der Dateien schreibt. aber ich bin mir noch nicht sicher, wie mehrere Ausführungen desselben Programms als ein Prozess zu adressieren sind ...

+0

Dies funktioniert. Stellen Sie nur sicher, dass nicht immer/oft die erste Datei in alphabetischer Reihenfolge hinzugefügt wird (andernfalls ist $ {files [0]} immer/oft offen, solange die write_processes funktionieren). –

0

Der einfachste Weg, um nur Schleife über die Dateien sein könnte „ruft“ das Verarbeitungsprogramm und entfernen Sie die Dateien:

for f in /path/to/folder/*; do 
    program_that_processes_file $f 
    rm $f 
done 

Es gibt ein kleines Problem mit diesem aber: Wenn das Programm, das die Dateien erstellt macht es nicht atomar, Sie könnten Dateien verarbeiten und vielleicht sogar entfernen, die noch nicht vollständig geschrieben sind. Die einfachste Lösung besteht darin, den Writer in ein temporäres Verzeichnis schreiben zu lassen, und wenn die Datei fertig ist, verschieben Sie sie in das endgültige Zielverzeichnis.

+0

Wird dies nicht beendet, sobald keine Datei mehr existiert? Was bedeutet das Schließen der For-Schleife? –

+1

@RadioControlled Dann haben Sie die Schleife in einer anderen Schleife. Oder verwenden Sie möglicherweise ein Cron-Skript, das dies alle paar Sekunden aufruft. Oder verwenden Sie ein Verzeichnisüberwachungsprogramm (es gibt einige davon), das dieses Skript aufruft, sobald Dateien im Verzeichnis vorhanden sind. –

+0

oh ich habe gerade festgestellt, dass 'od' schließt 'do' ... Ich habe immer 'done' verwendet –

1

inotify-tools wäre das ideale Werkzeug, um sofortige Benachrichtigungen für Änderungen im Verzeichnis zu erhalten. Sobald Sie eine Benachrichtigung über die Erstellung der neuen Datei erhalten, können Sie sie verarbeiten und löschen.

+0

Dies wird kompliziert, weil mehrere Dateien erstellt werden können, während ich einen verarbeite. Also müsste ich einen Stapel von zusätzlichen Dateien erstellen. Dies ist natürlich möglich, aber ich dachte, dass es eine einfachere Lösung geben könnte, da die Reihenfolge der Dateien im Ordner keine Rolle spielt. –

+0

Lesen Sie dieses https://techarena51.com/index.php/inotify-tools-example/. Sie haben Beispiele gegeben, wie Sie ein Skript erstellen und an inotifywait übergeben können (in Ihrem Fall das Ereignis create). – Fazlin

+1

'inotify' erstellt Benachrichtigungen für jede Dateierstellung innerhalb eines Verzeichnisses und für jede empfangene Benachrichtigung können Sie die gewünschte Verarbeitung vornehmen. Soweit ich weiß, ist dies die sauberste Lösung. Wäre glücklich, sich natürlich als falsch erwiesen zu haben !! – Fazlin

2

Sie können incrond verwenden, was für "inotify cron daemon" steht. Es ist ein Daemon, der im Hintergrund ausgeführt wird und Verzeichnisse überwacht, die in einer Tabelle angegeben sind. Eine gültige Konfiguration kann mit

incrontab -e 
erstellt werden

Dies wird mit einem Editor öffnen und Sie können das Verzeichnis und Aktionen, die Sie möchten, geben Sie sehen, zum Beispiel

/path/to/observed/directory IN_CREATE,IN_MOVED_TO <command> [email protected]/$# 

<command> ist der Befehl oder das Skript die Sie ausführen möchten, wenn eines der Ereignisse (IN_CREATE,IN_MOVED_TO) ausgelöst wird. [email protected]/$# ist der Pfad zu der Datei, die erstellt oder in den überwachten Ordner verschoben wurde und an <command> übergeben wird. Das ist im Grunde alles, was Sie tun müssen, um den Ordner anzuschauen.

Sie müssen incrond einmal initialisieren, indem Sie ihm mitteilen, welche Benutzer den Dienst nutzen dürfen. Sie können Benutzern erlauben, indem Sie sie zu incrond.allow verwenden incrond, zum Beispiel

echo 'root' >> /etc/incrond.allow 
echo '<username>' >> /etc/incrond.allow 

Hinweis, dass root muss auch in incrond.allow sein. Jetzt können Sie den Daemon starten, indem Sie einfach

incrond 

Weitere Informationen über incrond Aufruf: