Necesito implementar un proceso automatizado (a través de un script cron de 1 min) que busca archivos tar en un directorio específico. Si se encuentra un archivo tar, no está marcado en la ubicación adecuada y luego se elimina el archivo tar.
Los archivos tar se copian automáticamente a este servidor a través de SSH desde otro servidor. En algunos casos, los archivos tar son extremadamente grandes, con muchos archivos.
El problema con el que espero encontrarme: si el archivo tar tarda más de 1 minuto en copiarse en el servidor y el script cron se ejecuta una vez cada minuto, verá el archivo .tar.gz e intentará hacerlo descomprimirlo, a pesar de que el archivo tar todavía está en proceso de ser escrito.
¿Hay alguna forma (a través de comandos bash) de probar si un archivo se está escribiendo actualmente, o si es solo un archivo parcial, etc.?
Una alternativa en la que estaba pensando era copiar el archivo como una extensión de archivo diferente (como .tar.gz.part
) y luego cambiarle el nombre una .tar.gz
vez completada la transferencia. Pero pensé que intentaría averiguar si simplemente hay una manera de determinar si el archivo está completo en la línea de comando primero ... ¿Alguna pista?
rsync
usa un nombre de archivo temporal durante la transferencia (por defecto), y solo después de que el archivo se haya transferido por completo, cambia el nombre al nombre de archivo real.Respuestas:
Está en el camino correcto, renombrar el archivo es una operación atómica, por lo que realizar el cambio de nombre después de la carga es simple, elegante y no propenso a errores. Otro enfoque que se me ocurre es utilizar
lsof | grep filename.tar.gz
para verificar si otro proceso está accediendo al archivo.fuente
lsof filename.tar.gz
es más eficiente y más preciso quelsof | grep filename.tar.gz
)Su mejor opción es usar
lsof
para determinar si un archivo ha sido abierto por algún proceso:No se puede saber fácilmente si se está escribiendo, pero si se está escribiendo, DEBE estar abierto.
Editar: ¡resolvamos el problema real aquí en lugar de intentar implementar la solución propuesta!
Use rsync para transferir el archivo:
De esta manera, el archivo no se copiará sobre el archivo existente, sino que se copiará en un archivo temporal (
.big.tar.gz.XXXXXX
) hasta que se complete la transferencia, luego se moverá a su lugar.fuente
Un poco viejo, pero la mayoría de las respuestas pierde por completo el punto de la pregunta:
En general, no lo hay. Simplemente no tiene suficiente información para determinar eso.
Porque determinar que el archivo está cerrado no es lo mismo que determinar si el archivo está completo . Por ejemplo, un archivo se "cerrará" si la conexión se pierde durante la transferencia.
Solo la respuesta de @ Alex acertó. E incluso él se enamoró de usar
lsof
algo.Para determinar si el archivo se ha realizado completamente, la transferencia exitosa requiere más datos. Como:
Esa es una forma perfecta de comunicar que el archivo se ha transferido completa y exitosamente. También puede mover archivos de un directorio a otro siempre que permanezca dentro del mismo sistema de archivos. O haga que el remitente envíe un
filename.done
archivo vacío para indicar la finalización.Pero todos los métodos tienen que depender de que el remitente indique de alguna manera que la transferencia se ha completado con éxito. Porque solo el remitente tiene esa información.
Algunos formatos de archivo (como PDF) tienen datos que le permiten determinar si el archivo está completo. Pero tienes que abrir y leer casi todo el archivo para descubrirlo.
lsof
solo le dirá que el archivo ya no está abierto; no le dirá por qué ya no está abierto. Tampoco le dirá qué tan grande se supone que debe ser el archivo.fuente
La mejor manera de hacer esto es usar incron ("sistema cron inotify"). Le permite configurar un reloj inotify en un directorio que luego le notificará de las operaciones de archivo. En este caso, debe mirar el directorio para un close_write. Eso le permitirá ejecutar su comando una vez que el archivo se cerró después de una escritura.
fuente
Parece que lsof puede detectar en qué modo está abierto un archivo:
¿Ves donde dice 1w? Eso significa que el número de descriptor de archivo es 1 y el modo es w o write.
fuente
FD
campo se muestra3r
para mí cuando el archivo está abierto para lectura.El uso
inotifywait
puede lograr lo que busca: tiene la capacidad de esperar hasta que finalice la escritura de un archivo antes de ejecutar un comando.Lo siguiente observará continuamente una carpeta en busca de nuevos archivos y ejecutará el comando en el bucle cuando haya finalizado la escritura en el archivo.
Para obtener más opciones de configuración, consulte https://linux.die.net/man/1/inotifywatch
fuente