1 votos

Cómo reemplazar los valores contemporáneos en un archivo.

Estoy tratando de escribir en un solo archivo.cfg" los valores de dos variables generadas por dos secuencias de comandos independiente. Las dos variables se actualizan constantemente y se guardan en el archivo".cfg". A continuación es un ejemplo de mi trabajo.

ejemplo de archivo".cfg" contenido:

a=null
b=null

ejemplo "script_a.sh" actualización "y" valor con:

#!/bin/bash
while : do
    .............
    val_a=1 
    sed -i "s/^\(a=\).*/\1$val_a/" file.cfg
    .............
done

ejemplo "script_b.sh" actualización "b" de valor con:

#!/bin/bash
while : do
    .............
    val_b=2 
    sed -i "s/^\(b=\).*/\1$val_b/" file.cfg
    .............
done

Los scripts funcionan perfectamente y los valores se actualizan. Pero si las dos secuencias de comandos se ejecutan al mismo tiempo uno de los dos valores no se actualizan.

He descubierto que la sed con la opción "-i" crea un archivo temporal que se sobrescribe con los dos operaciones simultáneas. Cómo puedo solucionar?

1voto

Xen2050 Puntos 2860

Un archivo de bloqueo que debería funcionar bien, si el archivo de bloqueo que existe algún proceso que está utilizando el archivo de destino y otros procesos tendrán que esperar.

Si tienes el lockfile-progs paquete, entonces usted podría utilizar para comprobar si existe una válida de bloqueo (en los últimos 5 minutos) con lockfile-check, y similar lockfile-create & lockfile-remove.

Tenga en cuenta que estos lockfiles no bloquear o impedir el acceso a los archivos, pero son sólo informativa, de modo que los guiones saber para no interferir el uno con el otro.

lockfile-create tiene un retraso predeterminado si un archivo de bloqueo que ya existe, se va a esperar hasta que el archivo está abierto antes de continuar. Aquí está una excepción de la que es el hombre de la página:

-r retry-count, --retry retry-count

Intentar bloquear nombre de archivo retry-un número de veces antes de darse por vencido. Cada intento será demoró un poco más largo que el anterior (en 5 segundos) hasta llegar a un máximo de el retraso de un minuto entre reintentos. Si retry-conde no se especifica, el valor predeterminado es de 9 que se rinda después de 180 segundos (3 minutos) si todos los 9 intentos de bloqueo de fallar.

He aquí un ejemplo básico que permite a varios de los comandos, mientras que el archivo.cfg está bloqueado (incluyendo una salida si lockfile-create falla), pero consulte la página man para más detalles.:

lockfile-create file.cfg  || { echo "lockfile-create failed, exiting now"; exit; }
...
sed -i ... file.cfg
...
lockfile-remove file.cfg

Si usted necesita el archivo de bloqueo que por más de 5 minutos, use lockfile-touch a "correr para siempre, tocar la cerradura una vez cada minuto hasta que mueren". He aquí un fragmento de el hombre de la página:

Locking a file during a lengthy process:

     lockfile-create /some/file
     lockfile-touch /some/file &
     # Save the PID of the lockfile-touch process
     BADGER="$!"
     do-something-important-with /some/file
     kill "${BADGER}"
     lockfile-remove /some/file

Si quería hacer algo especial mientras se espera a que el archivo de desbloqueo, se puede utilizar un bucle while como este, pero no puede ser una ventana de pocos milisegundos (0.003 s en mi time pruebas) entre la comprobación y cierre el archivo, pero luego lockfile-cree sólo tiene que esperar hasta que sea seguro continuar de todos modos

while lockfile-check file.cfg
do
  echo doing stuff waiting for lock to clear
  sleep 1
done

lockfile-create file.cfg || exit
...
sed -i ... file.cfg
...
lockfile-remove file.cfg

Y mientras tanto los scripts de uso y respeto lockfiles, sed nunca debería ser capaz de reemplazar el archivo mientras se está desbloqueado, por lo que no debería ser ningún archivo a copiar y cambiar el nombre de los conflictos.


O hay otras opciones similares como:

  • dotlockfile
  • tu propio test -a FILE & touch...
  • flock como en Kamil la respuesta está en la coreutils paquete que es bonito
  • Almacenar los valores en un programa de base de datos que puede manejar el acceso simultáneo de forma segura

0voto

Seth Puntos 672

sed el hombre de la página

-yo[SUFIJO], --en lugar de[=SUFIJO]

editar archivos en el lugar (hace copia de seguridad si la extensión suministrado). El valor predeterminado modo de operación es romper los enlaces simbólicos y rígidos. Esto puede ser cambiado con-seguir-enlaces y-copia.

-c, --copia

el uso de copiar en lugar de cambiar el nombre cuando se baraja archivos en -i modo. Mientras esto ayudará a evitar la ruptura de los enlaces (simbólico o duro), el resultado es una operación de edición no es atómica. Esto rara vez es el modo deseado; - seguir-enlaces simbólicos generalmente es suficiente, y es tanto más rápido y más seguro.

Echa un vistazo cada vez que tiene algunos alias de instalación o lo que su comando se parece exactamente. Según el hombre de la página no debería ser la creación de una copia de seguridad si usted sólo tiene que utilizar -i.

Esto no significa que ambos no puede acceder al archivo de forma simultánea y sobrescribir los cambios de los demás. El uso de un mutex o similar podría ser aconsejable en esa situación.

0voto

AFH Puntos 3747

Este es el clásico de la actualización en tiempo real problema: script_a.sh lee file.cfg, y antes de que se escribe todos los cambios, script_b.sh lee la misma información; luego, lo de secuencia de comandos escribe su primera actualización, los cambios se sobrescribirán cuando las otras publicaciones del script de actualización. No importa si las actualizaciones se realizan a través de un archivo temporal o por escritura directa.

No hay ningún nativo o semáforo de exclusión mutua manipulación dentro de bash, pero puede utilizar el file.cfg sí mediante la adición de líneas a las secuencias de comandos, por ejemplo, en script_a.sh:-

#!/bin/bash
while : do
    .............
    while ! mv file.cfg file.cfg_a 2>/dev/nul; do sleep 0.1; done
    val_a=1
    sed -i "s/^\(a=\).*/\1$val_a/" file.cfg_a
    mv file.cfg_a file.cfg
    .............
done

Los cambios a script_b.sh son similares, excepto que el archivo se cambia a file.cfg_b para la actualización.

Mediante el uso de un comando cambiar nombre, el script comprueba la disponibilidad del archivo para la actualización y obtiene un acceso único en un único sistema de proceso.

Yo nunca como bucles rápidos, pero sin compilar código que soporta funciones para manejar los semáforos y los mutexes, esta es la mejor que se puede hacer fácilmente.

Tenga en cuenta que algunas versiones de sleep no admiten fracciones de los retrasos, en cuyo caso usted tendrá que retrasar para el mínimo de un segundo antes de volver a intentarlo, a menos que se utilice una utilidad diferente.

0voto

Kamil Maciorowski Puntos 897

Esta otra respuesta explota la idea de lockfile. Hay otra utilidad: flock(1). Desde su manual:

flock [options] file|directory command [arguments]
flock [options] file|directory -c command
[...]

Esta es una utilidad que maneja flock(2) bloqueos dentro de los scripts de shell o desde la línea de comandos.

La primera y la segunda de las anteriores formas de envolver el bloqueo en la ejecución de un comando, en una manera similar a su(1) o newgrp(1). Bloquear un determinado archivo o directorio, el cual es creado (suponiendo que los permisos adecuados) si no existe ya. De forma predeterminada, si el bloqueo no puede ser inmediatamente adquirida, flock espera hasta que el bloqueo está disponible.

Y debido a que utiliza flock(2) llamada al sistema, creo que el kernel garantiza que no hay dos procesos pueden mantenga un bloqueo para el mismo archivo:

LOCK_EX Lugar un bloqueo exclusivo. Sólo un proceso puede contener un bloqueo exclusivo para un archivo determinado en un momento dado.

En las secuencias de comandos, en lugar de sed … de ejecución flock some_lockfile sed …, por ejemplo,

flock some_lockfile sed -i "s/^\(a=\).*/\1$val_a/" file.cfg

Y eso es todo, el bloqueo se libera cuando sed salidas. Las únicas desventajas son:

  • some_lockfile ya puede estar en uso como un archivo de bloqueo; la forma segura es el uso de mktemp a crear un archivo temporal y el uso de ella;
  • al final usted necesita para eliminar some_lockfile (supongo que no quieres dejarlo como de basura); pero si nada más utiliza el archivo (probablemente no como un archivo de bloqueo), puede que no desee eliminar; de nuevo, mktemp es el camino a seguir: crear un archivo temporal, uso, quitar, a pesar de lo que otros procesos.

¿Por qué no flock file.cfg sed … ? Sería bloquear el archivo exacto que se opera; esta no dejar basura en todo. ¿Por qué no?

Bueno, porque es imperfecto. Para entenderlo vamos a ver lo que (GNU) sed -i exactamente:

-i[SUFFIX]
--in-place[=SUFFIX]

Esta opción especifica que los archivos van a ser editadas en el lugar. GNU sed hace esto mediante la creación de un archivo temporal y enviar la salida a este archivo en lugar de a la salida estándar.

[...]

Cuando el final del archivo, el archivo temporal se cambia el nombre para el archivo de salida nombre original. La extensión, si se proporciona, se utiliza para modificar el nombre del archivo antiguo antes de cambiar el nombre del archivo temporal, y por tanto hacer una copia de seguridad.

He probado que flock cerraduras de inodo en lugar de nombre (ruta de acceso). Esto significa que tan sólo después de la sed -i cambia el nombre del archivo temporal el nombre original (file.cfg en su caso), el bloqueo ya no se aplica al nombre original.

Ahora considere el siguiente escenario:

  1. El primer flock file.cfg sed -i … file.cfg bloquea el archivo original y trabaja con él.
  2. Antes de la primera sed acabados, otra flock file.cfg sed -i … file.cfg surge. Esta nueva flock objetivos de la original file.cfg y se espera para el primer bloqueo se libera.
  3. El primer sed mueve su archivo temporal con el nombre original y se sale. El primer bloqueo se libera.
  4. El segundo flock genera el segundo sed que ahora se abre el nuevo file.cfg. Este archivo no es el archivo original (debido a los diferentes inode). Pero el segundo flock dirigida y bloqueado el archivo original, no el de la segunda sed acaba de abrir!
  5. Antes de la segunda sed acabados, otra flock file.cfg sed -i … file.cfg surge. Esta nueva flock comprueba el actual file.cfg y encuentra que no está bloqueado; bloquea el archivo y genera sed. La tercera sed comienza a leer el actual file.cfg.
  6. Ahora hay dos sed -i procesos de lectura desde el mismo archivo en paralelo. Lo que termina primero, pierde – el otro le sobrescribir los resultados, finalmente, moviendo su copia independiente con el nombre original.

Es por eso que usted necesita some_lockfile con un sólido número de inodo.

EnMiMaquinaFunciona.com

EnMiMaquinaFunciona es una comunidad de administradores de sistemas en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros sysadmin, hacer tus propias preguntas o resolver las de los demás.

Powered by: