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


12

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

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.