Frage

Eine modifizierte Version eines Shell-Skript eine Audiodatei aus FLAC konvertiert zu MP3-Format. Der Computer verfügt über einen Quad-Core-CPU. Das Skript wird ausgeführt mit:

./flac2mp3.sh $(find flac -type f)

Diese wandelt die FLAC-Dateien im Verzeichnis flac (keine Leerzeichen in Dateinamen) zu MP3-Dateien im Verzeichnis mp3 (auf dem gleichen Niveau wie flac). Wenn das Ziel MP3-Datei bereits vorhanden ist, überspringt das Skript die Datei.

Das Problem ist, dass manchmal zwei Instanzen der Skripts Prüfung für die Existenz der gleichen MP3-Datei auf fast zur gleichen Zeit, was zu einer verstümmelten MP3-Dateien.

Wie würden Sie das Skript mehrere Male ausgeführt (das heißt, einmal pro Kern), ohne eine andere Datei auf jeder Befehlszeile gesetzt angeben zu müssen, und ohne Arbeit zu überschreiben?

Update - Minimal Race-Bedingung

Das Skript verwendet den folgenden Verriegelungsmechanismus:

  # Convert FLAC to MP3 using tags from flac file.
  #
  if [ ! -e $FLAC.lock ]; then
    touch $FLAC.lock
    flac -dc "$FLAC" | lame${lame_opts} \
      --tt "$TITLE" \
      --tn "$TRACKNUMBER" \
      --tg "$GENRE" \
      --ty "$DATE" \
      --ta "$ARTIST" \
      --tl "$ALBUM" \
      --add-id3v2 \
      - "$MP3"
    rm $FLAC.lock
  fi;

Dies läßt jedoch noch eine Race-Bedingung.

War es hilfreich?

Lösung

Der „Lock-Datei“ Befehl bietet, was Sie versuchen für Shell-Skripte ohne die Race-Bedingung zu tun. Der Befehl wurde speziell für diese Art von Zweck von den procmail Leuten geschrieben und ist auf den meisten BSD / Linux-Systeme verfügbar (wie procmail für die meisten Umgebungen verfügbar ist).

Ihr Test wird so etwas wie folgt aus:

lockfile -r 3 $FLAC.lock
if test $? -eq 0 ; then
  flac -dc "$FLAC" | lame${lame_opts} \
    --tt "$TITLE" \
    --tn "$TRACKNUMBER" \
    --tg "$GENRE" \
    --ty "$DATE" \
    --ta "$ARTIST" \
    --tl "$ALBUM" \
    --add-id3v2 \
    - "$MP3"
fi
rm -f $FLAC.lock

Alternativ können Sie lockfile erneuten Versuch machen auf unbestimmte Zeit, so dass Sie nicht den Return-Code testen müssen und stattdessen kann für die Ausgabedatei Test zur Bestimmung, ob flac ausgeführt werden.

Andere Tipps

Wenn Sie nicht lockfile haben und es nicht installieren können (in allen seinen Varianten - es gibt mehrere Implementierungen) eine robuste und tragbare Atom Mutex mkdir ist

.

Wenn das Verzeichnis, das Sie bereits erstellen versuchen, existiert, mkdir wird fehlschlagen, so dass Sie für das überprüfen kann; wenn Erstellung erfolgreich ist, haben Sie eine Garantie, dass kein anderer kooperierenden Prozess zur gleichen Zeit wie der Code in dem kritischen Abschnitt ist.

if mkdir "$FLAC.lockdir"; then
    # you now have the exclusive lock
    : critical section
    : code goes here
    rmdir "$FLAC.lockdir"
else
    : nothing? to skip this file
    # or maybe sleep 1 and loop back and try again
fi

Für die Vollständigkeit, vielleicht auch einen Blick für flock, wenn Sie auf einer Reihe von Plattformen, wo die verlässlich zur Verfügung gestellt werden und brauchen eine performante Alternative zu lockfile.

Sie können Sperren von FLAC-Dateien implementieren, die es funktioniert auf. So etwas wie:

if (not flac locked)
  lock flac
  do work
else
  continue to next flac

Senden Ausgabe in eine temporäre Datei mit einem eindeutigen Namen, benennen Sie die Datei auf den gewünschten Namen ein.

flac -dc "$FLAC" | lame${lame_opts} \
      --tt "$TITLE" \
      --tn "$TRACKNUMBER" \
      --tg "$GENRE" \
      --ty "$DATE" \
      --ta "$ARTIST" \
      --tl "$ALBUM" \
      --add-id3v2 \
      - "$MP3.$$"
mv "$MP3.$$" "$MP3"

Wenn eine Race-Bedingung Lecks durch Ihre Datei in einem während jeder einmal Schließanlage wird der endgültige Ausgang noch das Ergebnis eines Prozesses sein.

Um eine Datei Prozess sperren Sie eine Datei mit dem gleichen Namen mit einer .lock Erweiterung erstellen können.

Vor dem Start die Codierung die Existenz der .lock Datei überprüfen und gegebenenfalls sicherstellen, dass das Datum der lockfile ist nicht zu alt (falls der Prozess stirbt). Wenn es nicht vorhanden ist, erstellen Sie es, bevor die Codierung beginnt, und entfernen Sie es, nachdem die Codierung abgeschlossen ist.

Sie können auch die Datei scharen, aber dies funktioniert nur wirklich in c, wo man Herd anrufen () und Schreiben in die Datei dann und Entriegelung schließen. Für einen Shell-Skript, rufen Sie wahrscheinlich ein anderes Programm, um das Schreiben der Datei zu tun.

Wie wäre es ein Makefile zu schreiben?

ALL_FLAC=$(wildcard *.flac)
ALL_MP3=$(patsubst %.flac, %.mp3, $(ALL_FLAC)
all: $(ALL_MP3)
%.mp3: %.flac
        $(FLAC) ...

Dann tun

$ make -j4 all

In der bash ist es möglich, noclobber Option zu setzen Datei überschrieben zu vermeiden.

Hilfe-Set | egrep 'noclobber | C'

Verwenden Sie ein Tool wie FLOM (Free Lock Manager) und einfach Ihren Befehl serialisiert wie folgt:

flom -- flac ....
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top