Pregunta

modificado una versión de un href="http://www.sklav.com/?q=node/4" rel="nofollow secuencia de comandos shell convierte un archivo de audio de FLAC a formato MP3. El equipo tiene una CPU de cuatro núcleos. La secuencia de comandos se ejecuta utilizando:

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

Esto convierte los archivos FLAC en el directorio flac (sin espacios en los nombres de archivos) para archivos MP3 en el directorio mp3 (al mismo nivel que flac). Si el archivo de destino ya existe MP3, el guión se salta el archivo.

El problema es que a veces, dos instancias del cheque guión de la existencia del mismo archivo MP3 casi al mismo tiempo, lo que resulta en archivos MP3 destrozados.

¿Cómo se ejecuta el script varias veces (es decir, una vez por núcleo), sin tener que especificar un archivo diferente en cada conjunto de línea de comandos, y sin sobrescribir el trabajo?

Actualizar - Carrera mínima del Estado

El script utiliza el siguiente mecanismo de bloqueo:

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

Sin embargo, esto todavía deja una condición de carrera.

¿Fue útil?

Solución

El comando "fichero de bloqueo" responde a lo que estamos tratando de hacer por los scripts de shell sin la condición de carrera. El comando fue escrito por la gente procmail específicamente para este tipo de propósito y está disponible en la mayoría de los sistemas BSD / Linux (como procmail está disponible para la mayoría de los entornos).

Su prueba se convierte en algo parecido a esto:

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

Como alternativa, puede hacer que el archivo de bloqueo de volver a intentar mantener de forma indefinida por lo que no es necesario para poner a prueba el código de retorno, y en su lugar se pueden probar para el archivo de salida para determinar si se debe ejecutar FLAC.

Otros consejos

Si usted no tiene lockfile y no puede instalarlo (en cualquiera de sus versiones - hay varias implementaciones) un mutex atómica robusta y portátil es mkdir

.

Si el directorio que intenta crear ya existe, se producirá un error mkdir, para que pueda comprobar para eso; cuando la creación tiene éxito, usted tiene la garantía de que ningún otro proceso cooperando está en la sección crítica, al mismo tiempo que su código.

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

Para completar, quizá también buscan flock si usted está en un juego de plataformas en las que se ponen a disposición de forma fiable y necesita una alternativa a performant lockfile.

Se puede aplicar de bloqueo de archivos FLAC que se está trabajando. Algo así como:

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

enviar la salida a un archivo temporal con un nombre único, a continuación, cambiar el nombre del archivo al nombre deseado.

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

Si una condición de fugas a través de su archivo de sistema de bloqueo de vez en cuando, el resultado final todavía será el resultado de un proceso.

Para bloquear un proceso de archivo que puede crear un archivo con el mismo nombre con una extensión .lock.

Antes de iniciar la codificación comprueba la existencia del archivo .lock, y, opcionalmente, asegúrese de que la fecha del fichero de bloqueo no es demasiado viejo (en caso de que el proceso muere). Si no existe, cree que antes de que comience la codificación, y quitarlo después de la codificación es completa.

También puede acuden el archivo, pero esto sólo funciona en C donde realiza la llamada flock () y escribir en el archivo a continuación, cierre y desbloqueo. Para un script de shell, es probable que está llamando otra utilidad para hacer la escritura del archivo.

¿Cómo escribir un Makefile?

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

A continuación, realice

$ make -j4 all

En bash Es posible establecer noclobber opción para evitar la sobreescritura de archivos.

help set | 'Noclobber | -C' egrep

Utilice una herramienta como FLOM (Lock Manager gratuito) y simplemente serializar su comando de la siguiente manera:

flom -- flac ....
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top