一、前言 ======== 本文主要說明Linux下普通文件及目錄的存取權限設置。本文是為稍具基礎的初學者寫的(我也是beginner),如 果您能夠理解如下幾行'ls -l'命令的輸出含義(注意下面標注^的位),那您就沒有必要讀本文了——別浪費時 間看對你沒用的東西,時間是最寶貴的! -r-sr-xr-x 1 root bin 26975 Jun 24 1999 01:32 /usr/bin/passwd-----------1.1 ^ -rwxrwSr-x 1 zyd zyd 12506 Oct 29 10:27 test_euid-----------------------1.2 ^ drwxrwxrwt 5 root root 1024 Nov 1 17:17 01;34 /tmp----------------------1.3 ^^^^ ^ ^ -rwxr-xr-x 2 zyd zyd 32506 Oct 19 10:20 hard_link-----------------------1.4 ^ lrwxr-xr-x 1 zyd zyd 1 Oct 23 10:40 sym_link->/tmp/sym_target-----------1.5 ^ ^^^^^^^^^^^^^^^ 二、'ls -l'命令輸出格式簡介 =========================== 'ls -l'命令以長格式顯示文件列表,其各字段含義如下: lrwxr-xr-x 1 zyd users 15 Oct 23 10:40 sym_link->/tmp/sym_target _________ ___ _____ ____________ ________ _______________ +--符號連接(s_link) +-----文件名(name) +----文件最後更改時間(time) +------------以字節計的文件長度(size) +----------文件屬組(group) +--------------------文件屬主(user) +-------連接數位(count) +-------文件模式位(mode),占9位 +------------文件類型位(type),占一位 以上9個字段中除了s_link外,其他字段對不同文件和目錄都應該有。其中user、group、time和name的含義自 明,本文就不再介紹,其它字段將分專題小節在本文介紹。 三、文件類型(type) Linux支持的文件類型主要包括一下7類,箭頭右面的字符就是相應的文件類型位標志: 1、普通文件========>- 2、目錄文件========>d 3、符號連接========>l 4、字符設備文件====>c 5、塊設備文件======>b 6、命名管道FIFO 7、套接口socket 其中FIFO和socket超出了本文的范疇,不做介紹。其它文件簡單解釋如下: 1、普通文件:就是普通文件(廢話!),你用'vi myfile'建立的myfile就是普通文件,比如可執行二進制代碼 文件、script腳本文件、ASCII文本文件、數據文件、配置文件......就解釋到這樣行嗎? 2、目錄文件:目錄可以理解成放其它文件和/或其它目錄的容器,是一種特殊文件,其內容由目錄項組成,每個 目錄項主要包括兩部分內容:文件名name和索引節點號inode,兩者和起來稱為連接,我們將在下小節對inode 進行更詳細的介紹。 3、設備文件:不知道諸位是否有使用DOS的經驗,如果我們的機器只有三個DOS系統文件IO.SYS, MSDOS.SYS, COMMAND.COM,而你需要編輯一份英文文檔,日後再通過打印機輸出,你能怎麼辦? COPY CON MYDOC.TXT ;在此輸入文檔內容 ^+D ;結束存盤 COPY MYDOC.TXT > PRN ;打印文檔 如果你熟悉這個過程,那你就已經理解設備文件了。以上的CON和PRN分別是DOS定義的兩個設備文件,分別對應 終端和並行打印口。這種設計使我們不必了解設備使用的具體硬件細節,按使用普通文件相同的方法來使用外部 設備。 Linux下的設備文件分為三大類:字符設備、塊設備和網絡設備,要想准確區別它們可能需要單獨寫一篇更臭更 長的文章,大致情況是:字符設備是直接讀取的,不使用緩沖區,象串行口、終端等;而塊設備都是通過緩沖區 進行讀取的,並且每次只能讀取一定數量的塊,比如磁盤每次至少要讀取一個扇區(如512字節),塊設備可以實 現隨機讀寫;網絡設備即前面提到的socket,因為我還不很熟悉,就不亂說了。設備文件一般都保存在/dev目 錄下,諸位可以用ls -l命令看看都有什麼?反正本文的重點在於介紹普通文件和目錄,設備文件不是重點,所 以就只介紹到這裡。 四、索引節點、硬連接和連接計數 ============================== 1、索引節點inode: Linux為每個文件分配一個稱為索引節點的號碼inode,可以將inode簡單理解成一個指針,它永遠指向本文件的 具體存儲位置。系統是通過索引節點(而不是文件名)來定位每一個文件。例如: 假設我們在硬盤當前目錄下建立了一個名為mytext文本文件,其內容只有一行: This is my file. 當然這行文字一定是存儲在磁盤數據區某個具體位置裡(物理上要通過磁頭號、柱面號和扇區號來描述,在本例 中假設分別是1、20、30)。 假設其inode是262457,那麼系統通過一段標准程序,就能將這個inode轉換成存放此文件的具體物理地址(1磁 頭、20柱面、30扇區),最終讀出文件的內容:“This is my file.” 所以inode是指向一個文件數據區的指針號碼,一個inode對應著系統中唯一的一片物理數據區,而位於兩個不 同物理數據區的文件必定分別對應著兩個不同的inode號碼。 文件拷貝命令: # cp /home/zyd/mytext newfile 在當前工作目錄建立了一個新文件newfile,其實際操作主要包括如下三步: 1、在當前目錄中增加一個目錄項,其文件名域填入newfile,並分配了一個新的inode,假設是262456。 2、將原文件(在1磁頭、20柱面、30扇區)的內容復制了一份到新的空閒物理塊(假設是1磁頭、20柱面、31扇 區)。 3、填寫一些其他關鍵信息,使系統通過這些信息及inode號碼可以完成物理地址的轉換。 所以文件復制要分配新的inode和新的數據區,雖然兩個文件的內容是一樣的。 2、硬連接hardlink: 我們實際使用文件時一般是通過文件名來引用的。通過上面的討論,我們知道:1個inode號碼肯定和一片完全 屬於一個文件的數據區一一對應。那麼一個文件系統中兩個或更多個不同的文件名能否對應同一個文件呢?答案 是肯定的。我們知道inode號碼是記錄在文件名對應的目錄項中的,我們可以使兩個或多個文件的目錄項具有相 同的inode值,實際上就使它們對應著同一個文件。有幾個目錄項具有相同的inode號,我們就說這個文件有幾 個硬連接(hardlink),對於普通文件,ls -l命令的連接計數count域的數值就是本文件擁有的硬連接數。硬連 接可以通過ln命令建立,例如: # ln /home/zyd/mytext hardlink_mytext 就建立了一個新的文件hardlink_mytext,這個文件的inode同樣是262457。建立硬連接實際上只是增加了一個 目錄項,但並復制文件數據區,原文件的數據區由兩個文件共享。這一方面能夠節約大量磁盤空間,同時可以保 證兩個文件能同步更新。 'ls -il'可以顯示文件的inode(在下面最左邊): 262456 -rw-rw-r-- 1 zyd zyd 17 Nov 3 14:52 newfile 262457 -rw-rw-r-- 2 zyd zyd 17 Nov 3 14:50 hardlink_mytext 262457 -rw-rw-r-- 2 zyd zyd 17 Nov 3 14:50 mytext 3、連接計數count: 前面我們介紹了,文件的連接計數域表明本系統中共有幾個文件目錄項的inode和本文件相同,也就是本文件共 有幾個硬連接。如上面的例子中hardlink_mytext和mytext文件的count值都是2。 那麼對於目錄,其count域的含義是什麼呢?目錄的count同樣表示共有多少個目錄項指向此目錄,不過要詳細 說明必須進一步解釋VFS文件系統的結構,為簡單起見,只要這樣理解就行了:(count-2)等於本目錄包含的直 接子目錄數(就是只包括兒子,不包括孫子啦!)。例如:如果一個目錄/abc的count域為5,那麼 /abc目錄一定包含3個子目錄。 至此我們已經介紹了普通文件、目錄文件、設備文件、硬連接、連接計數、索引節點等非常重要的概念。 4、進一步說明: 硬連接文件實際上並不是一種新的文件類型,兩個文件互為對方的硬連接。它們應該都是普通文件(誰能告訴 我:其它類型的文件可以硬連接嗎?)。兩個文件除了名稱或/和文件目錄不同外,其它部分完全相同,更改了一 個文件,另一個的文件長度、內容、更改時間等都將相應發生變化,更改了一個文件的權限位mode,另一個也會 發生同樣的變化。 注意連接計數字段count,互為硬連接的兩個文件的count值都是2,表明有兩個inode指向同一文件的inode。 當我們刪除其中一個文件時,系統首先將(count-1)->count,如果結果是零,就將其目錄項和數據區都刪除, 否則只將本目錄項刪除,數據區仍然保留,仍然可以通過另外的文件名訪問。根據這個特性,可以通過為重要的 文件建立硬連接的方法來防止其被誤刪除。 一個文件系統允許的inode節點數是有限的,如果文件數量太多,即使每個文件都是0字節的空文件,系統最終 也會因為節點空間耗盡而不能再創建文件。所以當發現不能建立文件時首先要考慮硬盤數據區是否還有空間(可 通過du命令),其次還得檢查節點空間。 互為硬連接的多個文件必須位於同一個文件系統上。根設備及任何一個需要mount才能掛接進來的分區、軟盤、 NFS、光驅等都是一個獨立的文件系統,每個文件系統有一個相應的設備號,不同文件系統中具有相同inode節 點的文件間沒有任何聯系。系統則通過設備號和inode號的組合唯一確定一個文件。 Linux之所以能支持多種文件系統,其實是由於Linux提供了一個虛擬文件系統VFS,VFS作為實際文件系統的上 層軟件,掩蓋了實際文件系統底層的具體結構差異,為系統訪問位於不同文件系統的文件提供了一個統一的接 口。實際上許多文件系統並不具備inode結構,其目錄結構也和以上的討論不同,但通過VFS,系統均為其提供 了虛擬一致的inode和目錄項結構。所以,'ls -il'命令實際顯示的inode應該是VFS inode,也就是說, inode是存在於內存中的數據結構,而不一定是實際的硬盤結構。但為Linux量身定做的ext2文件系統具備實際 的inode和連接型目錄項結構,所以,對於ext2文件系統,可以認為我們上面討論的關於硬連接的概念是完全正 確的。 本節最後兩段的說明如果您暫時理解不了也沒關系,隨著學習的深入,慢慢就能理解了。 五、符號連接 ============ 不同文件系統中的文件不能建立硬連接,但可以通過符號連接進行同步。符號連接是一種獨立的文件類型,它有 自己的數據區,但數據區的內容只是一個被它指向的文件的路徑名。前言那節的例子1.5說明文件sym_link是一 個指向/tmp/sym_target文件的符號連接,如果我們cat sym_link,系統自動將它指向的文件打開顯示而不是 顯示sym_link文件本身,注意sym_link的文件長度是15,正是字符串/tmp/sym_target的長度。建立符號連接 和建立硬連接一樣使用ln命令,不過要加入'-s'選項: ln -s /home/zyd/file_system/mytext my_sym_link # ls -li my_sym_link 262458 lrwxrwxrwx 1 zyd zyd 28 Nov 3 14:55 my_sym_link -> /home/zyd/file_system/mytext 思考題:建立符號連接時一般都要輸入目標文件的絕對路徑,為什麼? (提示:假設我們想讓用戶在任意當前目錄都能執行/usr/local/my_bin/myproc而運行如下命令: # cd /usr/local/bin # ln -s ../my_bin/myproc myproc) 六、文件模式位mode ================== 通過chmod命令可以改變用戶對相應文件的存取權限。 Linux系統用一個16位的字來存儲每個文件的type和mode,其中高4位通過組合來決定文件的type,它是在文件 創建時寫入的,用戶不能更改。下面介紹後面的12位模式位 bit11 10 9 8 7 6 5 4 3 2 1 0 -------------------------------------- X X X X X X X X X X X X -------------------------------------- mode r w x r w x r w x 將這12位分成4組,高位組(9,10,11位)每位都有特殊的含義,下面將具體說明。此高位組(6,7,8位)決定文件 屬主擁有的權限,再下一組決定文件屬組成員對此文件擁有的權限,最低位組決定除了屬主及屬組以外的用戶擁 有的對此文件操作的權限。 較低3組中每組從最低位到最高位分別是執行位、改寫位和讀取位,哪位置1表示有相關權限。例如第6位是1表示 屬主可以執行此文件,第4位是1同組其他用戶可以改寫此文件,第2位是1表示其它用戶可以讀此文件。每組的3 位構成一位8進制數,可以將各權限位的組合通過3位8進制表示,例如: 111 101 100表示成754,則命令: chmod 754 filename使文件的屬主能讀、寫和執行filename文件,本組的其他用戶可以讀和執行此文件,但不 能修改。其他用戶則只能讀該文件。 第11位是SUID位,第10位是SGID位,第9位是粘附位。 如果某個可執行文件設置了SUID位,則此文件運行時的進程將具備和此文件屬主相同的權限。 /usr/bin/passwd設置了SUID位且其屬主是root,則任何用戶運行它時,其進程就具備了root權限,這就是為 什麼普通用戶也可以通過passwd命令更改自己的登陸口令的原因(實際就是改變/etc/shadow文件,只有root有 權讀寫此文件).具備SUID位且屬主可執行,則屬主執行位顯示s來代替沒有SUID位的x,如果屬主不能執行,則 顯示為大寫的S。 SGID和SUID含義相對應。設置SGID位且屬組可執行,則屬組執行位改成s顯示,否則以S顯示。 粘附位根據其他用戶是否可執行分別在ls -l時在其他用戶執行位上顯示成t或T。對於可執行文件,設置了粘附 位可以使其第一次運行後在交換分區swap中保留正文的副本,由於交換分區的文件是連續存放的,所以下次運行 時能較快調入內存。對於現代文件系統來說,這一功能已經沒有什麼實際意義了。 如果對一個目錄設置了粘附位,則只有對於該目錄具有寫許可權的用戶且滿足如下三個條件之一,才能刪除或更 名該目錄下的文件: 1、超級用戶root。 2、此目錄的擁有者。 3、擁有要被刪除或更改名字的文件。 這一特性被Linux使用到了/tmp目錄上:任何人都可以使用該目錄存儲文件,但只有文件所有者和root可以刪除 或更名文件。 最後要談的是目錄的讀、寫和執行位的准確含義 初學者常常對目錄的權限位理解得似是而非,原因主要在於對文件系統的確切結構不理解。 r表示讀目錄,w表示寫目錄,而x表示搜索目錄(注意不是執行目錄) 我們通過以上討論已經知道目錄實際是一種特殊文件,它由目錄項構成,每個目錄項包括該目錄下一個文件的文 件名和inode。所以讀權限就是讀目錄項的權限,因此獲得此目錄所包含的文件名列表。同樣寫目錄權限就是更 改目錄目錄文件(增加、減少和更名目錄項),實際就是能否在該目錄建立、刪除文件和為文件改名。搜索權限通 俗點可以理解為進入目錄對文件內容進行操作的權限,包括打開文件、獲取文件的進一步詳細信息等權力。更通 俗點,我們可以將目錄比喻為盛藥的盒子,我們在一個大藥盒(根目錄)上貼上叫“藥品”的標簽(目錄名),下面 列著“青霉素”和“感冒藥”(目錄項),擁有x權限相當於有打開這個盒子的鑰匙。如果我們擁有鑰匙,就能打 開這個盒子(擁有根目錄的x權限,可以進入),打開後發現裡面還有一個加鎖的盒子貼有“感冒藥”標簽(子目 錄),下面列著“感冒通”、“感康”......,另外還有一個藥瓶裡面裝有消炎藥青霉素(文件)。 如果我們需要服用“青霉素”(相當於打開根目錄下的文件),則我們必須擁有開大箱子的鑰匙(根目錄x權限)和 吃藥的權力(相應文件權限),但如果我們需要服用“感康”,則必須還有下一把鑰匙。目錄讀權限相當於我們是 否識字,寫權限相當於我們是否擁有一只筆。只要識字,我們沒有任何鑰匙也能大致了解大箱子內有什麼,但無 法了解小盒子裡有些什麼具體藥品。如果需要了解就必須首先能打開大箱子。如果我們要向大箱子內放入一種新 藥或拿出一種藥品(相當於在根目錄內創建、刪除文件),我們首先必須能進入大箱子(x),然後有筆(w)能相應 更改大箱子的標簽。 有了以上的比喻,下面進行正式說明: 1、當我們打開任何文件時(也就是我們的命令中包含最終文件名時),對該文件名的絕對路徑中的每個目錄均必 須擁有x搜索權限。也只有擁有了x權限,才能用cd命令進入該目錄。 2、讀權限允許我們通過ls命令獲得該目錄的文件名列表,但前提仍然是必須對該目錄的所有上級目錄擁有x權限 (想想藥盒的故事)。 3、在滿足目錄權限的前提下,最終對文件的讀、寫、執行取決於文件權限。 4、只要你擁有一個目錄的寫權限及其所有上層目錄的搜索權限,你就能在該目錄建立文件和刪除文件,即使這 個文件不歸你所有!!! 5、超級用戶可以超越大多數文件權限的檢查。 思考題: 1、為什麼目錄建立的默認權限是rwxr-xr-x? 2、假設在你的當前目錄下有一個子目錄test,你擁有讀和寫權限,沒有搜索權限,如下命令哪些能夠成功執 行?為什麼? ls test ls -l test cd test cp /etc/passwd ./test/newpasswd del test/new_file ln test/new_file up_file 七、更改文件模式mode ==================== 更改文件模式可以通過chmod命令進行,我們將mode的低12位每3位一組組成4位8進制數,被設置權限的位為1, 否則為0,作為chmod的參數之一,後面跟需要更改權限的文件名列表,例如: # chmod 4752 this.file 設置了this.file的SUID位(4),文件屬主可以讀、寫和執行(7)、同組其他用戶可以讀和執行,不能更改(5)、 其他用戶只能改寫、不能讀和執行(2)——哪位真的這樣設置了權限位,肯定腦筋有點問題:) (全文完) ======================================== 一點說明 ====================================== 我接觸Linux還不滿1年,UNIX則從未見過,又剛剛學習編程,文中錯誤和不當之處難免,歡迎各位指正。 Julian Chang
[email protected] 2000年11月20日