Question

Une version modifiée d'un script shell convertit un fichier audio de FLAC format MP3. L'ordinateur a un processeur quad-core. Le script est exécuté en utilisant:

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

Il convertit les fichiers FLAC dans le répertoire flac (sans espaces dans les noms de fichiers) aux fichiers MP3 dans le répertoire mp3 (au même niveau que flac). Si le fichier MP3 de destination existe déjà, le script saute le fichier.

Le problème est que parfois deux instances du contrôle de script pour l'existence du même fichier MP3 à peu près en même temps, ce qui dans les fichiers MP3. Déchiquetés

Comment exécuter le script plusieurs fois (à savoir, une fois par cœur), sans avoir à spécifier un fichier différent sur chaque commande mis en ligne, et sans travail écraser?

Mise à jour - Race Condition minimale

Le script utilise le mécanisme de verrouillage suivant:

  # 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;

Cependant, cela laisse encore une condition de course.

Était-ce utile?

La solution

La commande « lockfile » fournit ce que vous essayez de faire pour les scripts shell sans condition de course. La commande a été écrit par les gens procmail spécifiquement pour ce genre de but et est disponible sur la plupart des systèmes BSD / Linux (comme procmail est disponible pour la plupart des environnements).

Votre test devient quelque chose comme ceci:

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

Vous pouvez faire lockfile garder indéfiniment afin que vous réessayant n'avez pas besoin de tester le code de retour, et peut tester à la place du fichier de sortie pour déterminer si vous souhaitez exécuter flac.

Autres conseils

Si vous n'avez pas lockfile et ne peut pas l'installer (dans l'une de ses versions - il y a plusieurs implémentations) un mutex atomique robuste et portable est mkdir

.

Si le répertoire que vous essayez de créer existe déjà, mkdir échouera, de sorte que vous pouvez vérifier cela; lorsque la création réussit, vous avez une garantie qu'aucun autre processus de coopération est dans la section critique en même temps que votre code.

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

Pour être complet, peut-être aussi pour regarder flock si vous êtes sur un ensemble de plates-formes où qui est fiable et mis à la disposition besoin une alternative à lockfile performante.

Vous pouvez implémenter le verrouillage des fichiers FLAC qu'il fonctionne sur. Quelque chose comme:

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

Envoyer la sortie à un fichier temporaire avec un nom unique, puis renommez le fichier au nom de votre choix.

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

En cas de fuite de l'état de la course à travers votre système de verrouillage des fichiers chaque fois dans un certain temps, la sortie finale sera toujours le résultat d'un processus.

Pour verrouiller un processus de fichier que vous pouvez créer un fichier avec le même nom avec une extension .lock.

Avant de commencer l'encodage vérifier l'existence du fichier .lock, et éventuellement assurez-vous que la date du lockfile est pas trop vieux (dans le cas où le processus meurt). Si elle n'existe pas, créez avant l'encodage commence, et le retirer après l'encodage est terminé.

Vous pouvez également affluer le fichier, mais cela ne fonctionne vraiment dans c où vous appelez flock () et de l'écriture dans le fichier puis la fermeture et le déverrouillage. , Vous êtes probablement pour un script shell d'appeler un autre utilitaire pour faire de l'écriture du fichier.

Que diriez-vous d'écrire un Makefile?

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

Ensuite, faites

$ make -j4 all

Dans bash, il est possible de définir noclobber option pour éviter de fichiers écrasement.

help set | egrep 'noclobber | C'

Utilisez un outil comme FLOM (Free Verrouillez Manager) et simplement sérialiser votre commande comme ci-dessous:

flom -- flac ....
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top