Warum kann "rm -r" diesen Ordner nicht löschen?

12

Ich habe einen Ordner mit -wxBerechtigungen aufgerufen folder1und einen anderen Ordner darin folder2mit rwxBerechtigungen aufgerufen .

Ich habe versucht, folder1mit diesem Befehl zu löschen :

rm -r folder1

Aber ich habe folgenden Fehler bekommen:

rm: cannot remove 'folder1': Permission denied

Der Grund, warum ich denke, dass ich diesen Fehler habe, ist, dass das rmProgramm zuerst den Inhalt von folder1(die Namen der darin enthaltenen Dateien und Ordner folder1) abrufen muss, um diesen Inhalt löschen zu können (weil Sie eine Datei nicht löschen können) oder ordner ohne seinen namen zu kennen denke ich) und dann rmkann folder1sich das programm von selbst löschen .

Da das Programm folder1jedoch nicht über die readBerechtigung verfügt, rmkann es seinen Inhalt nicht abrufen und daher seinen Inhalt nicht löschen. Da es seinen Inhalt nicht löschen kann, kann es ihn nicht löschen.

Hab ich recht?

John
quelle
1
Geben Sie "ls -l" ein und teilen Sie uns die Berechtigungen des DIRECTORY mit.
Jamesqf

Antworten:

19

Ich denke, Ihre Analyse ist richtig: Sie können das Verzeichnis nicht löschen, da es nicht leer ist, und Sie können es nicht leeren, da Sie seinen Inhalt nicht sehen können.

Ich habe es gerade ausprobiert:

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

Als ich "Sie" schrieb, meinte ich jedes Programm, das Sie ausführen dürfen. Ihr rm -rBefehl erkennt zuerst, dass folder1es sich um ein Verzeichnis handelt. Daher versucht er, den Inhalt zu ermitteln, um es zu leeren, schlägt jedoch fehl, wenn die Leseberechtigung fehlt. Anschließend wird versucht, es zu löschen, schlägt jedoch fehl, weil es nicht leer ist. Die "Erlaubnis verweigert" ist irreführend; Ich denke, "Verzeichnis nicht leer" (wie rmdirBerichte) wäre angemessener.)

user2233709
quelle
4
Es kann Directory not emptyin diesem Fall nicht gemeldet werden, da es nicht wissen würde, dass es leer ist oder nicht. Wenn Sie versuchen, ein leeres Verzeichnis zu löschen , für das Sie keine Leseberechtigung haben, wird derselbe Fehler weiterhin angezeigt . (Bitte ignorieren Sie auch meinen vorherigen Kommentar, ich hatte meine Denkbeschränkung nicht aufgesetzt).
Kusalananda
1
@Kusalananda Das klingt vernünftig, kann aber rmdirmelden, dass das Verzeichnis nicht leer ist. Und wenn Sie meinen Test lesen, werden Sie feststellen, dass das Entfernen des folder1Verzeichnisses ohne Leseberechtigung akzeptiert wird , sobald ich es geleert habe.
user2233709
2
Ihr Test zeigt einen interessanten Unterschied zwischen unseren Systemen. Ich bekomme eine, Permission deniedwenn ich es versuche, rm -r folder1wenn es leer ist. Ich bin auf OpenBSD, nicht Linux.
Kusalananda
@ Kusalananda Das ist interessant. Ich hätte gedacht, dass dieses Verhalten durch die Single Unix-Spezifikation spezifiziert wurde, so dass Linux und {Free, Net, Open} BSD sich identisch verhalten würden. (Für die Aufzeichnung verwende ich Debian Stretch 9.8 mit einem Linux 4.9.144-3 x86_64-Kernel.)
user2233709
Hmm ... Das einzige, was POSIX sagt, ist, dass, wenn der Operand ein Verzeichnis ist und -rverwendet wird, jeder Verzeichniseintrag (mit Ausnahme von .und ..) entfernt werden sollte, als wäre er ein Dateioperand von rm -r. Es rmsieht so aus, als würde GNU einfach einen rmdir()Befehl im Verzeichnis ausführen, wenn er nicht lesbar ist, da es keine Möglichkeit gibt, den Inhalt abzurufen.
Kusalananda
7

Zum Löschen muss das System in der Lage sein, den Inhalt zu lesen und zu identifizieren, was gelöscht werden muss.

Ich habe versucht zu simulieren, was Sie versuchen:

[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 ~]$ 

Wenn wir versuchen, ohne Leserechte zu löschen, schlägt dies fehl:

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

In einer Strace für die beiden Versuche besteht der Unterschied darin, dass der Verzeichnisinhalt nicht gelesen werden kann (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

Mit Leserechten:

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

Selbst wenn Sie ein Verzeichnis besitzen und dieses über das ausführbare Bit verfügt, benötigen Sie Leseberechtigungen, damit Sie dessen Inhalt sehen und den Ordner löschen können. Es ist jedoch nicht dasselbe für eine Datei.

ttaran7
quelle
0

Nun, ich habe nicht genug Reputation, um die Antwort von ttaran7 zu kommentieren, also sieht es so aus, als müsste es eine Antwort sein. Meine Gegenstimme ist auch nicht öffentlich sichtbar, weil ich ein schlechtes Ansehen habe. Ich habe für diese Antwort gestimmt, weil sie tatsächlich eine Systemaufruf-Ablaufverfolgung enthält, und nicht nur Spekulation.

Um die Frage des OP zu beantworten: Ja, Ihre Argumentation war richtig: Sie werden blockiert, wenn Sie das Verzeichnis nicht lesen können

Ich habe eine ähnliche Ablaufverfolgung durchgeführt wie sie (ttaran7), weil ich die gleiche Überlegung vermutete: Der rmAufruf würde fehlschlagen, wenn das Verzeichnis nicht gelesen würde, und das wäre das Ende, keine Chance, sich über das leere Verzeichnis zu beschweren. Bei einem zweiten Blick auf den Trace, den ich erstellt habe, ist mir aufgefallen, dass ein Systemaufruf ausgeführt wurde, um zu versuchen, die Verknüpfung des angegebenen Dateinamens trotzdem aufzuheben:

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)

Schauen Sie sich die 4. Zeile an: unlinkat... was fehlschlägt, weil das Verzeichnis NICHT leer ist. Nun, das ist, was ich als unerwartetes Verhalten betrachten würde, die Tatsache, dass es versucht, das Verzeichnis überhaupt zu löschen, obwohl es keine Leseberechtigungen hat.

ojklan
quelle
Ah, du hast recht, das werde ich korrigieren, wenn ich zu einer richtigen Tastatur komme. Vielen Dank.
Ojklan