2016-10-16 3 views
0

ich eine Klartextdatei als eine Task-Warteschlange für meine Anwendung verwenden möchten (für in einer Datenbank zu schreiben, obwohl das irrelevant ist), wobei gilt:atomar Entfernen der ersten Zeile einer Datei und Zurückkehren es

  1. ich hinzufügen ein Element in der Warteschlange über echo "some task" >> task_queue.txt
  2. ich einen Artikel aus der Warteschlange

atomar entfernen Für 2. ich weiß nicht, einen Weg Rennbedingungen zu vermeiden, wenn ich Zugriff auf/task_queue.txt in mehreren Threads oder Prozesse zu modifizieren . Das Folgende ist nicht atomar:

ITEM=`head -1 task_queue.txt` 
sed -i '1d' task_queue.txt 
# process the item in the application 

Bietet Bash eine elegantere Möglichkeit, dies zu tun, als mit einer Sperrdatei? Ich habe noch nie zuvor flock verwendet, also weiß ich nicht, ob das unordentlich ist (z. B. wenn die Verarbeitung der Task meiner Anwendung fehlschlägt).

Antwort

0

Obwohl ich es Atom nicht bestätigen kann, ist dies viel mehr Atome als alles, was ich selbst schreiben kann (wahrscheinlich) und ist gut genug für mein nicht-unternehmenskritische App:

sed -i -e '1 w /dev/stdout' -e '1d' task_queue.txt 

(Credits: https://unix.stackexchange.com/a/108479/7000)

1

Alle diese leiden unter der Race Condition, zwischen dem Überprüfen, ob auf die Datei zugegriffen wird, und der Operation für die Datei. Obwohl vermutlich die Zeit zwischen Überprüfung und Betrieb sehr gering wäre.


Eine Möglichkeit könnte sein, pgrep mit der -f Option zu verwenden volle Befehlszeile übereinstimmen, und passen Sie, wenn die Datei heißt angepasst ist, wenn jeder Prozess die Datei zugreifen. Dies setzt voraus, dass der Prozess seine Befehlszeile nicht ändert.

if ! lsof /path/to/task_queue.txt &>/dev/null; then 
    ## File not Open, do stuff 
else 
    ## File is Open, do stuff 
fi 

Ähnlich fuser:

if ! fuser /path/to/task_queue.txt &>/dev/null; then 
    ## File not Open, do stuff 
else 
    ## File is Open, do stuff 
fi 

Hinweis

kann dies tun: (dies ist das gleiche wie das Parsen /proc/PID/fd/*)

if ! pgrep -f task_queue.txt &>/dev/null; then 
    ## File not Open, do stuff 
else 
    ## File is Open, do stuff 
fi 

Ein anderer Ansatz lsof oder fuser würde das Parsen das, hier senden wir Sowohl STDOUT als auch STDERR von lsof/fuser bis /dev/null ist dies möglicherweise nicht immer wünschenswert, da es möglicherweise eine Warnung/einen Fehler gibt. Da wir nur vom Exit-Status abhängig sind, werden alle diese Dateien missbraucht, wenn die Datei verwendet wird. Dies wäre einfacher zu implementieren, wenn lsof/fuser verschiedene Exit-Status für verschiedene Ereignisse hat, aber alles, was ich sehen kann, ist 1 für jede Art von Fehler oder keine Übereinstimmung.

+0

Interessanter Ansatz, und ich wusste nicht über 'pgrep -f'. Ich frage mich, ob das besser ist als die Verwendung von Flock. Ich denke, ich muss beide Optionen gleichzeitig verfolgen und sehen, bei wem ich mich sicherer fühle. –

+0

Hmmmm, ist es eigentlich nicht möglich, dass das "Zeug" im "if" -Körper den Dateideskriptor nicht die ganze Zeit festhält? 2 Befehle können einen kleinen Zeitraum haben, zwischen dem die Datei nicht geöffnet ist, was einem anderen Prozess erlauben könnte, sie zu stehlen. –

+1

@ Sridhar-Sarnobat Es gibt offensichtlich eine Möglichkeit der Rassenkondition zwischen 'pgrep' und Operation in der Datei, was auch immer klein sein mag.Wenn Sie Präzision wünschen, sollten Sie sich den Verriegelungsmechanismus z.B. 'Herde'. – heemayl

Verwandte Themen