Error `ls` cuando se elimina el directorio

13

Tengo dos conchas abiertas. El primero está en el directorio A. En el segundo, elimino el directorio A y luego lo vuelvo a crear. Cuando vuelvo al primer shell y escribo ls, la salida es:

ls: cannot open directory .: Stale file handle

¿Por qué? Pensé que el primer shell (el que permanecía abierto dentro de un directorio inexistente) se "congelaría" mientras esperaba el siguiente comando, y no se habría "dado cuenta" de que el directorio fue eliminado y recreado. ¿El shell contiene una referencia "más profunda" a su directorio de trabajo actual que no sea la cadena $PWD?

fonini
fuente
2
Una no respuesta, pero si simplemente desea que su caparazón caiga sobre sus pies, puede correr cd $PWD.
dhag
Me gustaría entender qué está pasando, sé que es fácil recuperar el shell :)
fonini
¿Está este directorio en un servidor NFS? Creo que esa es la única situación en la que obtienes identificadores de archivos obsoletos.
Barmar
El directorio es local. Cuando haces esto en tu sistema, ¿el resultado es diferente?
fonini

Respuestas:

17

Un directorio (como cualquier archivo) no está definido por su nombre. Pensar en el nombre como el del directorio de direcciones . Cuando mueve el directorio, sigue siendo el mismo directorio, al igual que si se muda a una casa diferente, sigue siendo la misma persona. Si elimina un directorio y crea uno nuevo con el mismo nombre, es un directorio nuevo, al igual que alguien que se muda a la casa donde solía vivir, ¿no es usted?

Cada proceso tiene un directorio de trabajo . El cdcomando en el shell cambia el directorio de trabajo actual del shell. El pwdcomando imprime la ruta to al directorio de trabajo actual.

Cuando eliminó el directorio A, lo que hizo fue eliminar la entrada de A en su directorio principal. El directorio A permaneció en el sistema de archivos, pero en un estado separado, sin nombre. Todavía no se eliminó porque estaba en uso por un proceso, es decir, el primer shell. Cuando cambió el directorio en el primer shell, el directorio finalmente se eliminó. Lo mismo sucede cuando se elimina un archivo mientras un proceso todavía lo tiene abierto: la entrada del directorio del archivo se elimina inmediatamente y el archivo en sí se elimina cuando deja de estar en uso.

Del mismo modo, observe lo que sucede cuando mueve los directorios.

mkdir one two
touch one/1 two/2
cd one
ls

En otro caparazón:

mv one tmp
mv two one
mv tmp two

En el primer caparazón:

ls

El archivo 1está en el directorio que originalmente se llamó oney ahora se llama two. El archivo 2está en el directorio que originalmente se llamó twoy ahora se llama one.

¹ Más precisamente, una ruta, que puede no ser única si están involucrados enlaces simbólicos u otras sutilezas.

Gilles 'SO- deja de ser malvado'
fuente
Entonces, ¿el punto clave aquí es que un proceso contiene el inodo de su directorio de trabajo, no solo la ruta?
Nacht - Restablece a Monica
1
@Nacht El proceso contiene un descriptor, pero el núcleo hace todo el mapeo (descriptor / entradas de tablas de archivo / inodo). Y de hecho, internamente, el núcleo no almacena rutas (porque lo interesante está en el inodo, no en la ruta). Además, una "ruta" es simplemente un enlace a un archivo ... puede haber varios :)
John WH Smith
oh cierto, tiene un descriptor. entonces bash mantiene constantemente un archivo fd del directorio de trabajo? seguramente no todos los procesos tienen fds del directorio de trabajo ... pensé que recordaba fds comenzando en el valor 3 después de stdin / out / err
Nacht - Reinstate Monica
2
@Nacht El directorio actual no es un descriptor de archivo, pero funciona muy parecido a uno. El núcleo mantiene eso para cada proceso. En Linux, puedes verlo /proc/<pid>/cwd, que funciona como /proc/<pid>/fd/<number>. Está CWDen la salida de lsof.
Gilles 'SO- deja de ser malvado'
Es posible hacer automático cd - && cd -en tal caso?
Vitaly Zdanevich
8

El nuevo directorio A no es el mismo que el directorio A. Se puede verificar con el statcomando antes de eliminar el antiguo y después de crear uno nuevo y verá diferentes números de i-node.
Y creo que esto está relacionado con el funcionamiento del núcleo. Simplemente realiza un seguimiento del número i del directorio actual para cada proceso. Entonces, como hay diferentes números i, esto conducirá a diferentes colisiones.

taliezin
fuente
Cabe señalar que un inodo es una estructura, no un número único. Se puede identificar de forma exclusiva, pero contiene más información que su ID. Esto es lo que lo hace más importante que los enlaces.
John WH Smith
1
@JohnWHSmith Voy a eliminar esta respuesta ya que Gilles es mejor.
taliezin
66
¡Esa no es razón para borrar la tuya! Si te sientes así, puedes agregar un descargo de responsabilidad a tu respuesta explicando que consideras que la otra es mejor.
terdon
7

Este es el comportamiento esperado. El nuevo directorio A no es el mismo que el antiguo directorio A, simplemente tiene el mismo nombre. Entonces, el $ PWD de la primera terminal aún no está, no apareció mágicamente cuando lo hizo mkdir A.

John
fuente
2
¿Podría elaborar en 'nuevo directorio A no es lo mismo que el antiguo directorio A'. ¿Qué aspectos del archivo / directorio cambian? ¿Tiene que ver con el número de inodo? Lamento preguntar, pero estoy aprendiendo sobre esto.
rahul
2
@rahul Filosóficamente, lo que cambia es su identidad : se ha creado un nuevo directorio a partir de la nada en la misma ubicación. A nivel de implementación, sí, todos los archivos abiertos se identifican por inodo, y los directorios antiguos y nuevos tendrán inodos distintos con diferentes números de inodo.
Hobbs
0

Un directorio, como un archivo, tiene un inodo asociado:

307% mkdir ABC

308% ls -i 11997708 A 11997709 B 11997710 C

Un inodo es una estructura de datos que contiene información sobre el directorio o archivo. Cada directorio y archivo tiene uno. Piense en ello como una dirección (un número de índice realmente).

Si estoy en A, número de inodo 11997708 y en otro shell (o en el mismo shell que voy a hacer) borre el directorio A y luego vuelva a crearlo y ls el inodo:

309% cd A

310% rmdir ../A

311% mkdir ../A

312% ls -i ..

11997720 A 11997709 B 11997710 C

El nodo i es diferente, por lo que si intenta crear un archivo en el directorio eliminado A:

313% toca esto

touch: no se puede tocar 'this': no ​​existe tal archivo o directorio

porque el directorio en el que estoy - ya no está asociado con el inodo 11997720 - por lo que actualmente ya no tengo una dirección / índice legítimo - inodo. De ahí el error.

usuario2592248
fuente