阿旺的 Linux 開竅手冊







基礎篇
進階篇
補腦篇
版權所有,引用請註明出處

 基礎篇

Chapter 5 : 檔案操作和權限

5.0 檔案基本操作
       連結檔
           符號連結
           硬連結
       ln 建立檔案連結
       cp 檔案複製
       rm 檔案刪除
       mv 檔案搬移
       〝\〞 跳脫字元
5.1 萬用字元
       rename 大量檔案更名
5.2 檔案擁有者和權限
       擁有者類別 (ownership)
       權限 (permission)
       目錄的權限
       特殊權限
           Sticky Bit
           SGID (Set Group ID bit)
           SUID (Set User ID Bit)
       chmod 變更檔案的權限
           數字表示法
           符號表示法
       連結檔的權限
       umask 改變預設檔案權限
5.3 檔案屬性
       chattr 變更檔案屬性
       lsattr 顯示檔案屬性





















檔案操作和權限

5.0 檔案基本操作
檔案的基本操作不外乎複製、搬移、刪除、和重新命名等,但這些操作的檔案或目錄有時並非檔案〝本尊〞,而是其〝分身〞即所謂的〝連結檔〞(Linking files),所以有必要先了解〝連結檔〞才能了解後續的介紹,所以就由〝連結檔〞開始吧。

連結檔
連結檔有點類似 Windows 的〝捷徑〞(Shortcut),但不完全相同 ,Windows 中的〝捷徑〞是一個實際會佔空間的檔案,副檔名為〝lnk〞。捷徑檔〝.lnk〞不直接記錄內容而是記錄某檔案的路徑,其目的是可大幅節省儲存空間。例如某一檔案或目錄有 100MB,但其捷徑檔〝lnk〞的大小應都小於 0.5K ,因捷徑檔〝lnk〞只記錄來源檔案的路徑和其他屬性(如是執行檔,其屬性可能還有執行時的啟動參數和啟動位置等內容)。

Linux 的檔案系統(Filesystem)標準為 ext2 ext3,其 filesystem 檔案的資訊記錄在 inode 而內容記錄在 block 內, 而連結檔可用 inode 來記錄來源檔的路徑不一定會動用到 block ,所以 Linux 的連結檔不一不定會像 Winodws 的〝捷徑〞一般會佔實際的空間。

Linux 的連結檔有兩種,一叫〝符號連結〞另一是〝硬連結〞,差別如下。 ln 建立檔案連結
知道了連結檔,來實際觀察和練習一下,建立檔案連結指令 ln (link)用法如下:

語法:ln [-otpiton][--option] source target_link_file
指令名稱/功能/命令使用者 選項 功能
ln/
(link)建立連結/
Any
-s 建立符號連結(Symbolic Link),如無此選項預設為硬連結 (Hard Link)
-b 如要建立的連結檔已存在,會先自動備份已存在的檔案(備份檔字尾加〝~〞)
-f 如要建立的連結檔已存在,覆蓋舊檔
--help 指令自帶說明


例: (符號連結)
$ ls -lgGh /etc/services ←查看一下檔案〝/etc/services〞的檔案大小
-rw-r--r-- 1 354K 2007-04-18 16:40 /etc/services ←檔案大小為 354K byte
$ ln -s /etc/services s_link ←建立符號連結檔〝s_link〞連結到〝/etc/services〞
$ ls -lgGh s_link ←查看一下符號連結檔〝s_link〞的大小
lrwxrwxrwx 1 13 2011-09-13 13:51 s_link -> /etc/services ←其符號連結只佔 13 byte

上例中.如讀或寫符號連結檔〝s_link〞就等於讀或寫來源檔〝/etc/services〞,但檔案大小比來源檔小多了只有 13 byte。如果細心點可能會發現到符號連結檔的大小剛好是〝路徑的字元數〞,所以符號連結檔事實上只記錄來源檔的路徑,所以 ln 如用相對路徑就可能會有延伸的問題,我們來實驗一下。

例:(符號連結檔相對/絕對路徑實驗)
$ cd ~ ←cd 到家目錄來實驗
$ echo '12345' > source ←建立一檔案〝source〞內容為〝12345〞
$ ln -sf source s_link ←建立符號連結檔〝s_link〞連結到工作目錄內的檔案〝source〞
$ cat s_link ←驗證一下軟連結檔〝s_link〞內容和〝source〞是否相同
12345
$ mv s_link /tmp ←實驗一下將軟連結檔〝s_link〞移到目錄 /tmp 下
$ cat /tmp/s_link ←驗證一下軟連結檔〝s_link〞內容
cat: /tmp/s_link: No such file or directory ←找不到檔案

$ ln -sf ~/source s_link ←用絕對路徑再實驗上述步驟
$ mv -f s_link /tmp
$ cat /tmp/s_link ←驗證一下
12345 ←如用絕對路徑,把軟連結檔移到其他目錄就不會有問題了
$ rm ~/source ←把來源檔殺掉
$ cat /tmp/s_link ←驗證一下來源檔不見了,軟連結檔會如何?
cat: /tmp/s_link: No such file or directory ←找不到檔案了

由以上的實驗可知操作符號連結最好用絕對路徑,且符號連結的來源檔如不小心被殺掉了,空有符號連結檔也沒用。

符號連結的來源檔不只可連結檔案,目錄,甚至可跨越不同檔案系統哦。

例:(符號連結到目錄)
$ ln -s /etc s_link2dir ←建立符號連結檔〝s_link2dir〞連結到目錄〝/etc〞
$ ls -lgG s_link2dir ←用指令 ls 看一下〝s_link2dir〞有無連結到目錄〝/etc〞
lrwxrwxrwx 1 4 2011-09-13 16:49 s_link_dir -> /etc
$ cd s_link2dir ←看一下可不可以進入符號連結的目錄

實驗了符號連結(symbolic link),現在來實驗硬連結(hard link)。

例:
$ cp /etc/services /tmp ←複製 /etc/services 到 /tmp 目錄下準備作為實驗的來源檔
$ ln /tmp/services h_link ←建立硬連檔〝h_link〞硬連結到來源檔〝/tmp/services〞(ln 沒選項為硬連結)
$ ls -li /tmp/services h_link ←把兩個檔案列出看看
1880233 -rw-r--r-- 2 aaa aaa 362047 2011-09-13 17:09 h_link ←兩個檔案除檔名外都一樣
(上面故意用綠字 mark 為 inode 編號,紅字為 link 數)

1880233 -rw-r--r-- 2 aaa aaa 362047 2011-09-13 17:09 /tmp/services

$ rm /tmp/services ←把來源檔殺掉看看
$ ls -li h_link ←列出硬連結檔看看有無影響
1880233 -rw-r--r-- 1 aaa aaa 362047 2011-09-13 17:09 h_link ←來源檔殺掉了,不會影響硬連結檔(但 link 數變 1)
$ cat h_link ←驗證一下來源檔不見了,硬連結檔可否讀出?

一個檔案系統(以 Linux ext2/ext3 而言),不同的檔案其 inode 會有不同的編號,如果 inode 編號相同就是同一檔案。如果多一個硬連結,其 link 數會加一,如前所言硬連結檔既是本尊也是分身,所以只要其一沒被刪除,資料都安全的故安全性較佳,但命缺點為:不可連結目錄也不可跨越不同檔案系統。

cp 檔案複製
Linux 檔案複製指令 cp (copy),基礎用法很簡易,基本上為 cp 來源檔 目的檔 cp 來源檔案1 來源檔案n 目的路徑 (把一到多個檔案複製到目錄內)cp 來源目錄 目的目錄,進一步用法如下:

語法:cp [-otpiton][--option] source traget
指令名稱/功能/命令使用者 選項 功能
cp/
(copy)檔案複製/
Any
-a 完全複製(包含其檔案擁有者,連結,目錄,時間)同等 -dpR (常用於備份)
-b 如目的檔已存在會先自動備份已存在的檔案(備份檔字尾加〝~〞)
-d 如來源為符號連結檔,複製後的檔也為符號連結檔
-f 如複製的檔案已存在,不詢問直接覆蓋舊檔
-i 如複製的檔案已存在,覆蓋舊檔之前會要求詢問
-l 硬連結取代複製
-p 複製檔案時連其檔案擁有者,時間戳記,權限也一併複製
-r 遞回(recursive)複製,將來源目錄下所有的檔案及子目錄一併複製
-R 同 -r
-s 符號連結取代複製
-S字串 同 -b 但可指定備份檔字尾字串
-u 更新(只複製來源檔 mtime 時間比目的檔 mtime 時間新或目的地沒有的檔案)
-v 顯示複製過程
--help 指令自帶說明

例:
$ cp file1 file2 ←將 file1 複製到 file2
$ cp /dev/null file1 ←將 file1 內容清空
$ cp /dir/file ./ ←將檔案 /dir/file 複製到工作目錄
$ cp file ../ ←將工作目錄的檔案複製到其父目錄
$ cp -r dir1/ dir2/ ←將來源目錄 dir1 下所有的檔案及子目錄一併複製到目錄 dir2 內
$ cp file1 file2 file3 dir ←如果來源檔不只一個,目的一定要為目錄,此例為將 file1~file3 複製到目錄 dir 內
$ cp -b /dir/file ./ ←如果工作目錄 file 已存在,file 會先備份為 file~ 再進行複製的動作
$ cp -S'_backuped' file1 file2 ←如果 file2 已存在,file2 會先備份為 file2_backuped 再進行複製的動作(指定備份檔字尾字串)
$ cp -auv dir1/ dir2/ ←更新目錄 dir2 (來源為 dir1)且顯示更新的過程(此例時常用於備份)
$ cp -s file1 file2 ←同等於指令 ln -s file1 file2,建立符號連結檔 file2
$ cp -l file1 file2 ←同等於指令 ln file1 file2, 建立硬連結
$ cp -i file1 file2 ←將 file1 複製為 file2 但如 file2 已存在,覆蓋舊檔之前會要求詢問

Linux 的 cp 指令有一特色,即如果權限許可,不管來源檔擁有者群組屬誰,複製過來的檔案的擁有者和群組會變操作者所有,當然其用意是讓操作者可以完全操控複製過來的檔案.如要維持原屬性,就要用 cp -acp -p

例:
$ ls -l /etc/fstab ←查看 /etc/fstab 的擁有者和群組
-rw-r--r-- 1 root root 608 2011-09-16 00:21 /etc/fstab ←擁有者,群組,兩者目前都屬〝root〞所有
$ cp /etc/fstab ./ ←複製 /etc/fstab 到工作目錄
$ ls -l fstab ←查看工作目錄檔案 fstab 的擁有者和群組
-rw-r--r-- 1 aaa aaa 608 2012-02-10 12:50 fstab ←擁有者/群組變建立者所有

上例中就算加選項 cp -p 也無法把擁有者和群組〝root〞複製過來,因其權限不足。反之如用 root 登入操作 cp -p ,因權限無限大就可把完全複製任何的擁有者和群組。

另外複製指令 cp 如來源為檔為符號連結檔,目的檔將不再是符號連結檔(而是直接複製其目的檔),如要保留目的檔也為符號連結檔就用選項 cp -d,而 cp -a 等於 cp -d -p -R 三個選項加起來的功能,即完全複製,時常用來備份檔案。

如果用 cp 於日常的備份,但檔案很大又很多,每個檔案都複製常浪費許多時間,用選項〝-u〞可節省許多的時間。因可根據 mtime 時間來判斷檔案有無更新,或有無新的檔案來判斷是否要複製。

另外建議養成好的指令操作習慣,如操作的為目錄,目錄的字尾最好加〝/〞以區別是目錄。例如將目錄 dir1 複製到目錄 dir2, 寫成 cp -r dir1 dir2 即可,但用 cp -r dir1/ dir2/ 更清楚明白操作的為目錄。事實上目錄的標準寫法後面是要加〝/〞只是大部分的人都省略,但有些應用,目錄後面非加〝/〞不可;如 ls -d */ 為列出工作目錄內還有那些目錄但不列出檔案。

rm 檔案刪除
Linux 刪除檔案指令 rm (remove),基本用法為 rm 檔案1 檔案n, 進階用法如下:

語法:cp [-otpiton][--option] file/directory
指令名稱/功能/命令使用者 選項 功能
rm/
(remove)刪除檔案/
Any
-f 不詢問直接刪除檔案
-i 刪除檔案之前會要求詢問
-r 遞回(recursive)刪除,將來源目錄下所有的檔案及子目錄一併刪除
-R 同 -r
-v 顯示刪除過程
--help 指令自帶說明

rm 刪除檔案指令也可刪除目錄,如用 rm -fr dir/ 來刪除目錄連問都不問就把整個目錄都殺光。所以 rm 是很危險的指令,所以建議殺目錄用專屬的殺目錄指令 rmdir 比較安全。

例:
$ rm file ←刪除檔案 file
$ rm 'file 1' ←刪除檔案〝file 1〞(如檔名有空格要用引號括起來)
$ rm file1 file2 file3 ←刪除檔案可連殺
$ rm -ri dir/ ←刪除目錄和目錄內的所有檔案,並要求每個檔案詢問
$ rm -rf dir ←不詢問直接刪除目錄和目錄內的所有檔案
$ rm ./-10degree ←刪除檔案〝-10degree〞

最後一個例子比較要注意一下,如檔案的第一個字用比較奇怪的字元,如例子中的檔案〝-10degree〞,但〝-〞又會被誤判為選項,所以要用代表工作目錄的〝./〞來隔開,但還是不太建議檔名太標新立異。

mv 檔案搬移
檔案搬移指令 mv (move) 和檔案複製指令 cp 用法和選項和都很類似,差別只是檔案搬移 mv 會把來源的檔案殺掉。且 mv 沒有〝-r〞或〝-R〞目錄遞回的選項,因如 mv 用於搬移目錄,已包含目錄內的檔案和子目錄一起搬移,mv 用法如下。

語法:mv [-otpiton][--option] source target
指令名稱/功能/命令使用者 選項 功能
mv/
(move)檔案搬移/
Any
-b 如目的檔案已存在,會先自動備份已存在的檔案(備份檔字尾加〝~〞)
-f 如目的檔案已存在,不詢問直接覆蓋舊檔
-i 如目的檔案已存在,覆蓋舊檔之前會要求詢問
-S字串 同 -b 但可指定備份檔字尾字串
-u 只搬移更新檔(只搬移來源檔 mtime 時間比目的檔 mtime 時間新或目的地沒有的檔案)
-v 顯示搬移過程
--help 指令自帶說明

例:
$ mv file1 file2 ←將 file1 搬移到 file2,此例同等於將 file1 更名為 file2
$ mv dir1/ dir2/ ←將目錄 dir1(包含 dir1 內所有的檔案和子目錄)搬移到 dir2,此例同等於目錄更名
$ mv -i file ../ ←將 file1 搬移到其父目錄,如目地檔存在並要求詢問
$ mv -b file dir/ ←將 file1 搬移到目錄 dir,如目地檔存在,覆蓋之前先備份(備份檔字尾加〝~〞)

第一個例子 mv file1 file2 也是 mv 主要的用法之一,用於更名。

〝\〞 跳脫字元
跳脫字元〝\〞(escape characters)用意為因語法衝突,故不得已暫時脫離某特殊字元(、/、"、{、? 等)原預設的功能或轉變功能,例如想在螢幕顯示〝I'm happy and I'm a student〞用 echo 指令寫成 echo I'm happy and I'm a student 會引起錯誤的輸出,因單引號〝'〞或雙引號〝'〞是括入字串的意思,故如要正確的輸出可加跳脫字元〝\〞使暫時脫離引號原有的功能而寫成 echo I\'m happy and I\'m a student

例:(暫時脫離某特殊字元原預設的功能)
$ echo > "fileA" ←製造個檔案〝 "fileA" 〞
$ echo > ""fileB"" ←製造個檔案〝 ""fileB"" 〞
$ ls ←確認一下
fileA      fileB ←檔案的引號不見了?
$ echo > \"fileC\" ←加跳脫字元再製造個檔案〝 "fileC" 〞看看
$ ls
fileA      fileB      "fileC" ←〝fileC〞有引號吔

$ rm \"fileC\" ←加跳脫字元才可操作語法衝突的檔案


例:(轉變功能)
echo -e 'I\x27m a student' ←加跳脫字元使轉變功能為 ASCII 碼(ASCII 碼 27HEX為單引號)
I'm a student

\ls  ←指令之前加跳脫字元代表〝除去別名〞,(ls 輸出就不會五顏六色)


^ back on top ^




5.1 萬用字元

萬用字元(Wildcard characters)和管線重定向是 Linux 指令的魔法師,可讓文字界面的威力由砲彈昇華為核彈,是圖形操作界面難以望其項背。

萬用字元主要的目的是在匹配檔名,萬用字元中的〝字元〞(Character)是以 ASCII code 所定義的英文字母或數字或符號稱為一個字元,例如英文字母〝A〞(ASCII=65)為一個字元。 一個以上的字元可組成一字串(String),例如〝XYZ〞為一字串。

傳統的檔名皆以 ASCII code 來編碼,所以善用萬用字元可減化檔案的操作,因 Linux shell 本身就能解讀萬用字元,故幾乎任何和檔案有關的指令皆可配合萬用字元,檔名有用到萬用字元來匹配叫〝globbing patterns〞或簡稱〝glob〞,常用的用法如下:
萬用字元雖好用,但也有其肓點時常困惑使用者,那就就遇到隱藏檔(〝.〞開頭的檔案)常會無效。舉例來說〝/tmp〞目錄內可能有許多的隱藏檔,但我想把此目錄內的檔案和目錄都清空,用 rm -fr * 郤無法把隱藏檔刪除。最主要原因為〝*〞代表任何東西,所以代表 rm -fr * 連同代表其目錄本身的〝.〞和其上層目錄的〝..〞也一起刪除,但這應不是我們期望的,所以只好放過〝.〞開頭的檔案。

當然其他指令如 ls *cp * ~/ 也會遇到類似的問題,解決辦法之一為用〝.[^.]*〞來匹配以〝.〞開頭的隱藏檔但又可排除〝.〞和〝..〞,如 rm -fr .[^.]* 表示刪除工作目錄中所有的隱藏檔。

另外非常不建議用很奇怪的檔名,如檔案開頭為〝-〞或檔名中有〝#、@、%、\、?、|、{、}〞等奇怪的字元,因有可能會讓萬用字元失效(試過許多的 Linux 發行版都有此 issue)或很不容易篩選和四配所要的檔案,我們來實驗一下吧!

實驗:
$ echo > abc ←製造一長度為三個字元的檔案
$ ls ??? ←驗證一下
abc
$ echo > -12 ←製造一檔案〝-12〞(長度也為三個字元)
$ ls ??? ←再驗證一下
ls: invalid option -- 2 ←??? 失效了
Try `ls --help' for more information.
$ ls * ←列出所有檔案
ls: invalid option -- 2 ←靈異事件 ? 萬用字元全失效
$ rm -f ./-12 ←把這靈異檔案殺掉吧
$ ls ??? ←再驗證一下
abc ←正常了 :-)

rename 大量檔案更名
rename 用法很另類主要是對付一堆的檔案,而語法也特立獨行,一定要有萬用字元的樣板(glob)。

其語法為 rename OLD NEW GLOB , 例如把檔名〝ABCijk〞更名為〝WXYZijk〞,其中大寫為要更名的地方,小寫〝ijk〞為要保留不變更的檔名部分,rename 的語法要寫成〝rename ABC WXYZ ABC???)〞,(小寫 ijk 為要保留不變更的檔名部分,要想辦法用萬用字元的樣板來匹配)。

有點抽象?小編不才實在不太會解釋,用實例來操作就很容易明白用法。例如我在基隆玩時拍了 50 張的照片,但相機的預設檔名是 IMAGE0001.jpg ~ IMAGE0050.jpg 。

但這種傻瓜檔名時間一久我就忘了是在那拍的照片,所以想把全部檔名改為拍攝地點的 keelung0001.jpg ~ keelung0050.jpg 。而用 mv 指令或用 Windows 的 GUI 一一改檔名操作,保證會操作到抽筋,用 rename 就方便多了。

例:(假設工作目錄內已有 IMAGE0001.jpg~IMAGE0050.jpg 共 50 個檔案)
$ rename IMAGE keelung IMAGE* ←把檔案 IMAGE0001.jpg ~ IMAGE0050.jpg 全改檔名為
keelung0001.jpg ~ keelung0050.jpg


例:(續上例,工作目錄內已有 IMAGE0001~IMAGE0050 共 50 個檔案)
$ rename IMAGE00 keelung00 IMAGE00[0-2]?.* ←把檔案 IMAGE0001.jpg ~IMAGE0029.jpg
全改檔名為 keelung0001.jpg~keelung0029.jpg,其餘不改

例:
$ rename .config .cfg *.config ←把所有工作目錄中,副檔名為〝.config〞改為〝.cfg〞
$ rename - _ *-* ←把所有檔案中檔名中的減號〝-〞改為底線〝_〞

不只是檔案, rename 也可用在大量更名目錄,其實頂好用的!
例:(假設家目錄內已有目錄 catlog00~catlog99,共 100 個目錄)
$ rename ~/catlog ~/list ~/catlog?? ←把家目錄內的目錄 catlog00~catlog99 全改目錄名為 list00~list99

當然只要高興,用牛刀殺雞也沒什麼不可,rename 也可用來重新更名單一檔案。

例:
$ rename abc wxyz * ←把〝abc〞更名為〝wxyz〞


^ back on top ^




5.2 檔案擁有者和權限
檔案相關指令中有說過:「Linux 下的副檔名只供〝參考〞;例如 Linux 的執行檔不會像 Windows 用〝.exe〞為副檔名」。那 Linux 如何判斷那些檔案是執行檔?為什麼以一般的身份登入,有些目錄進不去?為什麼除了自己建的檔案,其餘的檔案都無法刪除?甚至是許多檔案不讓我讀取?一切都和檔案的〝擁有者〞(ownership) 和〝權限〞(permissions) 有關,講解之前我們來實際體驗一下吧。

例:(以一般的帳號登入測試,不要用〝root〞帳號登入哦,因 Superuser 不受權限規範)
$ cd /root ←進去目錄〝/root〞內玩玩
bash: cd: /root: Permission denied ←許可拒絕
$ cat /etc/shadow ←讀看看帳號密碼的資訊檔〝/etc/shadow〞
cat: /etc/shadow: Permission denied ←許可拒絕
$ cp /etc/shadow ./ ←複製〝/etc/shadow〞看看
cp: cannot open '/etc/shadow' for reading: Permission denied ←許可拒絕
$ rm -f /bin/ls ←刪掉指令〝/bin/ls〞
rm: cannot remove `/bin/ls': Permission denied ←許可拒絕

擁有者類別 (ownership)
因 Linux 是多人多工(multi-tasking,multi-user)的作業系統,也就是可很多人使用,所以一定要有某種機制來適當的隔離不同登入者檔案的讀、寫、執行和刪除,甚至是進入某個目錄,這種安全機制就是檔案的〝擁有者類別〞(ownership)和〝權限〞(permission)。

Linux 的檔案的擁有者類別可分〝user 或 owner〞(擁有者)、〝group〞(群組)和〝other〞(其他)各如下:
Linux 登入的時候實際上有兩個身份,一個是登入者(user)另一是伴隨登入者的群組(group),而如有建立檔案,此檔會記錄這兩個身份。

例:
$ echo "hello Wold" > /tmp/myfile ←建立一檔案〝myfile〞
$ ls -l /tmp/myfile ←用 ls -l 列出冗長檔案資訊
-rw-rw-r-- 1 aaa aaa 11 2011-10-10 10:10 myfile ←紅字標記的為 user,綠字標記的為 group

權限(permission)
檔案的權限(permission),為擁有者類別(user/group/other)對此檔案是否有〝讀〞、〝寫〞或〝執行〞的能力(Linux 的執行檔可不是根據副檔名,而是執行檔也要有可〝執行〞的權限)。

而檔案的這些權限除了是否可〝執行〞對〝root〞有約束力外,其餘都無效。也就是說如以〝root〞登入會如入無人之境,想幹嘛都可,如刪除檔案或篡改內容。

回顧一下介紹 ls 指令時用 ls -l 列出冗長檔案資訊的例子,如下:

$  ls -l ←列出冗長檔案內容
drw-rw-r-- aaa  aaa  292 2011-09-07  11:44  myfile
 ↑    ↑  ↑         
 permission   user  group        

上例中〝權限〞(permission)欄位共列出 9 個字元,為了容易識別,刻意以不同的顏色顯示來說明,權限 9 個字元類似〝rwxrwxrwx〞,代表三個不同的擁有者類別,意義如下: 檔案的權限欄位出現的英文字元〝r〞、〝w〞、〝x〞(〝rwx〞順序是固定的)代表對檔案的意義各為 read(讀),write(寫) 和 excute(執行)的權限,而没設定的權限則以〝-〞顯示 。例如〝r--〞只有讀的權限。

下表為權限對檔案的作用:
權限 對檔案的作用
r (讀) 可查看該檔案的內容,如可用 catless 或其他工具來閱讀。
w (寫) 可變更其內容,如可用 vi累加重定向來變更檔案的內容。
x (執行) 如為執行檔則可被執行,但如是 shell script 額外還要有讀的權限才可被執行(因 shell 要讀取該檔)。

例:
$ ls -l /tmp/myfile
-rw-rw-r-- 1 aaa aaa 11 2011-10-10 10:10 myfile

上例 ls -l 輸出權限顯示為〝rw-rw-r--〞紅色字元第一個字元為〝r〞代表擁有者(此為帳號〝aaa〞)對此檔案有〝讀〞的權限,第二個字元為〝w〞 代表擁有者對此檔案有〝寫〞的權限,第三個字元〝-〞,並沒有〝w〞,而是顯示〝-〞代表擁有者對此無執行的權限。

同樣的綠色字體代表〝aaa〞這群組對這檔案也有讀和寫但無執行的權限,而 other(其他)為沒規範在擁有者和群組者皆是,只能讀,不能寫。

接下來我們用不同的帳號來測試一下。

例:
$ echo "hello Wold" > /tmp/myfile ←建立一檔案〝myfile〞
$ ls -l /tmp/myfile ←驗證權限
-rw-rw-r-- 1 aaa aaa 15 2011-09-07 00:46 /tmp/myfile ← 同一 owner/group 可讀寫但 other 只可讀
$ cat /tmp/myfile←讀看看 (測試〝讀〞的權限)
Hello Wold
$ echo 'Hello Linux' >> /tmp/myfile ← 變更〝myfile〞的內容看看(測試〝寫〞的權限)
$ cat /tmp/myfile ←驗證看看
Hello World
Hello Linux
$ su bbb ←暫時變更其他的帳號
Password: ←輸入其帳號密碼
$ cat myfile ←測試〝讀〞的權限
Hello World ←此檔 other 有〝讀〞的權限,故其他人皆可讀取帳號 aaa 所建立的檔案
Hello Linux
$ echo 'Hello Unix' >> /tmp/myfile ←增加〝myfile〞的內容看看
bash: /tmp/myfile: Permission denied ←許可拒絕 (因〝other〞對此檔無〝寫〞的權限)

我們再來看其他的例子。

例:
$ ls -l /etc/shadow ←列出帳號密碼的資訊檔〝/etc/shadow〞的冗長檔案資訊
-r-------- 1 root root 1147 2011-09-07 11:47 /etc/shadow

上例中檔案〝/etc/shadow〞是帳號密碼的影子檔,內容雖都是 ASCII 所編碼的文字檔,但經〝明碼編暗碼〞加密過。由於此檔很重要,有可能會被駭客(Hacker)破解而知每個人帳號的登入密碼,故此檔的擁有者和群組都是〝root〞,而其權限顯示為〝r--------〞表示此檔就算是用〝root〞登入也只能讀不能寫,但不能寫對〝root〞而言是宣示大於實際,因帳號〝root〞特權無限大(如好奇要測試可否更改其內容,請先備份此檔)。

我們再來看看一般的執行檔其擁有者和權限長什麼樣。

例:
$ ls -l /bin/cat
-rwxr-xr-x 1 root root 23360 2007-10-31 11:52 /bin/cat

上例中 cat 這指令其擁有者和群組是〝root〞且可完全讀、寫、和執行,而非〝root〞的擁有者和群組使用此指令的人都算 othe 只能讀和執行。

另外有些指令如 cp 會改變目的檔案的擁有者和群組,使之變成操作者所有,其目的是希望複製過來的檔案可完全掌控。

例:(請以一般帳號登入測試)
$ cp /bin/cat ~/ ←複製〝/bin/ls〞到家目錄
$ ls -l /bin/cat  ~/cat ←列出此兩檔比較看看
-rwxr-xr-x 1 root root 23360 2007-10-31 11:52 /bin/cat
-rwxr-xr-x 1 aaa  aaa  23360 2011-10-10 10:10 ./cat ←注意到沒,複製過來的檔案,擁有者和群組都變操作者所有

那要如何保持複製過來的檔案的原汁原味呢?例如備份系統檔時總不能連原擁有者和權限都把它改變了,萬一要復原系統時可就天下大亂。用 cp -acp -p 選項就能保持原檔案的擁有者和權限。

目錄的權限
目錄的權限和檔案的權限功能有些不一樣,如下表:
權限 對目錄的作用
r 列出目錄內的檔案或其子目錄,如用 ls 可顯示目錄內的檔案但並非可用 cat 來讀取目錄內的檔案
w 增減或更名目錄內的檔案(如可對目錄內的檔案操作 rmcpmv 等)
x 進入目錄或執行目錄內的程式(如可 cd 進入目錄)

當然目錄的這些權限對〝root〞都沒有約束力 。

例:
$ ls -l /home ←列出〝/home〞內所有家目權限
drwx------ 28 aaa aaa 4096 4096 2-11-10-11 15:41 aaa
drwx------ 3  bbb bbb 4096 4096 2-11-10-03 19:59 bbb

上例中顯示每個人的家目錄的 owner 有〝x〞權限故可以自由進入自己的家目錄,且有〝rw〞權限故可列出和增減自己家目錄內的檔案,但其他帳號的使用者為 other 都會被擋在家門口(帳號〝root〞除外)。

特殊權限
權限設定雖可符合大部份的需求,但有灰色地帶;例如某檔案權限為〝rw- --- ---〞,照理說只有該檔的擁有者可變更檔案的內容,但其目錄卻門戶洞開設為〝--- --- -wx〞,其目錄的 other 權限有〝x〞(進入目錄的權限)和〝w〞(增減目錄內的檔案) ,這樣別人(other)好像也可進入目錄把不屬於擁有者的檔案刪除或改名。

檔案和目錄的權限互相矛盾要聽誰的?有法律就會有漏洞,有軟體就會有 bug,當然要想辦法防堵,那就是特殊權限的功用。

特殊權限借用權限〝x〞(執行)的位置來設定和顯示,如權限〝x〞的地方顯示〝t〞或〝s〞即表示設了特殊權限。 以下為特殊權限的用途和用法總覽:
特殊權限 檔案/目錄 作用 但書 ls -l 的權限顯示
Sticky bit 目錄 在具有 Sticky bit 的目錄內, 只有該檔的擁有者或〝root〞可以刪除或更名該檔 ohers 也要有〝x 〞權限 --- --- --t
Set Group ID 檔案 只針對執行檔,執行時會暫時變該檔案所屬的群組 group 也要有〝x 〞權限 --- --s ---
目錄 任何放進目錄內的檔案都會變此目錄的群組
Set User ID 檔案 只針對執行檔,執行時會暫時變該檔所屬的擁有者 user 也要有〝x 〞權限 --s --- ---

chmod 變更檔案的權限
指令 chmod (change mode)可改變檔案和目錄的權限和特殊權限,只有該檔的擁有者和〝root〞有權去更動其權限。

chmod 可接受〝數字表示法〞(Numberic representation)和〝符號表示法〞(Textual representation),這兩種用法的使用者比例旗鼓相當。數字表示法比較簡短,但如非工科的人員可能會對十進制轉二進制感到頭大,而符號表示法寫起來可能比較冗長。 連結檔的權限
如是連結檔,其權限是要依據檔案的本尊還是其分身呢?如是符號連結檔,如用 ls -l 來查詢其權限永遠顯示〝lrwxrwxrwx〞。但其意義可不是任何人都可讀/寫/執行(進入目錄),而是〝完全依本尊的權限〞,如改變符號連結檔的權限,實際是改變原始檔的權限,而符號連結檔永遠不動如山的顯示〝lrwxrwxrwx〞。

如果是硬連結,因硬連結本來就是既是本尊也是分身,故改變本尊或分身的限權,本尊或分身的權限是一起變。

umask 改變預設檔案權限
如用一般身份登入建立一檔案,大部分的 Linux 發行版皆預設檔案的權限為〝rw- rw- r--〞(other 無寫的權限);如為 Superuser 所建立的檔案限制會多一點其檔案權限為〝rw- r-- r--〞(group 和 other 皆無寫的權限)。指令 umask 可變更建立檔案的預設權限。

例: (此為以一般身份測試,如用〝root〞身份測試,結果會有出入)
$ umask ←如沒任何選項,輸出為顯示建立檔案或目錄時的預設權限
0002

umask 輸出的數字對照下表為建立檔案或目錄的權限。
umask 建立檔案其權限 建立目錄其權限
000
666 (rw- rw- rw-)
777 (rwx rwx rwx)
002
664 (rw- rw- r--)
775 (rwx rwx r-x)
022
644 (rw- r-- r--)
755 (rwx r-x r-x)
027
640 (rw- r-- ---)
750 (rwx r-x ---)
077
600 (rw- --- ---)
700 (rwx --- ---)
277
400 (r-- --- ---)
500 (r-x --- ---)

由表可知 umask= 0002 代表建立檔案其權限為〝rw- rw- r--〞如為目錄其權限為〝rwx rwx r-x〞。

如果要改變建立檔案的預設權限,只要輸入 umask [#][###](〝#〞為數字,參考上表,而第一個〝#〞為特殊權限一般是不更動故保持 0)。

例: (此為以一般身份測試,如用〝root〞身份測試,結果會有出入)
$ umask ←看一下預設權限
0002
$ echo 'umask file1' > umask_0002 ←建立檔案〝umask_0002〞
$ umask 0027 ←改變一下預設權限為〝0027〞(rw- r-- ---)
$ umask ←確認看預設權限己改變了沒
0027 ←變〝0027〞了
$ echo 'umask file2' > umask_0027 ←用 umask=0027 建立檔案〝umask_0027〞
$ ls -l umask_0002 umask_0027 ←列出兩檔案的權限來比較看看
-rw-rw-r-- 1 aaa  aaa  12 2011-10-10 10:10 umask_0002 ←注意比對兩個檔案的權限不一樣了
-rw-r----- 1 aaa  aaa  12 2011-10-10 10:11 umask_0027

一般的應用查表就應夠了,如果想打破砂鍋問到底「為什麼 umask =0002,建立新的檔案其權限為〝rw- rw- r--〞」?可繼續看下去。

其實 umask 是〝user mask〞的縮寫,而〝mask〞計算機工程中譯為〝遮罩〞,遮罩意義為〝經位元運算(bitwise operation)來改變某一位元〞,其布林邏輯運算式(Boolean operators) 為〝Inital value & ~ umask value〞(initial value 檔案為 666,目錄為 777)或如下的邏輯電路運算。





因一般建立的文字檔案沒執行的必要,故權限的數字表示法起始值(initial vale)為〝666〞(rw- rw- rw-)。
上個範例測試中把 umask=002,inital value=666 帶入運算式〝 666 & ~002〞運算結果為〝664〞 (rw-r--r--)。
另一例 umask=027 其 initial value 一樣是 666 帶入運算式〝666 & ~027〞=〝640〞 (rw- r-- ---)。

如建立的是目錄,因要求可進入此一目錄,故起始值為〝777〞(rwx rwx rwx)。
以 umask=002 為例帶入運算式〝777 & ~002〞=〝775〞 (rwx rwx r-x)。





^ back on top ^




5.3 檔案屬性

檔案的權限對帳號〝root〞而言都沒什約束力,因 root 有〝權限豁免權〞。故如不小心操作失誤如下達指令 rm -fr / (根目錄和所有子目錄和檔案都殺無赦),那 Linux 大概要往生了。那有沒有什麼方法來規範 root 呢?那就是〝檔案屬性〞(file attributes),檔案屬性可彌補 root 權力太大的危險。

chattr 變更檔案屬性
chatttr (change attribute)可變更 Linux 檔案的 15 種屬性(但只定義約 8 種,其餘預留)用法和 chmod 有點類似,以〝+〞表示增加屬性;〝-〞減去屬性;〝=〞為直接設定屬性, 語法如下:
語法:chattr [-otpiton][+-=][mode] file/directroy
指令名稱/功能/命令使用者 選項 功能 mode的種屬性有[aAcdisSu],意義各為
chattr/
(change attribute)
變更檔案屬性/
Any(主要 for Superuser)
-R 遞回改變檔案的屬性,將目錄下
所有的檔案及子目錄一併異動屬性

〝a〞:用於檔案只能累加,不能刪除。用於目錄只能修改目錄內檔案的內容,但不能增減檔案。且只有〝root〞才可使用
〝A〞:不更新檔案的 atime
〝c〞:存檔時自動壓縮檔案,讀取時自動解壓縮(大部 Linux 發行版不支援此功能)
〝d〞:排除 dump 資料,即執行 dump 指令時會排除此檔
〝i〞:讓檔案具金剛不壞之身;包括不能刪除,更名,修改內容,變更權限等且只有〝root〞才可使用
〝s〞:毀屍滅跡,當檔案被刪除時,該檔案的 block 會被填 0(讓有心人無法復原該檔)
〝S〞:存檔時不先寫入緩衝記憶體,直接寫進硬碟(效能較差,但比較可防止斷電時,檔案流失)
〝u〞:和〝s〞毀屍滅跡相反,當檔案被剛除時只刪除 inode,以利未來後悔〝可能〞可救回此檔(預留功能,目前還沒相關指令可救回被刪除的檔案)
-V 顯示異動屬性的過程

chattr 的 mode 用法可知許多的屬性都是為了規範〝root〞( Supperuser),如屬性〝a〞主要用於會累加的記錄檔,就算用〝root〞帳號都不能刪除此檔,而 mode 中的屬性〝i〞更是不能動此檔一根寒毛。

刪除某一檔案時,Linux 為了效能,只刪除檔案的 inode 並不會真正把資料(block)清除,如有保密資料,刪除時怕被還原加屬性〝s〞就對了。

實驗:(以〝root〞登入,測試)
# echo '123' > myfile ←建立檔案〝myfile〞
# chattr +a myfile ←設定〝a〞屬性只能累加,但不能刪除
# rm -f myfile ←刪除看看
rm: cannot remove `myfile': Operation not permitted ←許可拒絕
# echo '456' > myfile ←覆寫看看
bash: myfile: Operation not permitted ←許可拒絕
# echo '456' >> myfile ←累加看看
cat myfile ←驗證一下
123
456
# chattr -V -a myfile ←減去〝a〞屬性就可被刪除
chattr 1.40.2 (12-Jul-2007)
Flags of myfile set as ---------------

例:(以〝root〞登入,測試)
# chattr =aAdS file ←設定檔案具有〝a〞,〝A〞,〝d〞,〝S〞屬性
# chattr -V +i -ad file ←將檔案增加〝i〞屬性並減去〝a〞,〝d〞屬性

lsattr 顯示檔案屬性
有時可能會遇到權限沒問題,但就是有某些檔案無法刪除或修改,此時可用 lsattr 來查看屬性是否被變動過,lsattrlist attrbute 的縮寫,用來查閱檔案的屬性,用法如下:

語法:lsattr [-otpiton] file/directroy
指令名稱/功能/命令使用者 選項 功能
lsattr/
(list attrbute)顯示檔案屬性/
Any
-a 列出所有檔案和目錄,包括隱藏檔和工作目錄和上層目錄的屬性
-d 只列出目錄屬性
-R 遞回將目錄下的檔案和子目錄列出屬性

例:(以〝root〞登入,測試)
# echo > file
# chattr =aAdS file ←設定檔案具有〝a〞,〝A〞,〝d〞,〝S〞屬性
# lsattr file ←顯示檔案屬性
--S--adA------ file

例:
# lsattr -a ←列出目錄內所有檔案的屬性(包含工作目錄和其父目錄)
-----a-------- ./. ←工作目錄的屬性
-------------- ./.. ←上層目錄的屬性
-----a-------- ./jun ←目錄內檔案的屬性


^ back on top ^











www.reliablecounter.com
digital mastering

[註5.0]參考 http://www.farhadsaberi.com/linux_freebsd/2010/12/hard-link-soft-symbolic-links.html

[註5.1]可用 LANG= 來設定語系,如下例:
$ LANG= ←清除所有設定的語系(同等〝LANG=C〞或〝LANG=POSIX〞為清除所有設定的語系)
$ LANG=en_US.UTF-8 ←設定語系為〝en_US.UTF-8〞