태그 보관물: inode

inode

inode로 파일을 검색 할 수 있습니까? 수 있으므로 명령이 rm실제로 a파일 대신

지정된 순서대로 다음 명령을 실행했습니다.

$ln a b
$ls -i a b
523669 a 523669 b
$rm -f a
$ls -i b
523669 b

이 테스트 에서 inode가 여전히 존재하고 다른 파일 이름 ( )을 통해 검색 할 수 있으므로 명령이 rm실제로 a파일 대신 파일 이름 ( 이 테스트에서) 만 제거 한다고 결론을 내 렸습니다 b.

내 질문은 파일이 하나의 파일 이름에만 하드 링크되어 있으면 파일에 rm실행될 때 실제 파일 (즉, inode)이 완전히 제거됩니까? 그렇지 않은 경우 파일 이름없이 inode를 통해서만 파일 inode를 검색 할 수 있습니까?



답변

inode를 통해 파일을 열려고하면 디렉토리 탐색이 무시됩니다. 파일의 권한 및 파일로 이어지는 디렉토리를 판별하려면 디렉토리 순회가 필요합니다. 디렉토리 탐색이 없으면 커널은 호출 프로세스가 파일에 액세스 할 수 있는지 여부를 판별 할 방법이 없습니다.

파일 디스크립터에서 파일에 대한 링크를 작성할 수 있도록 Linux 커널에 제안 된 패치 가있었습니다 . 그것은 한 안전이 구현하는 것은 매우 어려웠 때문에 거부 .

Linux에서 (그리고 아마도 같은 이유로 다른 유닉스 변형에서), 삭제 된 파일에 대한 링크를 만들 수 없으므로 파일에 더 이상 이름이 없으면 다시 추가 할 수 없습니다 .¹ 삭제 된 파일을 열 수 있습니다 아래 마법의 링크를 열어 파일 /proc/$pid/fd/.

파일에 더 이상 링크가없고 더 이상 열려 있지 않으면 더 이상 존재하지 않으며 이전에 해당 데이터에서 사용한 공간을 언제든지 회수 할 수 있습니다.

¹ 파일 시스템에서 바이트를 파일 시스템 종속 방식 (예 debugfs: ext2 / ext3 / ext4)으로 직접 조정하여이 작업을 수행 할 수 있습니다 . 이를 위해서는 파일 시스템이 마운트 된 장치에 액세스해야합니다 (즉, 일반적으로 루트 만 시도 할 수 있음). 그러나 debugfs는 inode로 파일에 액세스 할 수 있지만 파일이 삭제되면 도움이되지 않습니다. 응용 프로그램이 파일을 닫으면 파일이 실제로 삭제되며 마운트 된 파일 시스템에서 읽기 / 쓰기 모드로 debugfs를 실행하는 것이 좋습니다. 재앙.


답변

Linux debugfs에서 대화식 ext2 / ext3 / ext4 파일 시스템 디버거는 lninode 번호를 가져와 filespec해당 파일에 대한 새 하드 링크를 작성할 수 있는 명령을 제공 합니다. 그러나 실제로 는 링크되지 않은 파일은 프로세스 에서 열린 파일 디스크립터를 유지하면서 프로세스 를 통해 열린 상태로 유지해야합니다 /proc/[pid]/fd/[n]. 삭제 된 파일에이 파일을 넣으려고하면 파일 시스템이 손상 될 수 있습니다.

이는 ext3 (및 확장 ext4)이 충돌 후 링크 해제를 안전하게 다시 시작할 수 있도록 하기 위해 실제로 inode에서 블록 포인터를 0으로 만드는 반면, ext2는 이러한 블록을 블록 비트 맵에서 사용되지 않은 것으로 표시하고 inode를 “삭제됨”으로 설정하고 블록 포인터를 그대로 둡니다. 그럼에도 불구하고 하드 링크를 작성하기 위해 파일 시스템을 읽기-쓰기로 마운트해야하므로 삭제 된 파일에 예약 된 블록이 이미 재 할당되었을 수 있습니다.

커널 버전 2.6.39 이전에는 GNU coreutils에 도입 된 옵션이었습니다.ln -L|--logical v8.0에 사용 하여 링크가없는 파일과 새 하드 링크 /proc/[pid]/fd/[n] 모두 tmpfs 파일 시스템 에있는 경우 열린 파일 설명자를 통해 링크되지 않은 파일을 복구 할 수있었습니다 . Gilles가 지적했듯이 파일 디스크립터에서 직접 하드 링크 작성을 허용하는 데 관련된 보안 고려 사항 으로 인해이 기능은 사용 불가능 합니다.


답변

‘ln’및 ‘rm’명령은 1970 년대 초부터 모든 UNIX 파일 시스템에서 이와 동일하게 작동했습니다. Mac OSX, BSD 및 Linux는 모두이 독창적 인 디자인을 상속합니다.

UNIX 파일 자체에는 이름이 없으며 inode 번호 또는 inum 만 있습니다. 그러나 이름을 해당 inum과 연결하는 특수한 “디렉토리”파일의 항목을 통해서만 액세스 할 수 있습니다. inum을 직접 지정할 수 없습니다.

디렉토리 자체 는 파일이므로 액세스해야합니다. 에 “경로 이름”로 알려진 슬래시로 구분 된 디렉토리 이름 (/)의 시리즈를 통해, 등등 (다른) 디렉토리를 통해합니다. 이름이 “/”로 시작하지 않으면 프로세스의 “현재 작업 디렉토리”에서 경로가 시작됩니다.이 경우 파일 시스템 루트 디렉토리로 시작합니다. 예를 들어, 경로 이름에 “/”문자가 포함되어 있지 않으면 현재 디렉토리의 항목 일 것으로 예상됩니다.

비 디렉토리 파일은 “하드 링크”로 알려진 경로 이름의 수에는 제한이 없습니다, 그리고 때까지 계속해서 존재 하는 모든 해당 경로 이름이 제거 된 그리고 마지막 프로세스가 파일을 폐쇄했다. 그런 다음 파일이 실제로 삭제되고 해당 공간이 재사용 가능한 것으로 표시됩니다. 즉, 단일 링크 된 파일을 creat () 또는 open () 한 다음 unlink ()하여 파일 시스템 이름 공간에 더 이상 표시되지 않지만 파일을 닫을 때까지 파일은 계속 존재합니다. 다른 프로그램에서 읽을 수없는 임시 스크래치 파일에 유용합니다.

디렉토리에는 inode 번호가 있지만 대부분의 파일 시스템은 하드 링크를 허용하지 않습니다. 하나의 다른 디렉토리에만 나타날 수 있습니다. (Mac OSX HFS + 파일 시스템은 예외입니다. Time Machine 백업이 가능합니다.) 디렉토리 (또는 다른 파일)에 대한 “소프트 링크”를 만들 수 있습니다. 소프트 링크는 inum이 아닌 다른 경로 이름을 포함한다는 점을 제외하고 디렉토리 항목과 유사합니다.

모든 UNIX 파일에는 소유자, 그룹 및 액세스 권한이 있습니다. 파일을 열 수 있도록하는 것이 필요하지만 충분하지 않습니다. 또한 경로 이름을 참조하는 데 사용하는 모든 디렉토리에 대해 최소한 실행 권한이 있어야합니다. 따라서 inode 번호로 UNIX 파일을 여는 표준 방법이없는 이유입니다. 중요하고 널리 사용되는 보안 메커니즘을 우회합니다.

그러나 권한 검사가 무시되므로 루트 (권한이있는) 사용자가 inode 번호로 파일을 여는 표준 방법이없는 이유를 설명하지 않습니다 . 이것은 백업과 같은 특정 시스템 관리 기능에 매우 유용합니다. 내가 아는 한, 그러한 메커니즘은 존재하지만 모두 파일 시스템에 따라 다릅니다. UNIX 파일 시스템에 대해 일반적인 방법은 없습니다.


답변

문제는 이론적으로 취할 수 있습니다. debugfs ) 또는 실용적으로 (비상 상황) . 후자의 경우, 의도는 하루를 절약하고 파일의 내용을 긴급하게 복원하는 것으로 가정합니다 (이 질문에 착륙 한 방식이므로 여전히 관련성이 있고 유용하다고 생각합니다).

커널 API debugfs가 없으므로 FS 구조를 직접 조작하므로 라이브 파일 시스템에서 실행 하면 안됩니다. 따라서 실제로 사용하려면 다른 파일 이름을 가져와야합니다. 파일이 어떤 프로세스 (모든 프로세스)에 의해 여전히 열려 있다고 가정하면 다음과 같은 편리한 파일 디스크립터에 도달 할 수 있습니다 /proc.

$ lsof -F pf "$PWD/a" | sed 's/^p//' # find pid and file descriptor number of any process having the file open
$ pid=1234
$ ls -l /proc/$pid/fd/* | grep "$PWD/a" # find file descriptor number
$ fd=42
$ cat /proc/$pid/fd/$fd > "$PWD/a.restored" # read contents to a new filename

팁 :

  • 당신이 바로 FD에 대한 의심이있는 경우는 다음과 같은 명령을 실행할 수 있습니다 file그것에을
  • 파일에 쓰는 프로세스가있는 경우 해당 프로세스를 최대한 빨리 중지하십시오. 그렇지 않으면 최신 데이터를 얻지 못할 것입니다. 다른 방법으로 fd를 통해서만 읽은 파일을 여는 방법이 있습니다 (시도 tail -f < /proc/$pid/fd/$fd > /dev/null, 쓰기 프로세스를 종료하여 깨끗하게 종료하고 새 프로세스의 fd를 사용하는 것).

답변