O `rm -rf` não é atômico?


11

Acabei de pegar um erro confuso:

rm: cannot remove `xxx/app/cache/prod': Directory not empty

que foi causado pelo seguinte comando:

rm -rf $cache_dir/*

onde $cache_diré definido comoxxx/app/cache

Então, eu vejo como: rmremoveu tudo no cache/proddiretório e logo antes de tentar remover o cache/proddiretório - outro programa criou um arquivo / diretório dentro dele, causando rmfalha.

Minha suposição está correta?


7
Sua suposição está correta - rm -rnão é atômica. Se quiser ter certeza de que não há mais arquivos criados no diretório enquanto este rm -rfestiver em execução, renomeie-o primeiro e remova o diretório renomeado.
— 22413 Johnny

@Johnny: Sim, isso é o que eu realmente já implementadas :-)
— zerkms

Embora nem isso seja completamente seguro. Se um aplicativo estiver operando atualmente fora desse diretório, ele seguirá com a mudança e continuará funcionando normalmente.
— 22413 Patrick

Isso não tem nada a ver com a rm -rfsegurança de threads: se você executá-lo várias vezes simultaneamente no mesmo diretório, o diretório será excluído. Trata-se de rm -rnão ser atômico.
— Gilles 'SO- stop be evil' (

@ Gilles: depende: "Um pedaço de código é seguro para threads se apenas manipular estruturas de dados compartilhadas de uma maneira que garanta a execução segura de vários threads ao mesmo tempo". Portanto, se assumirmos "thread" como uma rminvocação, poderemos falar sobre segurança de threads. Mas de qualquer maneira, isso não muda nada
— zerkms

Respostas:


7

A mensagem de erro fornecida foi "Diretório não vazio" ( ENOTEMPTY), considerando que sua suposição parece correta, que é uma condição de corrida em que um programa criou um arquivo nesse diretório antes de rmtentar remover o diretório, fornecendo o ENOTEMPTYerro esperado do subjacente rmdir(2).

NOTA: Para estar seguro, você pode mover / renomear o diretório para um novo nome e, em seguida, executar sua exclusão deste diretório.


2
Esta resposta está errada, você pode remover as entradas do diretório, mesmo quando um arquivo estiver em uso, e excluir o diretório. Um teste simples mkdir x; cat > x/a &; tail -f x/a &; rm -r xmostra que um diretório pode ser removido mesmo quando os arquivos estão em uso, independentemente de estarem abertos para leitura ou gravação.
— wingedsubmariner

1
Sim, os arquivos ainda existem, mas isso não tem nada a ver com o motivo de a exclusão do diretório não ter êxito. Esta afirmação em sua resposta especificamente é falsa: "O sistema não excluirá um diretório que possui arquivos que estão abertos no modo de leitura / gravação". Há algumas coisas boas na sua resposta, ele simplesmente não dizem respeito à questão :)
— wingedsubmariner

1
Além disso, tome cuidado para não confundir descritores de arquivos com arquivos. Os descritores de arquivo nunca são excluídos, apenas fechados.
— wingedsubmariner

1
Seu primeiro parágrafo pode precisar de algum trabalho também. Você está certo sobre a exclusão do arquivo não ocorrer quando os arquivos ainda estão abertos, é que, uma vez que o arquivo foi desvinculado desse diretório, eles não impedem que o diretório seja excluído. Sim, isso significa que o UNIX permite a existência de arquivos que não estão em nenhum diretório, por mais estranho que pareça a princípio.
— wingedsubmariner

1
Eu realmente só consigo pensar em duas razões pelas quais a exclusão falharia: a intuição do OP estava correta e um novo arquivo foi criado, ou é um erro de permissão. rmreclama de erros de permissão, então acho que podemos eliminar isso. Não estou confiante o suficiente para postar uma resposta.
— wingedsubmariner
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.