Errore `ls` quando la directory viene cancellata


13

Ho due conchiglie aperte. Il primo è nella directory A. Nel secondo, rimuovo la directory A e quindi la ricrea. Quando torno alla prima shell e scrivo ls, l'output è:

ls: cannot open directory .: Stale file handle

Perché? Pensavo che la prima shell (quella rimasta aperta all'interno di una directory inesistente) si sarebbe "congelata" in attesa del comando successivo e non avrebbe "capito" che la directory era stata cancellata e ricreata. La shell contiene un riferimento "più profondo" alla sua directory di lavoro corrente diversa dalla stringa $PWD?


2
Una non risposta, ma se desideri semplicemente che la tua conchiglia cada di nuovo in piedi, puoi correre cd $PWD.
Dhag,

Vorrei capire cosa sta succedendo, so che è facile riavere la shell :)
fonini

Questa directory è su un server NFS? Penso che sia l'unica situazione in cui si ottengono handle di file non aggiornati.
Barmar,

La directory è locale. Quando lo fai nel tuo sistema, il risultato è diverso?
fonini,

Risposte:


17

Una directory (come qualsiasi file) non è definita dal suo nome. Pensa al nome come all'indirizzo della directory . Quando sposti la directory, è sempre la stessa directory, proprio come se ti sposti in un'altra casa, sei sempre la stessa persona. Se rimuovi una directory e ne crei una nuova con lo stesso nome, è una nuova directory, proprio come qualcuno che si trasferisce nella casa in cui vivevi non sei tu.

Ogni processo ha una directory di lavoro . Il cdcomando nella shell cambia la directory di lavoro corrente della shell. Il pwdcomando stampa il percorso¹ alla directory di lavoro corrente.

Quando hai rimosso la directory A, ciò che ha fatto è stato rimuovere la voce per A nella sua directory padre. La directory A stessa è rimasta nel filesystem, ma in uno stato distaccato, senza nome. Non è stato ancora cancellato perché era utilizzato da un processo, vale a dire la prima shell. Quando hai cambiato la directory nella prima shell, la directory è stata finalmente cancellata. La stessa cosa accade quando un file viene eliminato mentre un processo è ancora aperto: la voce della directory del file viene rimossa immediatamente e il file stesso viene rimosso quando smette di essere in uso.

Allo stesso modo, osserva cosa succede quando sposti le directory.

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

In un'altra shell:

mv one tmp
mv two one
mv tmp two

Nella prima shell:

ls

Il file si 1trova nella directory originariamente chiamata onee ora viene chiamata two. Il file si 2trova nella directory originariamente chiamata twoe ora viene chiamata one.

¹ Più precisamente, un percorso, che potrebbe non essere unico se sono coinvolti collegamenti simbolici o altre sottigliezze.


Quindi il punto chiave qui è che un processo contiene l'inode della sua directory di lavoro, non solo il percorso?
Nacht - Ripristina Monica

1
@Nacht Il processo contiene un descrittore, ma il kernel esegue tutto il mapping (descrittore / tabelle di file voci / inode). E infatti, internamente, il kernel non memorizza i percorsi (perché le cose interessanti sono nell'inode, non nel percorso). Inoltre, un "percorso" è semplicemente un collegamento a un file ... potrebbero essercene diversi :)
John WH Smith,

oh giusto contiene un descrittore. quindi bash tiene costantemente un fd della directory di lavoro? sicuramente non tutti i processi hanno fds della directory di lavoro ... pensavo di ricordare i fds a partire dal valore 3 dopo stdin / out / err
Nacht - Reinstate Monica

2
@Nacht La directory corrente non è un descrittore di file, ma funziona in modo molto simile a uno. Il kernel lo mantiene per ogni processo. Su Linux, puoi vederlo in /proc/<pid>/cwd, che funziona come /proc/<pid>/fd/<number>. È CWDnell'output di lsof.
Gilles 'SO- smetti di essere malvagio'

è possibile rendere automatico cd - && cd -in tal caso?
Vitaly Zdanevich,

8

La nuova directory A non è la stessa della directory A. Può essere verificata con il statcomando prima di eliminare quella vecchia e dopo averne creata una nuova e vedrai numeri i-node diversi.
E penso che questo sia legato al funzionamento del kernel. Tiene semplicemente traccia dell'i-numero della directory corrente per ogni processo. Quindi, poiché esistono diversi numeri i, questo porta a diverse collisioni.


Va notato che un inode è una struttura, non un numero univoco. Può essere identificato in modo univoco, ma contiene più informazioni del suo ID. Questo è ciò che lo rende più importante dei collegamenti.
John WH Smith,

1
@JohnWHSmith ho intenzione di eliminare questa risposta poiché Gilles è migliore.
Taliezin,

6
Non è un motivo per eliminare il tuo! Se la pensi così, potresti semplicemente aggiungere un disclaimer alla tua risposta spiegando che consideri l'altro migliore.
terdon

7

Questo è un comportamento previsto. La nuova directory A non è la stessa della vecchia directory A, ma ha semplicemente lo stesso nome. Quindi il $ PWD del primo terminale è ancora sparito, non è riapparso magicamente quando lo hai fatto mkdir A.


2
potresti approfondire "la nuova directory A non è la stessa della vecchia directory A". Quali aspetti del file / directory cambiano? Ha a che fare con il numero dell'inode? Mi dispiace chiedere, ma sto solo imparando questo.
rahul,

2
@rahul Filosoficamente, ciò che cambia è la sua identità : una nuova directory è stata creata dal nulla nella stessa posizione. A livello di implementazione, sì, tutti i file aperti sono identificati da inode e le directory vecchie e nuove avranno inode distinti con numeri di inode diversi.
Hobbs,

0

Una directory, come un file, ha un inode ad essa associato:

307% mkdir ABC

308% ls -i 11997708 A 11997709 B 11997710 C

Un inode è una struttura di dati che contiene informazioni sulla directory o sul file. Ogni directory e file ne ha uno. Pensalo come un indirizzo (un numero indice davvero).

Se mi trovo in A, inode numero 11997708 e in un'altra shell (o nella stessa shell che sto per fare) cancella la directory A quindi ricreala e ls l'inode:

309% cd A

310% rmdir ../A

311% mkdir ../A

312% ls -i ..

11997720 A 11997709 B 11997710 C

Il nodo i è diverso, quindi se tenta di creare un file nella directory eliminata A:

Il 313% tocca questo

touch: impossibile toccare "this": nessun file o directory

perché la directory in cui mi trovo - non è più associata all'inode 11997720 - quindi dove attualmente non ho più un indirizzo / indice legittimo - inode. Quindi l'errore.

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.