Хіба `rm -rf` не атомний?


11

Щойно я виявив заплутану помилку:

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

що було викликано наступною командою:

rm -rf $cache_dir/*

де $cache_dirвизначено якxxx/app/cache

Тож я бачу це так: rmвидалив усе в cache/proddir, потім прямо перед тим, як спробувати видалити cache/prodкаталог - інша програма створила файл / каталог всередині нього, таким чином, це спричинило rmзбій.

Чи правильне моє припущення?


7
Ваше припущення правильне - rm -rне атомне. Якщо ви хочете бути впевнені, що більше файлів не створюється в каталозі під час rm -rfзапуску, ви можете перейменувати його спочатку, а потім видалити перейменований каталог.
Джонні

@Johnny: Так, саме це я вже реалізував :-)
zerkms

Хоча навіть це не зовсім безпечно. Якщо додаток наразі працює з цього каталогу, він просто перейде та продовжить працювати нормально.
Патрік

Це не має нічого спільного з rm -rfтим, щоб бути безпечним для потоків: якщо ви запускаєте його кілька разів одночасно в одному каталозі, каталог видаляється. Йдеться про rm -rне атомне.
Жил "ТАК - перестань бути злим"

@Gilles: це залежить: "Частина коду є безпечною для потоків, якщо вона лише маніпулює спільними структурами даних таким чином, що гарантує безпечне виконання кількома потоками одночасно". Отже, якщо ми вважаємо "потік" як rmвиклик, ми можемо говорити про безпеку потоку. Але все одно, це нічого не змінює
zerkms

Відповіді:


7

Повідомлення про помилку було "Каталог не порожній" ( ENOTEMPTY), враховуючи це, ваше припущення звучить правильним, що це умова гонки, коли програма створила файл у цьому каталозі безпосередньо перед тим, як rmспробувати видалити каталог, надаючи очікувану ENOTEMPTYпомилку з основної бази rmdir(2).

ПРИМІТКА. Щоб бути на безпечній стороні, ви можете перенести / перейменувати каталог на нове ім’я, а потім виконати видалення цього каталогу.


2
Ця відповідь неправильна, ви можете видалити записи каталогів, навіть коли файл використовується, а потім видалити каталог. Простий тест mkdir x; cat > x/a &; tail -f x/a &; rm -r xпоказує, що каталог можна видалити, навіть коли файли використовуються, незалежно від того, відкриті вони для читання чи запису.
крила підводного човна

1
Так, файли все ще існують, але це не має нічого спільного з тим, чому видалення каталогу не вдалося. Це твердження у вашій відповіді конкретно хибне: "Система не видалить каталог, який містить у ньому файли, відкриті в режимі читання / запису". У вашій відповіді є кілька хороших речей, вона просто не стосується питання :)
wingedsubmariner

1
Також будьте обережні, щоб не плутати дескриптори файлів з файлами. Дескриптори файлів ніколи не видаляються, а лише закриваються.
wingedsubmariner

1
Ваш перший абзац також може потребувати певної роботи. Ви маєте рацію щодо того, що видалення файлу не відбувається, коли файли все ще відкриті, це лише те, що після від’єднання файлу від цього каталогу вони не перешкоджають видаленню каталогу. Так, це означає, що UNIX дозволяє існувати файлам, які відсутні в жодному каталозі, як це дивно, як це здається спочатку.
wingedsubmariner

1
Я дійсно можу подумати лише про дві причини, чому видалення не вдалося, або інтуїція ОП була правильною, і створено новий файл, або це помилка дозволу. rmскаржиться на помилки дозволу, тому я думаю, що ми можемо це усунути. Я недостатньо впевнений, щоб опублікувати відповідь.
крила підводного човна
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.