2009-09-24 11 views
0

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

./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 ignore le fichier.

Le problème est que parfois deux instances du script vérifient l'existence du même fichier MP3 presque au même moment, ce qui entraîne des fichiers MP3 altérés.

Comment exécuter le script plusieurs fois (c'est-à-dire, une fois par cœur), sans avoir à spécifier un jeu de fichiers différent sur chaque ligne de commande et sans écraser le travail?

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, il reste encore une condition de course.

+0

Toute raison de ne pas simplement utiliser 'lockfile'? – ezpz

Répondre

4

La commande "lockfile" fournit ce que vous essayez de faire pour les scripts shell sans condition de concurrence.La commande a été écrite par les gens de 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 

Alternativement, vous pouvez faire lockfile garder réessayant indéfiniment si vous ne avez pas besoin de tester le code de retour, et peut au lieu de tester le fichier de sortie pour déterminer si courir flac.

2

Vous pouvez implémenter le verrouillage des fichiers FLAC sur lesquels il travaille. Quelque chose comme:

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

Cette réponse Yahoo semble avoir une bonne idée sur la façon de le faire lors d'un script shell. http://answers.yahoo.com/question/index?qid=20061011215658AAbuBfB –

+0

exactement comme il l'a montré. Vous devez modifier le script shell pour inclure cette logique. –

1

Pour verrouiller un processus de fichier, vous pouvez créer un fichier portant le même nom avec une extension .lock. Avant de commencer le codage, vérifiez l'existence du fichier .lock et, en option, assurez-vous que la date du fichier de verrouillage n'est pas trop ancienne (au cas où le processus meurt). S'il n'existe pas, créez-le avant le début de l'encodage et supprimez-le une fois l'encodage terminé.

Vous pouvez également ajouter le fichier, mais cela ne fonctionne vraiment que dans les cas où vous appelez flock() et écrivez dans le fichier, puis fermez et déverrouillez. Pour un script shell, vous appelez probablement un autre utilitaire pour écrire le fichier.

0

Que diriez-vous d'écrire un Makefile?

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

Puis faire

$ make -j4 all 
0

Dans bash il est possible de définir l'option noclobber pour éviter d'écraser des fichiers.

aide définir | egrep 'noclobber | -C'

1

Envoie la sortie vers un fichier temporaire avec un nom unique, puis renomme le fichier au nom souhaité.

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.

-1

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

flom -- flac .... 
+0

Vous voudrez peut-être lire ici: http://meta.stackexchange.com/questions/57497/limits-for-self-promotion-in-answers – nkjt