“rm -r”이이 폴더를 삭제할 수없는 이유는 무엇입니까?


12

내가있는 폴더가 -wx호출 권한 folder1및라는 그 안에 다른 폴더 folder2에 rwx권한을.

folder1이 명령을 사용하여 삭제하려고했습니다 .

rm -r folder1

그러나 다음과 같은 오류가 발생했습니다.

rm: cannot remove 'folder1': Permission denied

내가이 오류가 발생했다고 생각하는 이유는 rm프로그램이 먼저 folder1파일 folder1을 삭제할 수 없기 때문에 해당 내용을 삭제할 수 있도록 내용을 가져와야합니다 ( 파일과 폴더의 이름을 가져와야 함) 때문입니다. 또는 그 이름을 알지 못하는 폴더) rm프로그램이 삭제 될 수 folder1있습니다.

그러나 권한 folder1이 없기 때문에 프로그램은 내용을 가져올 수 없으므로 내용을 삭제할 수 없으므로 내용을 삭제할 수 없으므로 삭제할 수 없습니다.readrm

제가 맞습니까?


1
"ls -l"을 수행하고 DIRECTORY의 권한이 무엇인지 알려주십시오.
— jamesqf 2014

답변:


19

분석이 정확하다고 생각합니다. 비어 있지 않기 때문에 디렉토리를 삭제할 수 없으며 내용을 볼 수 없으므로 비울 수 없습니다.

방금 시도해 보았습니다.

$ mkdir -p folder1/folder2
$ chmod -r folder1
$ rm -rf folder1
rm: cannot remove 'folder1': Permission denied
$ rmdir folder1/folder2
$ rm -rf folder1
$ 

“당신”이라고 썼을 때 나는 당신이 실행할 수있는 모든 프로그램을 의미했습니다. 귀하의 rm -r명령이 먼저가보고 folder1그것을 비워 내용을 발견하려고, 그래서 디렉토리이지만, 읽기 권한이없는 실패, 그것은 그것을 삭제하려고하지만이 비어 있기 때문에 실패합니다. “권한이 거부되었습니다”는 오해의 소지가 있습니다. rmdir보고서 와 같은 '비어 있지 않은 디렉토리' 가 더 적합하다고 생각합니다.)


4
Directory not empty이 경우에는 비어 있는지 알 수 없으므로보고 할 수 없습니다. 읽기 권한이없는 빈 디렉토리 를 삭제하려고하면 여전히 같은 오류가 발생 합니다. (또한 이전 의견을 무시하십시오. 내 생각 상한이 없었습니다).
— Kusalananda

1
@Kusalananda 제정신이게 들리지만 rmdir“Directory not empty”를보고 할 수 있습니다. 그리고 내 테스트를 읽으면 일단 비운 후에는 읽기 권한없이folder1 디렉토리 를 제거하는 것이 허용됩니다 .
— user2233709

2
테스트 결과 시스템간에 흥미로운 차이점이 있습니다. 내가 얻을 Permission denied하려고 할 때 rm -r folder1비어 때. 저는 Linux가 아니라 OpenBSD를 사용하고 있습니다.
— Kusalananda

@Kusalananda 흥미 롭습니다. Linux와 {Free, Net, Open} BSD가 동일하게 동작하도록이 동작이 Single Unix Specification에 의해 지정되었다고 생각했을 것입니다. (기록을 위해, 나는 리눅스 4.9.144-3 x86_64 커널과 함께 데비안 스트레치 9.8을 사용하고 있습니다.)
— user2233709

흠 ... POSIX가 말하는 유일한 것은 피연산자가 디렉토리이고 -r사용되는 경우 각 디렉토리 항목 ( .및 제외 ..)은 마치 파일 피연산자 인 것처럼 제거해야한다는 것입니다 rm -r. 읽을 수 없다면 GNU는 rm단순히 rmdir()디렉토리에서 내용을 얻을 수있는 방법이 없기 때문에 디렉토리에서 수행하는 것처럼 보입니다 .
— Kusalananda

7

삭제가 발생하려면 시스템이 내용을 읽고 삭제할 내용을 식별 할 수 있어야합니다.

나는 당신이 시도하는 것을 시뮬레이션하려고 시도했습니다.

[vagrant@desktop1 ~]$ sudo rm -rf folder1/ && mkdir -pv folder1/folder2 && sudo chmod 333 -v folder1/ && sudo chmod 777 -v folder1/folder2
mkdir: created directory 'folder1'
mkdir: created directory 'folder1/folder2'
mode of 'folder1/' changed from 0775 (rwxrwxr-x) to 0333 (-wx-wx-wx)
mode of 'folder1/folder2' changed from 0775 (rwxrwxr-x) to 0777 (rwxrwxrwx)
[vagrant@desktop1 ~]$ ls -lh
total 0
d-wx-wx-wx. 3 vagrant vagrant 21 Feb 24 10:40 folder1
[vagrant@desktop1 ~]$ 

읽기 권한없이 삭제하려고하면 실패합니다.

[vagrant@desktop1 ~]$ rm -r folder1/
rm: cannot remove 'folder1/': Permission denied
[vagrant@desktop1 ~]$ sudo chmod +r folder1/
[vagrant@desktop1 ~]$ rm -r folder1/
[vagrant@desktop1 ~]$ 

두 가지 시도에 대한 strace에서 차이점은 디렉토리 내용을 읽을 수 없다는 것입니다 (getdents).

newfstatat(AT_FDCWD, "folder1/", {st_mode=S_IFDIR|0333, st_size=21, ...}, AT_SYMLINK_NOFOLLOW) = 0
openat(AT_FDCWD, "folder1/", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_DIRECTORY|O_NOFOLLOW) = -1 EACCES (Permission denied)
geteuid()                               = 1000
newfstatat(AT_FDCWD, "folder1/", {st_mode=S_IFDIR|0333, st_size=21, ...}, AT_SYMLINK_NOFOLLOW) = 0
faccessat(AT_FDCWD, "folder1/", W_OK)   = 0
openat(AT_FDCWD, "folder1/", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_DIRECTORY|O_NOFOLLOW) = -1 EACCES (Permission denied)
newfstatat(AT_FDCWD, "folder1/", {st_mode=S_IFDIR|0333, st_size=21, ...}, AT_SYMLINK_NOFOLLOW) = 0

읽기 권한이있는 경우 :

newfstatat(AT_FDCWD, "folder1/", {st_mode=S_IFDIR|0777, st_size=21, ...}, AT_SYMLINK_NOFOLLOW) = 0
openat(AT_FDCWD, "folder1/", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_DIRECTORY|O_NOFOLLOW) = 3
fstat(3, {st_mode=S_IFDIR|0777, st_size=21, ...}) = 0
fcntl(3, F_GETFL)                       = 0x38800 (flags O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_DIRECTORY|O_NOFOLLOW)
fcntl(3, F_SETFD, FD_CLOEXEC)           = 0
getdents(3, /* 3 entries */, 32768)     = 80
close(3)                                = 0
geteuid()                               = 1000

디렉토리를 소유하고 실행 가능 비트가있는 경우에도 결론을 보려면 해당 내용을보고 폴더를 삭제할 수있는 읽기 권한이 필요합니다. 그러나 파일과 동일하지 않습니다.


0

글쎄, 나는 ttaran7의 답변에 대해 논평 할만 큼 충분한 평판을 얻지 못했기 때문에 대답해야 할 것 같습니다. 저의 평판은 낮은 투표로 인해 공개적으로 보이지 않습니다. 나는 단지 추측이 아니라 시스템 콜 트레이스를 실제로 포함시킨 것에 대한 답변에 투표했다.

OP의 질문에 대답하려면 : 그렇습니다. 당신의 추론은 맞습니다.

나는 같은 추론을 의심했기 때문에 그들 (ttaran7)이 한 일과 비슷한 추적을 실행했습니다 rm. 디렉토리를 읽지 못하면 호출이 실패하고 그 끝이되어 디렉토리가 비어 있다고 불평 할 기회가 없습니다. 내가 가져온 추적을 다시 살펴보면 제공된 파일 이름을 연결 해제하려고 시스템 호출이 이루어 졌음을 알았습니다.

newfstatat(AT_FDCWD, "folder1", {st_mode=S_IFDIR|0311, st_size=4096, ...}, AT_SYMLINK_NOFOLLOW) = 0
openat(AT_FDCWD, "folder1", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_NOFOLLOW|O_DIRECTORY) = -1 EACCES (Permission denied)
openat(AT_FDCWD, "folder1", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_NOFOLLOW|O_CLOEXEC|O_DIRECTORY) = -1 EACCES (Permission denied)
unlinkat(AT_FDCWD, "folder1", AT_REMOVEDIR) = -1 ENOTEMPTY (Directory not empty)
openat(AT_FDCWD, "/usr/share/locale/locale.alias", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=2995, ...}) = 0
read(3, "# Locale name alias data base.\n#"..., 4096) = 2995
read(3, "", 4096)                       = 0
close(3)                                = 0
openat(AT_FDCWD, "/usr/share/locale/en_AU/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/en/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale-langpack/en_AU/LC_MESSAGES/coreutils.mo", O_RDONLY) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=45256, ...}) = 0
mmap(NULL, 45256, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f8db25ca000
close(3)                                = 0
openat(AT_FDCWD, "/usr/share/locale- langpack/en/LC_MESSAGES/coreutils.mo", O_RDONLY) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=578, ...}) = 0
mmap(NULL, 578, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f8db25c9000
close(3)                                = 0
write(2, "rm: ", 4rm: )                     = 4
write(2, "cannot remove 'folder1'", 23cannot remove 'folder1') = 23
openat(AT_FDCWD, "/usr/share/locale/en_AU/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/en/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale-langpack/en_AU/LC_MESSAGES/libc.mo", O_RDONLY) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=2893, ...}) = 0
mmap(NULL, 2893, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f8db25c8000
close(3)                                = 0
openat(AT_FDCWD, "/usr/share/locale-langpack/en/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
write(2, ": Permission denied", 19: Permission denied)     = 19
write(2, "\n", 1
lseek(0, 0, SEEK_CUR)                   = -1 ESPIPE (Illegal seek)
close(0)                                = 0
close(1)                                = 0
close(2)                                = 0
exitgroup(1)

네 번째 줄을보십시오 : unlinkat... 디렉토리가 비어 있지 않아 실패합니다. 이제는 예상치 못한 동작, 즉 읽기 권한이 없어도 디렉토리를 삭제하려고 시도하는 것입니다.


아, 맞아요. 실제 키보드에 도달하면 바로 잡겠습니다. 감사.
— ojklan 2019
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.