GNU/Linux >> Tutoriales Linux >  >> Linux

Mover archivo pero solo si está cerrado

Del lsof página man

Lsof devuelve uno (1) si se detectó algún error, incluido el hecho de no localizar nombres de comandos, nombres de archivos, direcciones o archivos de Internet, nombres de inicio de sesión, archivos NFS, PID, PGID o UID que se le solicitó enumerar. Si se especifica la opción -V, lsof indicará los elementos de búsqueda que no incluyó en la lista.

Eso sugeriría que su lsof failed for some other reason cláusula nunca se ejecutaría.

¿Ha intentado simplemente mover el archivo mientras su proceso externo aún lo tiene abierto? Si el directorio de destino está en el mismo sistema de archivos, entonces no debería haber problemas para hacerlo, a menos que necesite acceder a él bajo la ruta original desde un tercer proceso, ya que el inodo subyacente seguirá siendo el mismo. De lo contrario, creo que mv fallará de todos modos.

Si realmente necesita esperar hasta que su proceso externo termine con el archivo, es mejor usar un comando que bloquee en lugar de sondear repetidamente. En Linux, puede usar inotifywait para esto. Por ejemplo:

 inotifywait -e close_write /path/to/file

Si debe usar lsof (quizás por portabilidad), podría intentar algo como:

until err_str=$(lsof /path/to/file 2>&1 >/dev/null); do
  if [ -n "$err_str" ]; then
    # lsof printed an error string, file may or may not be open
    echo "lsof: $err_str" >&2

    # tricky to decide what to do here, you may want to retry a number of times,
    # but for this example just break
    break
  fi

  # lsof returned 1 but didn't print an error string, assume the file is open
  sleep 1
done

if [ -z "$err_str" ]; then
  # file has been closed, move it
  mv /path/to/file /destination/path
fi

Actualizar

Como señaló @JohnWHSmith a continuación, el diseño más seguro siempre usaría un lsof bucle como el anterior, ya que es posible que más de un proceso tenga el archivo abierto para escritura (un caso de ejemplo puede ser un demonio de indexación mal escrito que abre archivos con el indicador de lectura/escritura cuando en realidad debería ser de solo lectura). inotifywait Sin embargo, todavía se puede usar en lugar de dormir, simplemente reemplace la línea de sueño con inotifywait -e close /path/to/file .


Como enfoque alternativo, este es el caso perfecto para una tubería - el segundo proceso procesará la salida del primer proceso tan pronto como esté disponible, en lugar de esperar a que finalice el proceso completo:

process1 input_file.dat | process2 > output_file.dat

Ventajas:

  • Mucho más rápido en general:
    • No tiene que escribir ni leer desde el disco (esto se puede evitar si usa un ramdisk).
    • Debería utilizar los recursos de la máquina de forma más completa.
  • No hay lima intermedia que quitar después del acabado.
  • No es necesario un bloqueo complejo, como en OP.

Si no tiene forma de crear directamente una canalización pero tiene GNU coreutils puedes usar esto:

tail -F -n +0 input_file.dat | process2 > output_file.dat

Esto comenzará a leer el archivo de entrada desde el principio, no importa cuán lejos el primer proceso consiste en escribir el archivo (incluso si aún no se ha iniciado o ya ha finalizado).


Linux
  1. Mover archivos en la terminal de Linux

  2. ¿Cómo mover una línea en un archivo de texto hacia arriba o hacia abajo una línea?

  3. ¿Descomprimir un archivo .gz para obtener un archivo de texto pero obtener un archivo binario?

  4. ¿Cancelar la finalización, pero solo la finalización, en Zsh?

  5. ¿Mostrar solo Stderr en pantalla pero escribir tanto Stdout como Stderr en el archivo?

Cómo mover un archivo en Linux

¿Diff -r solo para ciertos tipos de archivos?

Cómo usar el comando lsof en Linux

El comando Mover archivo de Linux:¡fácil!

Comandos vi básicos (hoja de trucos)

¿Cómo crear un archivo solo si no existe?