¿`Rm -rf` no es atómico?

11

Acabo de detectar un error confuso:

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

que fue causado por el siguiente comando:

rm -rf $cache_dir/*

donde $cache_dirse define comoxxx/app/cache

Entonces lo veo así: rmeliminé todo en el cache/proddirectorio, luego justo antes de intentar eliminar el cache/proddirectorio; otro programa creó un archivo / un directorio dentro de él, por lo que causó un rmerror.

¿Es correcta mi suposición?

zerkms
fuente
77
Su suposición es correcta, rm -rno es atómica. Si desea asegurarse de que no se creen más archivos en el directorio mientras se rm -rfestá ejecutando, puede cambiarle el nombre primero y luego eliminar el directorio renombrado.
Johnny
@Johnny: sí, eso es lo que ya implementé :-)
zerkms
Aunque incluso eso no es completamente seguro. Si una aplicación actualmente está operando fuera de ese directorio, simplemente irá con el movimiento y seguirá funcionando normalmente.
Patrick
Esto no tiene nada que ver con rm -rfser seguro para subprocesos: si lo ejecuta varias veces al mismo tiempo en el mismo directorio, el directorio se eliminará. Esto se trata de rm -rno ser atómico.
Gilles 'SO- deja de ser malvado'
@Gilles: depende: "Un fragmento de código es seguro para subprocesos si solo manipula estructuras de datos compartidas de una manera que garantice la ejecución segura de múltiples subprocesos al mismo tiempo". Entonces, si asumimos "thread" como una rminvocación, podemos hablar sobre seguridad de thread. Pero de todos modos, no cambia nada
zerkms

Respuestas:

7

El mensaje de error dado fue "Directorio no vacío" ( ENOTEMPTY), dado que su suposición suena correcta, que es una condición de carrera donde un programa creó un archivo en ese directorio justo antes de rmintentar eliminar el directorio, dando el ENOTEMPTYerror esperado del subyacente rmdir(2).

NOTA: para estar seguro, puede mover / cambiar el nombre del directorio a un nuevo nombre y luego ejecutar la eliminación de este directorio.

slm
fuente
2
Esta respuesta es incorrecta, puede eliminar las entradas del directorio incluso cuando un archivo está en uso y luego eliminar el directorio. Una prueba simple de mkdir x; cat > x/a &; tail -f x/a &; rm -r xmuestra que un directorio puede eliminarse incluso cuando los archivos están en uso, independientemente de si están abiertos para leer o escribir.
wingedsubmariner
1
Sí, los archivos aún existen, pero esto no tiene nada que ver con por qué la eliminación del directorio no tuvo éxito. Esta afirmación en su respuesta específicamente es falsa: "El sistema no eliminará un directorio que tiene archivos que residen en él que se abren en modo lectura / escritura". Hay algunas cosas buenas en su respuesta, simplemente no corresponde a la pregunta :)
wingedsubmariner
1
Además, tenga cuidado de no confundir los descriptores de archivo con los archivos. Los descriptores de archivos nunca se eliminan, solo se cierran.
wingedsubmariner
1
Su primer párrafo podría necesitar algo de trabajo también. Tiene razón acerca de que la eliminación del archivo no ocurre cuando los archivos aún están abiertos, es solo que una vez que el archivo se ha desvinculado de ese directorio, no impiden que se elimine el directorio. Sí, esto significa que UNIX permite que existan archivos que no están en ningún directorio, por extraño que parezca al principio.
wingedsubmariner
1
Realmente solo puedo pensar en dos razones por las cuales la eliminación podría fallar, o la intuición de OP era correcta y se creó un nuevo archivo, o es un error de permiso. rmse queja de errores de permisos, por lo que creo que podemos eliminar eso. Sin embargo, no tengo la confianza suficiente para publicar una respuesta.
wingedsubmariner