文件權限與屬性 - Arch Linux 中文维基

跳至內容

# 文件權限與屬性

出自 Arch Linux 中文维基
翻譯狀態：

- 本文（或部分內容）譯自 File permissions and attributes，最近一次同步於 2022-11-18，若英文版本有所更改，則您可以幫助同步與翻譯更改的內容。
- 您可以在 ArchWiki 的對應頁面找到本文翻譯的原始修訂歷史。
- 本文可能與英文原文存在出入。

相關文章

- Users and groups
- umask
- Access Control Lists
- Capabilities

文件系統用權限和屬性來規範系統進程與文件和目錄之間的交互。

警告：權限和屬性設置只能防範來自已經啟動了的當前系統的攻擊。為了防止數據被能物理訪問該機器的人的接觸，必須同時使用磁碟加密.

## 查看權限

使用ls命令的`-l`選項查看為目錄內容設置的權限（或文件模式），例如：

    $ ls -l /path/to/directory

    total 128
    drwxr-xr-x 2 archie users  4096 Jul  5 21:03 Desktop
    drwxr-xr-x 6 archie users  4096 Jul  5 17:37 Documents
    drwxr-xr-x 2 archie users  4096 Jul  5 13:45 Downloads
    -rw-rw-r-- 1 archie users  5120 Jun 27 08:28 customers.ods
    -rw-r--r-- 1 archie users  3339 Jun 27 08:28 todo
    -rwxr-xr-x 1 archie users  2048 Jul  6 12:56 myscript.sh

第一欄是我們必須關注的內容。 以`drwxrwxrwx +`為例，每個字符的含義在下表中說明：

`d` | `rwx` | `rwx` | `rwx` | `+`
文件類型，技術上不屬於其權限。 有關可能值的說明，請參閱 `info ls -n "What information is listed"` 命令的輸出。 | 所有者對文件的權限，如下所述。 | 該組對該文件的權限，如下所述。 | 所有其他用戶對該文件的權限，如下所述。 | 一個指定備用訪問方法是否適用於該文件的字符。 當此字符是空格時，沒有備用訪問方法。 `.`字符表示具有安全上下文的文件，但沒有其他備用訪問方法。 具有任何其他備用訪問方法的文件用`+`字符標記，例如在使用訪問控制列表 (ACL) 的情況下.

權限三元組（也就是上面例子中的`rwx`）可以由以下字符（權限位）構成：

| 字符 | 文件效果 | 目錄效果
--- | --- | --- | ---
讀權限（第一個字符） | `-` | 不能讀取該文件 | 不顯示目錄裡的內容
`r` | 可以讀取該文件 | 能顯示目錄裡的內容
寫權限（第二個字符） | `-` | 不能修改該文件 | 不能修改目錄中的內容
`w` | 可以修改該文件 | 能修改目錄中的內容（創建、重命名或刪除文件或子目錄）；需要同時設置執行權限，否則本權限無效。
執行權限（第三個字符） | `-` | 不能執行該文件 | 無法使用 cd 命令訪問該目錄
`x` | 可以執行該文件 | 能使用 cd 命令訪問該目錄。這是實踐中唯一一個算是可以從父目錄繼承而來的權限。實際上，如果某文件或目錄路徑中的任何一個目錄沒有設置 x 權限， 就算最終訪問的文件或目錄設置了對應的權限也是打不開的。請參考path_resolution(7) 來了解更多。
`s` | 當出現在用戶（所有者）權限三元組時，代表 setuid 位； 當出現在組權限三元組時，代表 setgid 位；不會出現在對其他用戶權限的三元組中；同時意味著設置了 `x` 權限。
`S` | 與 `s` 相同，但是未設置 `x` 權限；普通文件中很少見，並且對於目錄是無效的。
`t` | 粘滯位，只存在於對其他用戶權限的三元組中；同時意味著設置了 `x` 權限。
`T` | 與 `t` 相同，但是未設置 `x` 權限 ；普通文件中很少見。

請參考 `info Coreutils -n "Mode Structure"` 和 chmod(1) 以獲得更詳細的說明。

提示：您可以用 `namei -l path` 命令查看文件或者目錄沿路的權限

### 案例

讓我們用一些案例來解釋說明：

    drwx------ 6 archie archie  4096 Jul  5 17:37 Documents

Archie 具有對 `Document` 目錄的完全訪問權限。它可以列出、創建和重命名或刪除 Documents 中的任何文件，無論其中文件的權限是什麼。而它訪問文件的能力取決於具體文件的權限。

    dr-x------ 6 archie archie  4096 Jul  5 17:37 Documents

Archie 擁有完全訪問權限，但他們不能創建、重命名或刪除任何文件。他們可以列出文件，並且（如果文件的權限允許）可以訪問文檔中的現有文件。

    d-wx------ 6 archie archie  4096 Jul  5 17:37 Documents

Archie 不能在 `files` 目錄中執行 `ls` ，但是如果它知道現有文件的名稱，就可以列出、重命名、刪除或(如果文件的權限允許)訪問該文件。此外，它們還能夠創建新文件。

    d--x------ 6 archie archie  4096 Jul  5 17:37 Documents

Archie 只能夠在文件權限允許的情況下訪問已知的文件。它不能列出目錄中的文件，也無法創建、重命名或者刪除任何文件。

要記得，我們在此介紹的是目錄權限，這與單個文件權限無關。創建一個新文件時，修改的是目錄。這就是為什麼您需要有目錄的寫權限。

接下來我們看一些文件權限方面的例子：

    -rw-r--r-- 1 archie web  5120 Jun 27 08:28 foobar

在這裡，我們可以看到第一個字母不是 `d` 而是 `-`。所以我們知道它是一個文件，而不是一個目錄。接下來，所有者的權限是`rw-`。所有者並沒有擁有全部的三個權限可能很奇怪，但這個文件作為一個文本文件而不是一個可執行文件時，並不需要`x` 權限（但如果它包含 python 代碼之類的內容，那麼它很可能是可執行文件），我們可以用 Gedit、EMACS 等文本編輯器或者 R 之類的軟體來讀取它。該文件的組權限為 `r--` ，因此該組的成員可以讀取文件，但不能以任何方式對其進行寫入/編輯，實際上就是把它設置為只讀。最後是對其他用戶的權限，被設置為與組權限一致，也是只讀。

## 修改權限

chmod 是 Linux 和其他 Unix-like 作業系統中用來修改文件或者目錄權限的命令。

### 以字符形式修改權限

想要修改文件的權限（或者叫訪問模式），請在終端裡使用 chmod 命令。以下是該命令的基本結構：

    chmod who=permissions filename

其中的 `who` 是一個或者多個字母，代表要指定權限的對象，可以為：

- `u`: 擁有該文件的用戶
- `g`: 該文件所屬的用戶組 .
- `o`: 所有其他用戶
- `a`: 以上所有，等效於 `ugo`.

權限和上面 #查看權限所述的相同 (`r`, `w` 和 `x`).

現在看一下使用這個命令的一些示例。假設您對「文檔」目錄進行了嚴格的保護，並希望拒絕除您之外的所有人在其中讀取、寫入和執行(或在本例中是拒絕搜索或查看)的權限。

修改前： `drwxr-xr-x 6 archie web 4096 Jul 5 17:37 Documents`

    $ chmod g= Documents
    $ chmod o= Documents

修改後： `drwx------ 6 archie web 4096 Jul 6 17:32 Documents`

在這裡，因為您想要禁止所有權限，所以不要在 `=` 後面輸入任何內容。如此修改後，除了文件所有者的權限為 `rwx` 之外，其他權限都是 `-`。

您可以使用如下命令來恢復原來的狀態：

再次修改前：`drwx------ 6 archie web 4096 Jul 6 17:32 Documents`

    $ chmod g=rx Documents
    $ chmod o=rx Documents

再次修改後：`drwxr-xr-x 6 archie web 4096 Jul 6 17:32 Documents`

在下一個例子中，您想給組及其他用戶讀取和執行權限，所以您可以在 `=` 後面輸入相應的權限 `r` 和`x`，記得不要帶空格。

您可以在 `who` 的地方輸入多個字母，來同時給多個對象設置權限，如：

    $ chmod go=rx Documents

注意：`chmod` 命令中的 `who` 字母或者權限位（``）字符的順序是無關緊要的。`chmod go=rx file` 和 `chmod og=xr file` 這兩個命令的含義完全相同

接下來我們考慮第二個例子，假設您想讓自己和 `web` 用戶組中的用戶（可能是您的同事）有 `foobar` 這個文件的讀寫權限， 但其他人只能讀取它。那麼操作如下：

修改前： `-rw-r--r-- 1 archie web 5120 Jun 27 08:28 foobar`

    $ chmod g=rw foobar

修改後：`-rw-rw-r-- 1 archie web 5120 Jun 27 08:28 foobar`

這與第一個示例完全相同，但使用的是文件，而不是目錄，並且您授予的是寫入權限（這只是為了給出授予每個權限的示例）。

#### 字符形式的捷徑

chmod 命令允許使用 `+` 或 `-` 而不是`=`從現有集合中添加和減去權限。這與上面的命令不同，後者實質上是重設權限(例如，要將權限從`r--`更改為`rw-` ，您仍然需要在 chmod 命令的`=`之後包含 `r` 和 `w`。如果遺漏了`r` ，那麼在使用`=`重設權限時，它將取消`r`的權限。使用`+`和`-`可以通過添加或刪除當前的權限集來避免這種情況)。

讓我們用 `+` 和 `-` 的方式復現一下前面給組添加寫權限的例子：

修改前： `-rw-r--r-- 1 archie web 5120 Jun 27 08:28 foobar`

    $ chmod g+w foobar

修改後：`-rw-rw-r-- 1 archie web 5120 Jun 27 08:28 foobar`

另一個例子，取消所有用戶和組的寫入權限。

修改前： `-rw-rw-r-- 1 archie web 5120 Jun 27 08:28 foobar`

    $ chmod a-w foobar

修改後： `-r--r--r-- 1 archie web 5120 Jun 27 08:28 foobar`

另一個不同的捷徑是特殊的 `X` 模式：實際上不存在這個模式，但它通常與 `-R` 選項（遞歸）一起使用，以設置只針對目錄的執行權限，而不修改常規文件的權限，例如:

    $ chmod -R a+rX ./data/

#### 複製權限

您可以讓 chmod 把某對象（比如所有者）的權限複製給其他對象（比如組或者所有人）。想要做到這一點，在 `=` 後面不要跟權限（`r`、`w`和`x`），而是輸入另一個 who 字母。比如：

修改前 `-rw-r--r-- 1 archie web 5120 Jun 27 08:28 foobar`

    $ chmod g=u foobar

修改後 `-rw-rw-r-- 1 archie web 5120 Jun 27 08:28 foobar`

這個命令的意思就是「把對組(`g=`)的權限設置為與所有者(`=u`)的權限相同」。請注意，您不能複製一組權限，也不能授予新的權限，以下是錯誤示範，chmod 會報錯：

    $ chmod g=wu foobar

### 數字形式

chmod 也可以用數字來設置權限。

使用數字是另一種方法，它允許您同時編輯所有者、組和其他人的權限，以及setuid、setgid和粘滯位。命令的基本結構如下：

    $ chmod xxx filename

`xxx` 部分是一個三位數，其中的每一位可以是0到7之間的任何數字。第一位數字指所有者的權限，第二位數字指組的權限，而第三位數字指所有其他人的權限。

在這個數字表示法中，權限 `r`、`w`和`x`所對應的數值是:

    r=4
    w=2
    x=1

要得到這個三位數，您要考慮為所有者、組和所有其他人設置哪些權限，然後將其對應的數值累加起來。例如，如果希望授予目錄的所有者讀寫和執行權限，並希望 group 和其他所有人只有讀寫權限，那麼通過計算可以得到如下數值：

- 所有者: `rwx`=4+2+1=7
- 組: `r-x`=4+0+1=5
- 其他人: `r-x`=4+0+1=5

    $ chmod 755 filename

這就相當於使用如下命令：

    $ chmod u=rwx filename
    $ chmod go=rx filename

若要以數字形式查看文件或目錄的現有權限，請使用stat(1)命令：

    $ stat -c %a filename

`%a` 指定以數字形式輸出文件權限。

大多數目錄被設置為 `755` 以允許所有者讀取、寫入和執行，但拒絕被其他所有人寫入；文件通常是`644` 以允許所有者讀取和寫入，但允許其他所有人讀取；請參考最後一個關於不可執行文件缺少`x`權限的說明，此處同理。

為了用實例來說明這一點，我們用數字方式復現一下前面舉過的例子：

修改前：`-rw-r--r-- 1 archie web 5120 Jun 27 08:28 foobar`

    $ chmod 664 foobar

修改後： `-rw-rw-r-- 1 archie web 5120 Jun 27 08:28 foobar`

如果這是一個可執行文件，同時您想向所有者和組授予可執行權限，則權限數字為`774`。或者，如果您希望每個人都只具有讀取權限，則數字將為`444`。將`r`視為4，`w`視為2，以及`x`視為1，這可能是計算`chmod xxx 文件名`的權限數值最簡單的方法。

但還有一種二進制方法，其中每個權限都代表一個二進制數，最後再將其轉換為一個數字。它有點複雜，但為了完整起見，在此也介紹該方法。

對於以下權限組合：

    -rwxrwxr-x

如果您在每個授予的權限下寫1，而在每個未授予的權限下寫0，則結果如下：

    -rwxrwxr-x
     111111101

然後把它當成二進制數進行轉換：

    000=0	    100=4
    001=1	    101=5
    010=2	    110=6
    011=3	    111=7

因此，上述值為775。

如果我們想從組中刪除寫權限：

    -rwxr-xr-x
     111101101

因此，該值將為755，您可以使用 `chmod 755 文件名`刪除可寫權限。無論使用哪種方法，您最終都會得到相同的三位數。使用文本還是數字取決於個人偏好和打字速度。如果您希望將目錄或文件還原為默認權限（例如所有者有讀寫和執行權限，但拒絕其他所有人的寫權限），則使用`chmod 755/644 文件名`可能會更快。但如果您要將權限更改為比較少見的組合，則使用文本方法可能會更簡單、更快，而不是嘗試將其轉換為數字，這可能會導致錯誤。對於只需要偶爾使用chmod的用戶來說，這兩種方法的速度都沒有顯著的差異。

您也可以用數字形式設置`setuid`, `setgid` 和 `sticky` 權限位。

    setuid=4
    setgid=2
    sticky=1

比如 `chmod 2777 filename` 將為每個人設置讀/寫/可執行位，並啟用`setgid`位。

### 批量 chmod

通常，目錄和文件不應具有相同的權限。如果需要批量修改目錄樹，請使用find選擇性地修改其中一個或另一個。

若要只把目錄權限修改為 755：

    $ find directory -type d -exec chmod 755 {} +

若要只把文件權限修改為 644：

    $ find directory -type f -exec chmod 644 {} +

## 修改所有者

chown 能夠修改文件或者目錄的所有者，這在某些情況下會更簡單快捷。

比如，您要使用GParted為備份數據創建一個新分區。Gparted以root身份執行所有操作，因此默認情況下所有內容都屬於root。這一切都很好，但當要向掛載的分區寫入數據時，常規用戶會沒有權限。

    brw-rw---- 1 root disk 8,    9 Jul  6 16:02 sda9
    drwxr-xr-x 5 root root    4096 Jul  6 16:01 Backup

若您所見，`/dev`是由root所有的，而掛載點(`/media/Backup`也是一樣。如果我們要修改掛載點的所有者，您可以執行如下命令：

修改前： `drwxr-xr-x 5 root root 4096 Jul 6 16:01 Backup`

    # chown archie /media/Backup

修改後： `drwxr-xr-x 5 archie root 4096 Jul 6 16:01 Backup`

現在在無需調整權限的情況下，這個分區就可以由新的所有者 archie 寫入了。（作為所有者，它本身就擁有 `rwx` 權限）

注意：

- `chown` 總是會清除 setuid 和 setgid 權限位
- 非 root 用戶不能使用 `chown` 來把他們自己擁有的文件「送給」其他用戶

## 訪問控制列表（ACL）

Access Control Lists 通過允許為任何用戶或組設置對任何文件的權限，為文件系統提供了額外的、更靈活的權限機制。

## Umask

umask 實用程序用於控制文件創建模式掩碼，該掩碼確定了新創建文件的權限位的初始值。

## 文件屬性

除了控制用戶和組讀、寫和執行權限的文件權限之外，還有幾個文件系統支持文件屬性，這些屬性可以進一步自定義允許的文件操作。

警告：默認情況下， cp、rsync 和其他類似的程序不會保留文件屬性

e2fsprogs包 軟體包內有 lsattr(1) 和 chattr(1) 這兩個可以列出和修改文件屬性的工具。

以下是一些有用的屬性，但並非所有的文件系統都支持每個屬性。

- `a` - 僅追加（append only）：文件只能以追加的方式打開。
- `c` - 壓縮（compressed）：為文件啟用文件系統級的壓縮。
- `i` - 不變（immutable）：無法被修改、刪除、重命名或創建指向它的連結。只能由root用戶設置。
- `j` - 數據日誌（data journaling）：為文件的寫入和元數據啟用日誌。
- `m` - 不壓縮（no compression）：為文件禁用文件系統級的壓縮。
- `A` - 禁用atim更新（no atime update）：文件的 atime （訪問時間）將不會被修改。
- `C` - 禁用寫時拷貝（no copy on write）: 對於支持寫時拷貝的文件系統，禁用寫時拷貝。

查看 chattr(1) 以獲得更詳細的文件屬性列表以及它們的作用。

比如，如果您想給某個文件設置不變（immutable）屬性，使用如下命令：

    # chattr +i /path/to/file

要刪除文件上的屬性，只需把 `+` 改為 `-`。

## 擴展屬性

根據 xattr(7)：「擴展屬性是與文件和目錄永久關聯的鍵值對」。有四個擴展屬性類: security、 system、 trust 和 user。

警告：默認情況下，cp、rsync 和其他類似的程序不會保留文件屬性。請參考 #保留擴展屬性.

擴展屬性還用於設置能力（Capabilities）.

### 用戶擴展屬性

用戶擴展屬性可用於存儲有關文件的任意信息，比如：

    $ setfattr -n user.checksum -v "3baf9ebce4c664ca8d9e5f6314fb47fb" foo.txt

使用getfattr來顯示擴展屬性：

    $ getfattr -d foo.txt

    # file: foo.txt
    user.checksum="3baf9ebce4c664ca8d9e5f6314fb47fb"

如果要刪除擴展屬性：

    $ setfattr -x user.checksum foo.txt

### 保留擴展屬性

命令 | 所需的選項
--- | ---
`cp` | `--preserve=mode,ownership,timestamps,xattr`
`mv` | 默認會保留[注 1]
`tar` | 創建tar檔時用 `--xattrs` ，解壓時用 `--xattrs-include='*'`
`bsdtar` | 解壓時用 `-p`
rsync | `--xattrs`

1. ↑ 當目標文件系統不支持擴展屬性時，mv 會靜默地丟棄這些擴展屬性。

要在使用文本編輯器的時候保留擴展屬性，您需要把他們配置為在保存時截斷（truncate）文件而非使用 rename(2).[1]

## 技巧和竅門

### Preserve root

使用 `--preserve-root` 選項來阻止 `chmod` 遞歸地從 `/` 修改文件權限。 這可以防止在系統範圍內刪除可執行位，從而破壞系統。要每次使用此標誌，請在alias中設置它。參見 [2].

## 參見

- wikipedia:Chattr
- Linux 文件權限的困惑
- Linux 文件權限的困惑第二部分
- wikipedia:Extended file attributes#Linux
- 擴展屬性：好，不太好，壞。
- 在 Linux 中備份和恢復文件權限
- 為什麼 「chmod -R 777 /」 具有破壞性？
- Unix 中用戶私有組的方式和原因

分類：​

- 文件系統
- 命令行

文件權限與屬性
新增話題