`Rm -rf` non è atomico?


11

Ho appena riscontrato un errore confuso:

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

che è stato causato dal seguente comando:

rm -rf $cache_dir/*

dove $cache_dirè definito comexxx/app/cache

Quindi lo vedo come: rmrimosso tutto in cache/proddir, quindi proprio prima di tentare di rimuovere la cache/proddirectory - un altro programma ha creato un file / una directory al suo interno e quindi ha causato un rmerrore.

La mia ipotesi è corretta?


7
Il tuo presupposto è corretto - rm -rnon è atomico. Se si desidera essere sicuri che non vengano creati altri file nella directory mentre rm -rfè in esecuzione, è possibile rinominarlo prima, quindi rimuovere la directory rinominata.
Johnny,

@Johnny: sì, è quello che ho già implementato :-)
zerkms

Anche se anche questo non è completamente sicuro. Se un'app sta attualmente funzionando fuori da quella directory, andrà semplicemente con lo spostamento e continuerà a funzionare normalmente.
Patrick,

Questo non ha nulla a che fare con la rm -rfsicurezza dei thread: se lo si esegue più volte contemporaneamente nella stessa directory, la directory viene eliminata. Si tratta di rm -rnon essere atomici.
Gilles 'SO- smetti di essere malvagio' il

@Gilles: dipende: "Un pezzo di codice è sicuro per i thread se manipola solo le strutture di dati condivise in un modo che garantisca l'esecuzione sicura di più thread contemporaneamente". Quindi se assumiamo "thread" come rminvocazione, potremmo parlare di thread-safety. Ma comunque, non cambia nulla
zerkms,

Risposte:


7

Il messaggio di errore fornito era "Directory non vuota" ( ENOTEMPTY), dato che il tuo presupposto sembra corretto, che si tratta di una condizione di competizione in cui un programma ha creato un file in quella directory poco prima di rmprovare a rimuovere la directory, dando l' ENOTEMPTYerrore previsto dal sottostante rmdir(2).

NOTA: per essere al sicuro, è possibile spostare / rinominare la directory con un nuovo nome, quindi eseguire la cancellazione di questa directory.


2
Questa risposta è errata, è possibile rimuovere le voci della directory anche quando un file è in uso, quindi eliminare la directory. Un semplice test mkdir x; cat > x/a &; tail -f x/a &; rm -r xmostra che una directory può essere rimossa anche quando i file sono in uso, indipendentemente dal fatto che siano aperti per la lettura o la scrittura.
wingedsubmariner

1
Sì, i file esistono ancora, ma questo non ha nulla a che fare con il motivo per cui l'eliminazione della directory non è riuscita. Questa affermazione nella tua risposta in particolare è falsa: "Il sistema non eliminerà una directory in cui sono presenti file che sono aperti in modalità lettura / scrittura". C'è qualcosa di buono nella tua risposta, semplicemente non riguarda la domanda :)
wingedsubmariner,

1
Inoltre, fare attenzione a non confondere i descrittori di file con i file. I descrittori di file non vengono mai eliminati, solo chiusi.
wingedsubmariner

1
Anche il tuo primo paragrafo potrebbe richiedere del lavoro. Hai ragione sul fatto che la cancellazione dei file non si verifichi quando i file sono ancora aperti, è solo che una volta che il file è stato scollegato da quella directory non impediscono la cancellazione della directory. Sì, questo significa che UNIX consente l'esistenza di file che non si trovano in nessuna directory, per quanto strano all'inizio possa sembrare.
wingedsubmariner

1
Posso solo pensare a due motivi per cui la cancellazione non sarebbe riuscita, l'intuizione di OP era corretta e un nuovo file è stato creato, oppure si tratta di un errore di autorizzazione. rmsi lamenta di errori di autorizzazione, quindi penso che possiamo eliminarlo. Tuttavia, non sono abbastanza sicuro di pubblicare una risposta.
wingedsubmariner
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.