¿Cómo mover y recrear una carpeta al mismo tiempo?

9

Tengo una carpeta llamada statisticsen un servidor Ubuntu en el que los archivos de datos se almacenan regularmente. ¿Cómo puedo cambiar el nombre de la statisticscarpeta backup-xxmientras vuelvo a crear la statisticscarpeta para que esté disponible para almacenar nuevos archivos?

Los archivos en la statisticscarpeta son creados por PHP file_put_contents.

Prefiero cambiar el nombre de la carpeta, ya que hay muchos archivos en la statisticscarpeta.

Googlebot
fuente
Al principio pensé que querías decir "al mismo tiempo" que la operación debería ser "atómica" (en la medida de lo posible).
phk
@phk Sí, es exactamente lo que quise decir.
Googlebot
La terminología correcta sería "directorio" y no "carpeta" por cierto.
Berk Özbalcı

Respuestas:

7
mv statistics backup-xx && mkdir statistics

Esto cambiaría el nombre del statisticsdirectorio existente a backup-xx, y si eso tiene éxito, continuaría para crear un nuevo statisticsdirectorio.

Para una operación más atómica, considere crear un directorio statistics-001(o similar, tal vez reemplazándolo 001con la fecha de hoy en un formato adecuado), y un enlace simbólico llamado statistics:

mkdir statistics-001
ln -s statistics-001 statistics

Cuando desee "rotar" esto para que los datos nuevos entren en un directorio limpio, primero cree el directorio y luego vuelva a crear el statisticsenlace:

mkdir statistics-002
ln -sf statistics-002 statistics

mv statistics-001 backup-001

De esta manera, cualquier programa de escritura para el statisticsdirectorio (es decir, el directorio que este vínculo simbólico puntos a) nunca 1 que encontrarlo.

Si necesita permisos especiales o propiedad establecida en el directorio al que statisticsapunta, configúrelos antes de (re) crear el enlace.

1 O más bien, de esta manera, el tiempo que un programa estaría sin un directorio de destino válido se minimiza tanto como sea prácticamente posible utilizando herramientas estándar de Unix.

Kusalananda
fuente
1
También es posible que desee chown --reference=backup-xx statistics ; chmod --reference=backup-xx statisticsestablecer una propiedad y permisos. Idealmente, haría esto antes de cambiar el nombre, por lo que es un mkdir new ; chown ; chmod ; mv stats backup ; mv new statsproceso de tipo
Stephen Harris
@StephenHarris Sí, en sistemas que tienen esas banderas.
Kusalananda
Sin embargo, esto no es atómico. Está cerca de atómico, pero no del todo.
un CVn
@ MichaelKjörling lo arregló.
Kusalananda
ln -sfNo es atómico. Se especifica para desvincular el antiguo enlace simbólico y luego crear uno nuevo, que necesariamente no es atómico. En su lugar, debe hacer un enlace simbólico temporal adicional y utilizar la renamefunción (a través del mvcomando, por ejemplo) para reemplazar atómicamente el antiguo. Vea mi enfoque aquí: git.musl-libc.org/cgit/musl/tree/tools/…
R .. GitHub
12

No hay forma de reemplazar atómicamente un directorio por otro directorio. Puede mover el directorio anterior y luego crear un nuevo directorio:

mv statistics backup-xx
mkdir statistics

Pero esto deja una pequeña ventana de tiempo durante la cual statisticsno existe. Este es un problema si algún proceso puede soltar archivos en el directorio en cualquier momento.

Para reemplazar de manera atómica un directorio, debe usar enlaces simbólicos. Cree un directorio cuyo nombre incluya el período de tiempo desde el inicio:

mkdir "statistics-$(date +%Y%m%d)"

(o como quiera elegir la convención de nomenclatura de directorios). Cree un enlace simbólico con un nombre fijo a la ubicación actual:

ln -s  statistics

Para reemplazar el directorio, primero cree un nuevo directorio y un nuevo enlace simbólico, y luego muévalo para sobrescribir el viejo enlace simbólico. Tenga en cuenta que ni un plano mven el enlace simbólico ni un plano ln -sharán esto: crearían una entrada dentro del directorio de destino. GNU coreutils ln -snftampoco es adecuado porque elimina el enlace simbólico existente antes de crear uno nuevo, lo que deja una pequeña ventana de tiempo durante la cual la ruta no existe. Puede usar GNU coreutils mv -Ten el nuevo enlace simbólico.

new_dir="statistics-$(date +%Y%m%d)"
mkdir "$new_dir"
ln -s statistics.new
mv -Tf statistics.new statistics
Gilles 'SO- deja de ser malvado'
fuente
busybox' ln -sftampoco es atómico, no sé de ninguna implementación que sea.
phk
1
Además de los enlaces simbólicos de comentarios de phk, tampoco son 100% seguros porque un proceso en ejecución aún puede tener un descriptor de archivo de directorio abierto (destino de enlace simbólico) y podría crear más archivos nuevos en el directorio renombrado (piense openat()o CWD). Solo movería el contenido del directorio a uno nuevo. Eso todavía no es seguro con respecto a los archivos abiertos, pero es un poco mejor. En caso de duda, utilice lo logrotateque debería respetar tales problemas lo mejor posible.
rudimeier
1
@phk La symlinkllamada al sistema no sobrescribirá un archivo existente, por lo que es imposible cambiar directamente un enlace simbólico atómicamente, desafortunadamente. La renamellamada al sistema sobrescribirá un archivo existente, pero molestamente no hay una forma portátil de hacerlo en el shell; es posible con GNU coreutils gracias a la -Topción.
Gilles 'SO- deja de ser malvado'
3

No cambie el nombre del directorio en absoluto. Dijiste que prefieres renombrar el directorio porque tiene muchos archivos. La única razón por la que puedo pensar que querrías esto es porque copiar los archivos llevaría demasiado tiempo. Sin embargo, mover (es decir, renombrar) los archivos es instantáneo siempre que se muevan a una ubicación en el mismo sistema de archivos. Supongo que esto es lo que debe hacer, ya que si está cambiando los sistemas de archivos, mvtomará tanto tiempo como cpsi esté moviendo un directorio o su contenido.

Entonces, solo haz:

mkdir backup-xx && mv statistics/* backup-xx

Si también necesita obtener archivos ocultos, puede hacer:

mkdir backup-xx && mv statistics/* statistics/.* backup-xx

O, si se utiliza bash:

shopt -s dotglob; mkdir backup-xx && mv statistics/* statistics/.* backup-xx

De esta manera, el directorio siempre está ahí, pero aún puede mover su contenido en una operación simple y rápida.

terdon
fuente
1

Puede mover el contenido de la carpeta de estadísticas a un directorio recién creado en lugar de mover la carpeta en sí. Si mueve toda la carpeta, deberá ejecutar otro comando para cambiar los permisos del directorio.

mkdir -p <path>/backup-xxx
mv statistics/* <path>/backup-xxx/.
Kiran Kumar Annam
fuente