「rm -r」がこのフォルダーを削除できないのはなぜですか?


12

私はとフォルダ持っている-wxと呼ばれるアクセス権folder1と呼ばれ、その中に別のフォルダfolder2rwxアクセス権を。

folder1このコマンドを使用して削除しようとしました:

rm -r folder1

しかし、私は次のエラーを受け取りました:

rm: cannot remove 'folder1': Permission denied

私がこのエラーを受け取ったと思う理由は、rmプログラムがそのコンテンツを削除するために最初にコンテンツを取得する必要があるためですfolder1(その中のファイルとフォルダの名前を取得するfolder1)またはその名前を知らないフォルダ)、rmプログラムはfolder1それ自体を削除できます。

しかしfolder1read許可rmがないため、プログラムはコンテンツを取得できず、したがってコンテンツを削除できません。また、コンテンツを削除できないため、削除できません。

私は正しいですか?


1
「ls -l」を実行して、ディレクトリのアクセス許可を教えてください。
jamesqf

回答:


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この場合、空かどうかはわからないため、レポートできません。読み取り権限のない空のディレクトリを削除しようとすると、同じエラーが引き続き発生します。(また、私の以前のコメントを無視してください、私は自分の思考の上限がありませんでした)。
クサラナナンダ

1
@Kusalanandaそれは健全に聞こえますが、rmdir「Directory not empty」を報告できます。そして、あなたが私のテストを読んだ場合、それが空になったら、読み取り許可なしでfolder1ディレクトリを削除することを受け入れることがわかります。
user2233709

2
あなたのテストは、システム間の興味深い違いを示しています。それが空のときPermission deniedにしようとすると、私は得るrm -r folder1。私はLinuxではなくOpenBSDを使用しています。
クサラナンダ

@Kusalanandaそれは面白いです。Linuxと{Free、Net、Open} BSDが同じように動作するように、この動作は単一のUnix仕様で指定されていると思います。(記録のために、Linux 4.9.144-3 x86_64カーネルでDebian Stretch 9.8を使用しています。)
user2233709

うーん... POSIXが言うことは、オペランドがディレクトリで-rあり、使用されている場合、各ディレクトリエントリ(.およびを除く..)は、のファイルオペランドであるかのように削除する必要があるということですrm -r。GNU rmは、rmdir()その内容を取得する方法がないので、GNU が読み取り可能でない場合、単にディレクトリに対してa を実行するように見えます。
クサラナンダ

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

2つの試みのトレースでは、違いはディレクトリの内容を読み取ることができないことです(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)

4行目を見てください:unlinkat...ディレクトリが空ではないため失敗します。これは、予期しない動作であると考えられるものです。読み取り権限がないにもかかわらず、ディレクトリをまったく削除しようとするという事実です。


ああ、あなたは正しい、私は本当のキーボードに着いたときにそれを修正します。ありがとう。
オイクラン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.