디렉토리 삭제시`ls` 오류


13

두 개의 껍질이 열려 있습니다. 첫 번째는 디렉토리 A에 있습니다. 두 번째는 디렉토리 A를 제거한 다음 다시 만듭니다. 첫 번째 쉘로 돌아가서을 입력 ls하면 출력은 다음과 같습니다.

ls: cannot open directory .: Stale file handle

왜? 첫 번째 쉘 (존재하지 않는 디렉토리 안에 열려있는 쉘)은 다음 명령을 기다리는 동안 "고정"되고 디렉토리가 삭제되고 재 작성되었다는 것을 "실현"하지 않았다고 생각했습니다. 쉘이 문자열 이외의 현재 작업 디렉토리에 대한 "더 깊은"참조를 보유하고 $PWD있습니까?


2
답이 아니지만 쉘이 발에 떨어지게하려면을 실행할 수 있습니다 cd $PWD.
dhag

나는 무슨 일이 일어나고 있는지 이해하고 싶습니다, 나는 껍질을 다시 얻는 것이 쉽다는 것을 알고 있습니다 :)
fonini

이 디렉토리가 NFS 서버에 있습니까? 부실 파일 핸들을 얻는 유일한 상황이라고 생각합니다.
Barmar

디렉토리가 로컬입니다. 시스템에서이 작업을 수행하면 결과가 달라 집니까?
fonini

답변:


17

디렉토리 (예 : 모든 파일)는 이름으로 정의되지 않습니다. 이름을 디렉토리의 주소 로 생각하십시오 . 디렉토리를 옮길 때 여전히 같은 디렉토리입니다. 다른 집으로 이사하는 경우에도 여전히 같은 사람입니다. 디렉토리를 제거하고 같은 이름으로 새 디렉토리를 만들면 이전에 살던 집으로 이사하는 사람이 아닌 것처럼 새 디렉토리입니다.

각 프로세스에는 작업 디렉토리가 있습니다. cd쉘 의 명령은 쉘의 현재 작업 디렉토리를 변경합니다. 이 pwd명령은 현재 작업 디렉토리의 ¹ 경로를 인쇄합니다.

디렉토리 A를 제거했을 때, 이것은 부모 디렉토리에서 A에 대한 항목을 제거하는 것이 었습니다. 디렉토리 A 자체는 파일 시스템에 남아 있지만 이름이없는 분리 된 상태입니다. 프로세스, 즉 첫 번째 쉘에서 사용 중이므로 아직 삭제되지 않았습니다. 첫 번째 쉘에서 디렉토리를 변경하면 디렉토리가 마지막으로 삭제되었습니다. 프로세스가 여전히 열려있는 동안 파일이 삭제 될 때도 같은 일이 발생합니다. 파일의 디렉토리 항목이 즉시 제거되고 파일 자체는 사용이 중지되면 제거됩니다.

마찬가지로 디렉토리를 이동할 때 어떤 일이 발생하는지 관찰하십시오.

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

다른 껍질에서 :

mv one tmp
mv two one
mv tmp two

첫 번째 쉘에서 :

ls

파일 1은 원래 호출 된 디렉토리에 one있으며 이제는이라고 two합니다. 파일 2은 원래 호출 된 디렉토리에 two있으며 이제는이라고 one합니다.

¹ 좀 더 정확하게 말하면, 심볼릭 링크 나 다른 미묘한 부분이 포함 경로는 고유하지 않을 수 있습니다.


여기서 핵심은 프로세스가 경로뿐만 아니라 작업 디렉토리의 inode를 보유한다는 것입니다.
Nacht-복직 모니카

1
@Nacht이 프로세스는 디스크립터를 보유하지만 커널은 모든 맵핑 (설명자 / 파일 테이블 항목 / 노드)을 수행합니다. 실제로 내부적으로 커널은 경로를 저장하지 않습니다 (관심있는 것들이 경로가 아닌 inode에 있기 때문에). 게다가하는 "경로는" 파일에 단지 하나 개의 링크는 몇 :)있을 수 있습니다 ...입니다
존 WH 스미스

아, 그것은 설명자를 가지고 있습니다. bash는 지속적으로 작업 디렉토리의 fd를 보유하고 있습니까? 반드시 모든 프로세스가 작업 디렉토리의 fd를 가지고있는 것은 아닙니다 ... stdin / out / err 이후에 값 3에서 시작하는 fd를 기억한다고 생각했습니다
Nacht-Reinstate Monica

2
@Nacht 현재 디렉토리는 파일 디스크립터가 아니지만, 파일 디스크립터와 비슷하게 작동합니다. 커널은 모든 프로세스에 대해이를 유지 관리합니다. Linux에서는 다음 /proc/<pid>/cwd과 같이 작동합니다 /proc/<pid>/fd/<number>. 그것은이다 CWD의 출력에 lsof.
질 'SO-정지 존재 악마'

cd - && cd -경우 자동으로 만들 수 있습니까?
Vitaly Zdanevich

8

새 디렉토리 A는 디렉토리 A와 동일하지 않습니다. 새 디렉토리 A stat를 삭제하기 전과 새 디렉토리 를 작성한 후 명령 으로 확인할 수 있으며 다른 i- 노드 번호가 표시됩니다.
그리고 이것은 커널 작동 방식과 관련이 있다고 생각합니다. 단순히 각 프로세스에 대한 현재 디렉토리의 i 번호를 추적합니다. 따라서 다른 i- 번호가 있으므로 다른 충돌이 발생합니다.


inode는 고유 한 숫자가 아니라 구조입니다. 고유하게 식별 할 수 있지만 ID보다 많은 정보를 보유합니다. 이것이 링크보다 더 중요한 이유입니다.
John WH Smith

1
@ JohnWHSmith Gilles가 더 좋을수록이 답변을 삭제하려고합니다.
taliezin

6
당신을 삭제할 이유가 없습니다! 그런 느낌이 든다면, 답변에 다른 면책을 더 잘 고려한다는 면책을 추가 할 수 있습니다.
terdon

7

이것은 예상 된 동작입니다. 새 디렉토리 A는 이전 디렉토리 A와 동일하지 않으며 동일한 이름을 갖습니다. 따라서 첫 번째 터미널의 $ PWD는 여전히 사라졌습니다 mkdir A.


2
'새 디렉토리 A는 이전 디렉토리 A와 동일하지 않습니다'에 대해 자세히 설명해 주시겠습니까? 파일 / 디렉토리의 어떤 측면이 변경됩니까? inode 번호와 관련이 있습니까? 물어봐서 미안하지만, 나는 이것에 대해 배우고 있습니다.
rahul

2
@rahul 철학적으로, 그 변화는 그 정체성 에 관한 것입니다. 같은 위치에 아무것도없는 새로운 디렉토리가 만들어졌습니다. 구현 수준에서 그렇습니다. 열려있는 모든 파일은 inode로 식별되며 이전 디렉토리와 새 디렉토리는 다른 inode 번호를 가진 고유 한 inode를 갖습니다.
홉스

0

파일과 같은 디렉토리에는 관련된 inode가 있습니다.

307 % mkdir ABC

308 % ls -i 11997708 A 11997709 B 11997710 C

inode는 디렉토리 또는 파일에 대한 정보를 포함하는 데이터 구조입니다. 모든 디렉토리와 파일에는 하나가 있습니다. 이를 주소 (실제로 색인 번호)로 생각하십시오.

내가 A, inode 번호 11997708 및 다른 쉘 (또는 똑같은 쉘)에 있으면 디렉토리 A를 삭제 한 다음 다시 작성하고 inode를 ls하십시오.

309 % cd A

310 % rmdir ../A

311 % mkdir ../A

312 % ls -i ..

11997720 A 11997709 B 11997710 C

i 노드가 다르므로 삭제 된 디렉토리 A에 파일을 작성하려고하면 :

313 % 터치

touch : 'this'를 터치 할 수 없습니다 : 해당 파일 또는 디렉토리가 없습니다.

내가있는 디렉토리가 더 이상 inode 11997720 과 연결되어 있지 않기 때문에 현재 더 이상 합법적 인 주소 / 색인 -inode 가 없습니다. 따라서 오류입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.