Perché "rm -r" non è in grado di eliminare questa cartella?


12

Ho una cartella con le -wxautorizzazioni chiamate folder1e un'altra cartella al suo interno chiamata folder2con le rwxautorizzazioni.

Ho provato a cancellare folder1usando questo comando:

rm -r folder1

Ma ho ricevuto il seguente errore:

rm: cannot remove 'folder1': Permission denied

Il motivo per cui penso di aver ricevuto questo errore è perché il rmprogramma deve prima ottenere il contenuto di folder1(ottenere i nomi dei file e delle cartelle all'interno di folder1esso) per poter eliminare quel contenuto (perché non è possibile eliminare un file o cartella senza conoscere il suo nome penso), e quindi il rmprogramma può eliminare folder1se stesso.

Ma dal momento folder1che non ha il readpermesso, quindi il rmprogramma non può ottenere il suo contenuto, e quindi non può cancellare il suo contenuto, e dal momento che non può cancellare il suo contenuto, quindi non può cancellarlo.

Ho ragione?


1
Fai "ls -l" e dicci quali sono le autorizzazioni della DIRECTORY.
jamesqf,

Risposte:


19

Penso che la tua analisi sia corretta: non puoi cancellare la directory poiché non è vuota e non puoi svuotarla poiché non puoi vederne il contenuto.

Ho appena provato:

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

Quando ho scritto "tu", intendevo qualsiasi programma tu possa eseguire. Il tuo rm -rcomando vede prima che si folder1tratta di una directory, quindi cerca di scoprirne il contenuto per svuotarlo, ma non riesce a perdere l'autorizzazione di lettura, quindi tenta di eliminarlo ma non riesce perché non è vuoto. L '"Autorizzazione negata" è fuorviante; Penso che "Directory non vuota" (come i rmdirreport) sarebbe più appropriato.)


4
In Directory not emptyquesto caso non può segnalare in quanto non saprebbe che era vuoto o no. Si otterrebbe comunque lo stesso errore quando si tenta di eliminare una directory vuota per la quale non si dispone delle autorizzazioni di lettura. (Inoltre, per favore, ignora il mio commento precedente, non avevo il mio cappello pensante).
Kusalananda

1
@Kusalananda Sembra sano, ma rmdirè in grado di segnalare "Directory non vuota". E se leggi il mio test, vedrai che accetta di rimuovere la folder1directory, senza permesso di lettura , una volta che l'ho svuotato.
user2233709

2
Il tuo test mostra un'interessante differenza tra i nostri sistemi. Ottengo un Permission deniedquando provo rm -r folder1quando è vuoto. Sono su OpenBSD, non su Linux.
Kusalananda

@Kusalananda È interessante. Avrei pensato che questo comportamento fosse stato specificato dalla specifica Unix singola, così che Linux e {Free, Net, Open} BSD si sarebbero comportati in modo identico. (Per la cronaca, sto usando Debian Stretch 9.8 con un kernel linux 4.9.144-3 x86_64.)
user2233709

Hmm ... L'unica cosa che dice POSIX è che se l'operando è una directory e -rviene usato, ogni voce di directory (tranne per .e ..) dovrebbe essere rimossa come se fosse un operando di file di rm -r. Sembra che GNU rmfaccia semplicemente uno rmdir()nella directory se non è leggibile, perché non avrà modo di ottenerne il contenuto.
Kusalananda

7

Affinché si verifichi la cancellazione, il sistema deve essere in grado di leggere i contenuti e identificare ciò che deve essere eliminato.

Ho provato a simulare ciò che stai tentando:

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

Se proviamo a eliminare senza autorizzazioni di lettura, non riesce:

[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 una sequenza per i due tentativi la differenza è che il contenuto della directory non può essere letto (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

Con autorizzazioni di lettura:

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

Per concludere anche se possiedi una directory e ha il bit eseguibile, hai ancora bisogno delle autorizzazioni di lettura in modo da poter vedere il suo contenuto ed eliminare la cartella. Tuttavia, non è lo stesso per un file.


0

Bene, non ho abbastanza reputazione per commentare la risposta di ttaran7, quindi sembra una risposta che dovrà essere. Anche il mio voto non è pubblicamente visibile, a causa della scarsa reputazione. Ho votato a favore di quella risposta per aver effettivamente incluso una traccia di chiamata di sistema, piuttosto che solo una speculazione.

Per rispondere alla domanda del PO: Sì, il tuo ragionamento era corretto: ti bloccavi per la mancata lettura della directory

Ho eseguito una traccia simile a quella che avevano fatto (ttaran7) perché sospettavo lo stesso ragionamento: la rmchiamata non sarebbe riuscita in caso di mancata lettura della directory e quella sarebbe stata la fine, nessuna possibilità di lamentarsi della directory vuota. Dopo aver dato una seconda occhiata alla traccia che ho preso, ho notato che è stata effettuata una chiamata di sistema per tentare di scollegare comunque il nome file fornito:

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)

Guarda la quarta riga: unlinkat... che non riesce perché la directory NON è vuota. Questo è ciò che considererei un comportamento inaspettato, il fatto che tenti di eliminare la directory, nonostante non abbia i permessi di lettura.


Ah, hai ragione, lo correggerò quando arrivo a una vera tastiera. Grazie.
ojklan,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.