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).