Como mover e recriar uma pasta ao mesmo tempo?

9

Eu tenho uma pasta chamada statisticsem um servidor Ubuntu na qual os arquivos de dados são armazenados regularmente. Como posso renomear a statisticspasta para backup-xxrecriar a statisticspasta para estar disponível para armazenar novos arquivos?

Os arquivos na statisticspasta são criados pelo PHP file_put_contents.

Eu prefiro renomear a pasta, pois há muitos arquivos na statisticspasta.

Googlebot
fonte
No começo, pensei que você quisesse dizer "ao mesmo tempo" que a operação deveria ser "atômica" (na medida do possível).
Php
@phk Sim, é exatamente o que eu quis dizer.
Googlebot
A terminologia correta seria "diretório" e não "pasta", a propósito.
Berk Özbalcı

Respostas:

7
mv statistics backup-xx && mkdir statistics

Isso renomeia o statisticsdiretório existente para backup-xxe, se for bem-sucedido, continuará criando um novo statisticsdiretório.

Para uma operação mais atômica, considere criar um diretório statistics-001(ou similar, talvez substituindo pela 001data de hoje em um formato adequado) e um link simbólico para ele chamado statistics:

mkdir statistics-001
ln -s statistics-001 statistics

Quando você deseja "girar" isso para que novos dados entrem em um diretório limpo, crie o diretório primeiro e depois recrie o statisticslink para ele:

mkdir statistics-002
ln -sf statistics-002 statistics

mv statistics-001 backup-001

Desta forma, qualquer programa escrito para o statisticsdiretório (ou seja, o diretório que este link simbólico aponta para) nunca 1 não conseguem encontrá-lo.

Se você precisar de permissões especiais ou de propriedade definidas no diretório que statisticsaponta para, defina-as antes de (re) criar o link.

1 Ou melhor, dessa forma, o tempo que um programa ficaria sem um diretório de destino válido é minimizado o máximo possível na prática, usando as ferramentas padrão do Unix.

Kusalananda
fonte
1
Você também pode querer chown --reference=backup-xx statistics ; chmod --reference=backup-xx statisticsdefinir propriedades e permissões. Idealmente, você faria isso antes de renomear, para um mkdir new ; chown ; chmod ; mv stats backup ; mv new statsprocesso de tipo.
Stephen Harris
@StephenHarris Sim, em sistemas que possuem esses sinalizadores.
Kusalananda
Isso não é atômico, no entanto. É quase atômico, mas não exatamente.
um CVn
@ MichaelKjörling Corrigido.
Kusalananda
ln -sfnão é atômico. É especificado para desvincular o link simbólico antigo e criar um novo, que é necessariamente não atômico. Em vez disso, você deve criar um vínculo simbólico temporário adicional e usar a renamefunção (via mvcomando, por exemplo) para substituir atomicamente o antigo. Veja minha abordagem aqui: git.musl-libc.org/cgit/musl/tree/tools/…
R .. GitHub PARE DE AJUDAR O GELO
12

Não há como substituir atomicamente um diretório por outro diretório. Você pode mover o diretório antigo e criar um novo diretório:

mv statistics backup-xx
mkdir statistics

Mas isso deixa uma pequena janela de tempo durante a qual statisticsnão existe. Este é um problema se algum processo puder soltar arquivos no diretório a qualquer momento.

Para efetivamente substituir atomicamente um diretório, você precisa usar links simbólicos. Crie um diretório cujo nome inclua o período desde o início:

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

(ou no entanto você deseja escolher a convenção de nomenclatura de diretório). Crie um link simbólico com um nome fixo para o local atual:

ln -s  statistics

Para substituir o diretório, primeiro crie um novo diretório e um novo link simbólico e mova-o para substituir o link simbólico antigo. Observe que nem uma planície mvno link simbólico nem uma planície ln -sfarão isso: elas criariam uma entrada dentro do diretório de destino. O coreutils do GNU ln -snftambém não é adequado porque remove o link simbólico existente antes de criar um novo, o que deixa uma pequena janela de tempo durante a qual o caminho não existe. Você pode usar os GNU coreutils mv -Tno novo link simbólico.

new_dir="statistics-$(date +%Y%m%d)"
mkdir "$new_dir"
ln -s statistics.new
mv -Tf statistics.new statistics
Gilles 'SO- parar de ser mau'
fonte
busybox' ln -sftambém não é atômico, não conheço nenhuma implementação que seja.
Php
1
Ao lado dos comentários, os links simbólicos do phk também não são 100% seguros, porque um processo em execução ainda pode ter um descritor de arquivo de diretório aberto (destino de link simbólico) e pode criar mais novos arquivos no diretório renomeado (pense em openat()ou CWD). Gostaria apenas de mover o conteúdo do diretório para um novo. Isso ainda é inseguro em relação aos arquivos abertos, mas um pouco melhor. Em dúvida, use o logrotateque deve respeitar da melhor maneira possível essas questões.
Rudimeier
1
@phk A symlinkchamada do sistema não substituirá um arquivo existente, por isso é impossível trocar diretamente um link simbólico atomicamente, infelizmente. A renamechamada do sistema substituirá um arquivo existente, mas irritantemente não há uma maneira portátil de fazer isso no shell; é possível com o GNU coreutils graças à -Topção
Gilles 'SO- stop be evil'
3

Não renomeie o diretório. Você disse que prefere renomear o diretório porque ele possui muitos arquivos. A única razão pela qual consigo pensar que você deseja isso é porque a cópia dos arquivos levaria muito tempo. No entanto, mover (ou seja, renomear) os arquivos é instantâneo, desde que sejam movidos para um local no mesmo sistema de arquivos. Suponho que é isso que você deseja fazer, pois, se você estiver alterando os sistemas de arquivos, mvlevará tanto tempo quanto a cpmovimentação de um diretório ou seu conteúdo.

Então, faça:

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

Se você também precisar obter arquivos ocultos, poderá:

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

Ou, se estiver usando bash:

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

Dessa forma, o diretório está sempre lá, mas você ainda move seu conteúdo em uma operação simples e rápida.

terdon
fonte
1

Você pode mover o conteúdo da pasta de estatísticas para um diretório recém-criado, em vez de mover a própria pasta. Se você mover uma pasta inteira, precisará executar outro comando para alterar as permissões do diretório.

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