'ls' erro quando o diretório é excluído

13

Eu tenho duas conchas abertas. O primeiro está no diretório A. No segundo, eu removo o diretório A e, em seguida, o recrio. Quando eu volto para o primeiro shell e digito ls , a saída é:

ls: cannot open directory .: Stale file handle

Por quê? Eu pensei que o primeiro shell (aquele que permaneceu aberto dentro de um diretório inexistente) iria "congelar" enquanto aguarda o próximo comando, e não teria "percebido" que o diretório foi excluído e recriado. O shell mantém uma referência "mais profunda" ao seu diretório de trabalho atual diferente da string $PWD ?

    
por fonini 14.05.2015 / 21:10

4 respostas

17

Um diretório (como qualquer arquivo) não é definido por seu nome. Pense no nome como o endereço do diretório . Quando você move o diretório, ainda é o mesmo diretório, como se você fosse para uma casa diferente, você ainda é a mesma pessoa. Se você remover um diretório e criar um novo com o mesmo nome, é um novo diretório, assim como alguém que se muda para a casa onde você morava não é você.

Cada processo tem um diretório de trabalho . O comando cd no shell altera o diretório de trabalho atual do shell. O comando pwd imprime o caminho to para o diretório de trabalho atual.

Quando você removeu o diretório A, o que isso fez foi remover a entrada de A em seu diretório pai. O diretório A permaneceu no sistema de arquivos, mas em um estado desanexado, sem nome. Ele não foi excluído ainda porque estava em uso por um processo, ou seja, o primeiro shell. Quando você alterou o diretório no primeiro shell, o diretório foi finalmente excluído. O mesmo acontece quando um arquivo é excluído enquanto um processo ainda o mantém aberto: a entrada de diretório do arquivo é removida imediatamente e o próprio arquivo é removido quando ele deixa de estar em uso.

Da mesma forma, observe o que acontece quando você move diretórios.

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

Em outro shell:

mv one tmp
mv two one
mv tmp two

No primeiro shell:

ls

O arquivo 1 está no diretório originalmente chamado one e agora é chamado de two . O arquivo 2 está no diretório originalmente chamado two e agora é chamado de one .

¹ Mais precisamente, o caminho a , que pode não ser único se links simbólicos ou outras sutilezas estiverem envolvidos.

    
por 15.05.2015 / 03:14
8

O novo diretório A não é o mesmo que o diretório A. Ele pode ser verificado com o comando stat antes de excluir o antigo e depois de criar um novo e você verá diferentes números de nós i. E acho que isso está relacionado a como o kernel funciona. Ele simplesmente controla o número i do diretório atual de cada processo. Então, como há números diferentes, isso levará a diferentes colisões.

    
por 15.05.2015 / 00:15
7

Esse é o comportamento esperado. O novo diretório A não é o mesmo que o antigo diretório A, acontece que ele tem o mesmo nome. Então, o $ PWD do primeiro terminal ainda está desaparecido, ele não reapareceu magicamente quando você fez o mkdir A .

    
por 14.05.2015 / 21:15
0

Um diretório, como um arquivo, tem um inode associado a ele:

307% mkdir A B C

308% ls -i 11997708 A 11997709 B 11997710 C

Um inode é uma estrutura de dados que contém informações sobre o diretório ou arquivo. Todo diretório e arquivo tem um. Pense nisso como um endereço (um número de índice realmente).

Se eu estiver em A, o número do inode 11997708 e em outro shell (ou no mesmo shell que vou fazer) exclua o diretório A e, em seguida, recrie-o e ls o inode:

309% cd A

310% rmdir ../ A

311% mkdir ../ A

312% ls -i ..

11997720 A 11997709 B 11997710 C

O nó i é diferente, por isso, se tentar criar um arquivo no diretório excluído A:

313% tocam isso

toque: não pode tocar em "this": nenhum arquivo ou diretório desse tipo

porque o diretório em que estou - não está mais associado ao inode 11997720 - portanto, onde eu não tenho mais um endereço / índice - inode legítimo. Assim, o erro.

    
por 22.05.2015 / 14:55