1. 程式人生 > >Linux學習筆記13——檔案與目錄的預設許可權與隱藏許可權

Linux學習筆記13——檔案與目錄的預設許可權與隱藏許可權

檔案與目錄的預設許可權與隱藏許可權

除了基本r, w, x許可權外,在Linux傳統的Ext2/Ext3/Ext4檔案系統下,我們還可以設定其他的系統隱藏屬性, 這部份可使用 chattr 來設定,而以 lsattr 來檢視,最重要的屬性就是可以設定其不可修改的特性!讓連檔案的擁有者都不能進行修改! 這個屬性可是相當重要的,尤其是在安全機制上面 (security)!比較可惜的是,在 CentOS 7.x 當中利用 xfs 作為預設檔案系統, 但是 xfs 就沒有支援所有的 chattr 的引數了!僅有部份引數還有支援而已!

1,檔案預設許可權:umask

 

你知道當你建立一個新的檔案或目錄時,他的預設許可權會是什麼嗎?呵呵!那就與 umask 這個玩意兒有關了!那麼 umask 是在搞什麼呢?基本上, umask 就是指定 “目前使用者在建立檔案或目錄時

候的許可權預設值”, 那麼如何得知或設定 umask 呢?他的指定條件以下面的方式來指定:

[[email protected] tmp]# umask

0022 <==與一般許可權有關的是後面三個數字!

[[email protected] tmp]# umask -S

u=rwx,g=rx,o=rx

查閱的方式有兩種,一種可以直接輸入 umask ,就可以看到數字體態的許可權設定分數, 一種則是加入 -S (Symbolic) 這個選項,就會以符號型別的方式來顯示出許可權了! 奇怪的是,怎麼 umask 會有四組數字啊?不是隻有三組嗎?是沒錯啦。 第一組是特殊許可權用的,我們先不要理他,所以先看後面三組即可。

 

在預設許可權的屬性上,目錄與檔案是不一樣的。從第五章我們知道 x 許可權對於目錄是非常重要的! 但是一般檔案的建立則不應該有執行的許可權,因為一般檔案通常是用在於資料的記錄嘛!當然不需要執行的許可權了。 因此,預設的情況如下:

若使用者建立為“檔案”則預設“沒有可執行( x )許可權”,亦即只有 rw 這兩個專案,也就是最大為 666 分,預設許可權如下: -rw-rw-rw-

若使用者建立為“目錄”,則由於 x 與是否可以進入此目錄有關,因此預設為所有許可權均開放,亦即為 777 分,預設許可權如下: drwxrwxrwx

要注意的是,umask 的分數指的是“該預設值需要減掉的許可權!”因為 r、w、x 分別是 4、2、1 分,所以囉!也就是說,當要拿掉能寫的許可權,就是輸入 2 分,而如果要拿掉能讀的許可權,也就是 4 分,那麼要拿掉讀與寫的許可權,也就是 6 分,而要拿掉執行與寫入的許可權,也就是 3 分,這樣瞭解嗎?請問你, 5 分是什麼?呵呵! 就是讀與執行的許可權啦!

 

(1)umask的利用與重要性:專題製作

 

想像一個狀況,如果你跟你的同學在同一部主機裡面工作時,因為你們兩個正在進行同一個專題, 老師也幫你們兩個的帳號建立好了相同群組的狀態,並且將 /home/class/ 目錄做為你們兩個人的專題目錄。 想像一下,有沒有可能你所製作的檔案你的同學無法編輯?果真如此的話,那就傷腦筋了!

這個問題很常發生啊!舉上面的案例來看就好了,你看一下 test1 的許可權是幾分? 644 呢!意思是“如果 umask 訂定為 022 ,那新建的資料只有使用者自己具有 w 的許可權, 同群組的人只有 r 這個可讀的許可權而已,並無法修改喔!”這樣要怎麼共同製作專題啊!您說是吧!

所以,當我們需要新建檔案給同群組的使用者共同編輯時,那麼 umask 的群組就不能拿掉 2這個 w 的許可權! 所以囉, umask 就得要是 002 之類的才可以!這樣新建的檔案才能夠是 -rw-rw-r-- 的許可權模樣喔! 那麼如何設定 umask 呢?簡單的很,直接在 umask 後面輸入 002就好了!

[[email protected] tmp]# umask 002

[[email protected] tmp]# touch test3

[[email protected] tmp]# mkdir test4

[[email protected] tmp]# ll -d test[34] # 中括號 [ ] 代表中間有個指定的字元,而不是任意 字元的意思

-rw-rw-r-- 1 root root 0 11月 9 16:58 test3

drwxrwxr-x 2 root root 6 11月 9 16:59 test4

 

關於 umask 與許可權的計算方式中,教科書喜歡使用二進位制的方式來進行 AND 與 NOT的計算, 不過,鳥哥還是比較喜歡使用符號方式來計算~聯想上面比較容易一點~但是,有的書籍或者是 BBS 上面的朋友,喜歡使用檔案預設屬性 666 與目錄預設屬性 777來與 umask 進行相減的計算~這是不好的喔!以上面例題來看, 如果使用預設屬性相加減,則檔案變成:666-003=663,亦即是 -rw-rw--wx ,這可是完全不對的喔! 想想看,原本檔案就已經去除 x 的預設屬性了,怎麼可能突然間冒出來了? 所以,這個地方得要特別小心喔!在預設的情況中, root 的 umask 會拿掉比較多的屬性,root 的 umask 預設是 022 , 這是基於安全的考慮啦~至於一般身份使用者,通常他們的 umask 為 002 ,亦即保留同群組的寫入權力! 其實,關於預設 umask 的設定可以參考 /etc/bashrc 這個檔案的內容,不過,不建議修改該檔案, 你可以參考第十章 bash shell 提到的環境引數配置檔案 (~/.bashrc) 的說明!

 

2,檔案隱藏屬性

 

什麼?檔案還有隱藏屬性?光是那九個許可權就快要瘋掉了,竟然還有隱藏屬性,真是要命~但是沒辦法,就是有檔案的隱藏屬性存在啊!不過,這些隱藏的屬性確實對於系統有很大的幫助的~ 尤其是在系統安全 (Security) 上面,重要的緊呢!不過要先強調的是,下面的chattr指令只能在Ext2/Ext3/Ext4的 Linux 傳統檔案系統上面完整生效, 其他的檔案系統可能就無法完整的支援這個指令了,例如 xfs 僅支援部份引數而已。下面我們就來談一談如何設定與檢查這些隱藏的屬性吧!

chattr (設定檔案隱藏屬性)

 

# chattr [+-=][ASacdistu] 檔案或目錄名稱

選項與引數:

+ :增加某一個特殊引數,其他原本存在引數則不動。

- :移除某一個特殊引數,其他原本存在引數則不動。

= :設定一定,且僅有後面接的引數

A :當設定了 A 這個屬性時,若你有存取此檔案(或目錄)時,他的存取時間 atime 將不會被修改,可避免 I/O 較慢的機器過度的存取磁碟。(目前建議使用檔案系統掛載引數處理這個專案)

S :一般檔案是非同步寫入磁碟的(原理請參考[前一章sync](../Text/index.html#sync)的說明),如果加上 S 這個屬性時,

當你進行任何檔案的修改,該更動會“同步”寫入磁碟中。

a :當設定 a 之後,這個檔案將只能增加資料,而不能刪除也不能修改資料,只有root 才能設定這屬性

c :這個屬性設定之後,將會自動的將此檔案“壓縮”,在讀取的時候將會自動解壓縮,

但是在儲存的時候,將會先進行壓縮後再儲存(看來對於大檔案似乎蠻有用的!)

d :當 dump 程式被執行的時候,設定 d 屬性將可使該檔案(或目錄)不會被 dump 備份

i :這個 i 可就很厲害了!他可以讓一個檔案“不能被刪除、改名、設定連結也無法寫入或新增資料!”

對於系統安全性有相當大的助益!只有 root 能設定此屬性

s :當檔案設定了 s 屬性時,如果這個檔案被刪除,他將會被完全的移除出這個硬碟空間,所以如果誤刪了,完全無法救回來了喔!

u :與 s 相反的,當使用 u 來設定檔案時,如果該檔案被刪除了,則資料內容其實還存在磁碟中,可以使用來救援該檔案喔!

注意1:屬性設定常見的是 a 與 i 的設定值,而且很多設定值必須要身為 root 才能設定

注意2:xfs 檔案系統僅支援 AadiS 而已

 

範例:請嘗試到/tmp下面建立檔案,並加入 i 的引數,嘗試刪除看看。

[[email protected] ~]# cd /tmp

[[email protected] tmp]# touch attrtest <==建立一個空檔案

[[email protected] tmp]# chattr +i attrtest <==給予 i 的屬性

[[email protected] tmp]# rm attrtest <==嘗試刪除看看

rm: remove regular empty file `attrtest'? y

rm: cannot remove `attrtest': Operation not permitted

# 看到了嗎?呼呼!連 root 也沒有辦法將這個檔案刪除呢!趕緊解除設定!

範例:請將該檔案的 i 屬性取消!

[[email protected] tmp]# chattr -i attrtest

 

這個指令是很重要的,尤其是在系統的資料安全上面!由於這些屬性是隱藏的性質,所以需要以 lsattr 才能看到該屬性呦!其中,個人認為最重要的當屬 +i 與 +a 這個屬性了。+i 可以讓一個檔案無法被更動,對於需要強烈的系統安全的人來說, 真是相當的重要的!裡頭還有相當多的屬性是需要 root 才能設定的呢!

此外,如果是 log file 這種的登入檔案,就更需要 +a 這個可以增加,但是不能修改舊有的資料與刪除的引數了!怎樣?很棒吧! 未來提到登入檔案 (十八章) 的認知時,我們再來聊一聊如何設定他吧!

 

lsattr (顯示檔案隱藏屬性)

 

# lsattr [-adR] 檔案或目錄

選項與引數:

-a :將隱藏檔案的屬性也秀出來;

-d :如果接的是目錄,僅列出目錄本身的屬性而非目錄內的檔名;

-R :連同子目錄的資料也一併列出來!

[[email protected] tmp]# chattr +aiS attrtest

[[email protected] tmp]# lsattr attrtest

--S-ia---------- attrtest

 

使用 chattr 設定後,可以利用 lsattr 來查閱隱藏的屬性。不過, 這兩個指令在使用上必須要特別小心,否則會造成很大的困擾。例如:某天你心情好,突然將 /etc/shadow 這個重要的密碼記錄檔案給他設定成為具有 i 的屬性,那麼過了若干天之後, 你突然要新增使用者,卻一直無法新增!別懷疑,趕快去將 i 的屬性拿掉吧!

 

3,檔案特殊許可權: SUID, SGID, SBIT

 

我們前面一直提到關於檔案的重要許可權,那就是 rwx 這三個讀、寫、執行的許可權。 但是,眼尖的朋友們在第五章的目錄樹章節中, 一定注意到了一件事,那就是,怎麼我們的 /tmp 許可權怪怪的? 還有,那個 /usr/bin/passwd 也怪怪的?怎麼回事啊?看看先:

[[email protected] ~]# ls -ld /tmp ; ls -l /usr/bin/passwd

drwxrwxrwt. 14 root root 4096 Jun 16 01:27 /tmp

-rwsr-xr-x. 1 root root 27832 Jun 10 2014 /usr/bin/passwd

 

不是應該只有 rwx 嗎?還有其他的特殊許可權( s 跟 t )啊?啊.....頭又開始昏了~ @[email protected] 因為s 與 t 這兩個許可權的意義與系統的帳號 (第十三章)及系統的程式(process, 第十六章)較為相關, 所以等到後面的章節談完後你才會比較有概念!下面的說明先看看就好,如果看不懂也沒有關係, 先知道s放在哪裡稱為SUID/SGID以及如何設定即可,等系統程式章節讀完後,再回來看看喔!

Set UID

當 s 這個標誌出現在檔案擁有者的 x 許可權上時,例如剛剛提到的 /usr/bin/passwd 這個檔案的許可權狀態:“-rwsr-xr-x”,此時就被稱為 Set UID,簡稱為 SUID 的特殊許可權。 那麼SUID的許可權對於一個檔案的特殊功能是什麼呢?基本上SUID有這樣的限制與功能:

SUID 許可權僅對二進位制程式(binary program)有效;

執行者對於該程式需要具有 x 的可執行許可權;

本許可權僅在執行該程式的過程中有效 (run-time);

執行者將具有該程式擁有者 (owner) 的許可權。

 

講這麼硬的東西你可能對於 SUID 還是沒有概念,沒關係,我們舉個例子來說明好了。 我們的 Linux 系統中,所有帳號的密碼都記錄在 /etc/shadow 這個檔案裡面,這個檔案的許可權為:“---------- 1 root root”,意思是這個檔案僅有root可讀且僅有root可以強制寫入而已。 既然這個檔案僅有 root 可以修改,那麼鳥哥的 dmtsai 這個一般帳號使用者能否自行修改自己的密碼呢? 你可以使用你自己的帳號輸入“passwd”這個指令來看看,嘿嘿!一般使用者當然可以修改自己的密碼了!

 

唔!有沒有衝突啊!明明 /etc/shadow 就不能讓 dmtsai 這個一般帳戶去存取的,為什麼dmtsai 還能夠修改這個檔案內的密碼呢? 這就是 SUID 的功能啦!藉由上述的功能說明,我們可以知道

1. dmtsai 對於 /usr/bin/passwd 這個程式來說是具有 x 許可權的,表示 dmtsai 能執行passwd;

2. passwd 的擁有者是 root 這個帳號;

3. dmtsai 執行 passwd 的過程中,會“暫時”獲得 root 的許可權;

4. /etc/shadow 就可以被 dmtsai 所執行的 passwd 所修改。

但如果 dmtsai 使用 cat 去讀取 /etc/shadow 時,他能夠讀取嗎?因為 cat 不具有 SUID 的許可權,所以 dmtsai 執行 “cat /etc/shadow” 時,是不能讀取 /etc/shadow 的。我們用一張示意圖來說明如下:

當 s 這個標誌出現在檔案擁有者的 x 許可權上時,例如剛剛提到的 /usr/bin/passwd 這個檔案的許可權狀態:“-rwsr-xr-x”,此時就被稱為 Set UID,簡稱為 SUID 的特殊許可權。 那麼SUID的許可權對於一個檔案的特殊功能是什麼呢?基本上SUID有這樣的限制與功能:

SUID 許可權僅對二進位制程式(binary program)有效;

執行者對於該程式需要具有 x 的可執行許可權;

本許可權僅在執行該程式的過程中有效 (run-time);

執行者將具有該程式擁有者 (owner) 的許可權。

 

講這麼硬的東西你可能對於 SUID 還是沒有概念,沒關係,我們舉個例子來說明好了。 我們的 Linux 系統中,所有帳號的密碼都記錄在 /etc/shadow 這個檔案裡面,這個檔案的許可權為:“---------- 1 root root”,意思是這個檔案僅有root可讀且僅有root可以強制寫入而已。 既然這個檔案僅有 root 可以修改,那麼鳥哥的 dmtsai 這個一般帳號使用者能否自行修改自己的密碼呢? 你可以使用你自己的帳號輸入“passwd”這個指令來看看,嘿嘿!一般使用者當然可以修改自己的密碼了!

 

唔!有沒有衝突啊!明明 /etc/shadow 就不能讓 dmtsai 這個一般帳戶去存取的,為什麼dmtsai 還能夠修改這個檔案內的密碼呢? 這就是 SUID 的功能啦!藉由上述的功能說明,我們可以知道

1. dmtsai 對於 /usr/bin/passwd 這個程式來說是具有 x 許可權的,表示 dmtsai 能執行passwd;

2. passwd 的擁有者是 root 這個帳號;

3. dmtsai 執行 passwd 的過程中,會“暫時”獲得 root 的許可權;

4. /etc/shadow 就可以被 dmtsai 所執行的 passwd 所修改。

但如果 dmtsai 使用 cat 去讀取 /etc/shadow 時,他能夠讀取嗎?因為 cat 不具有 SUID 的許可權,所以 dmtsai 執行 “cat /etc/shadow” 時,是不能讀取 /etc/shadow 的。我們用一張示意圖來說明如下

 

另外,SUID 僅可用在binary program 上, 不能夠用在 shell script 上面!這是因為 shellscript 只是將很多的 binary 可執行檔案叫進來執行而已!所以 SUID 的許可權部分,還是得要看shell script 呼叫進來的程式的設定, 而不是 shell script 本身。當然,SUID 對於目錄也是無效的~這點要特別留意。

Set GID

當 s 標誌在檔案擁有者的 x 專案為 SUID,那 s 在群組的 x 時則稱為 Set GID, SGID 囉!是這樣沒錯!^_^。 舉例來說,你可以用下面的指令來觀察到具有 SGID 許可權的檔案喔:

[[email protected] ~]# ls -l /usr/bin/locate

-rwx--s--x. 1 root slocate 40496 Jun 10 2014 /usr/bin/locate

與 SUID 不同的是,SGID 可以針對檔案或目錄來設定!如果是對檔案來說, SGID 有如下的功能:

SGID 對二進位制程式有用;

程式執行者對於該程式來說,需具備 x 的許可權;

執行者在執行的過程中將會獲得該程式群組的支援!

舉例來說,上面的 /usr/bin/locate 這個程式可以去搜尋 /var/lib/mlocate/mlocate.db 這個檔案的內容 (詳細說明會在下節講述), mlocate.db 的許可權如下:

[[email protected] ~]# ll /usr/bin/locate /var/lib/mlocate/mlocate.db

-rwx--s--x. 1 root slocate 40496 Jun 10 2014 /usr/bin/locate

-rw-r-----. 1 root slocate 2349055 Jun 15 03:44 /var/lib/mlocate/mlocate.db

與 SUID 非常的類似,若我使用 dmtsai 這個帳號去執行 locate 時,那 dmtsai 將會取得slocate 群組的支援, 因此就能夠去讀取 mlocate.db 啦!非常有趣吧!

除了 binary program 之外,事實上 SGID 也能夠用在目錄上,這也是非常常見的一種用途!當一個目錄設定了 SGID 的許可權後,他將具有如下的功能:

使用者若對於此目錄具有 r 與 x 的許可權時,該使用者能夠進入此目錄;

使用者在此目錄下的有效群組(effective group)將會變成該目錄的群組;

用途:若使用者在此目錄下具有 w 的許可權(可以新建檔案),則使用者所建立的新檔案,該新檔案的群組與此目錄的群組相同。

Sticky Bit

這個 Sticky Bit, SBIT 目前只針對目錄有效,對於檔案已經沒有效果了。SBIT 對於目錄的作用是:

當使用者對於此目錄具有 w, x 許可權,亦即具有寫入的許可權時;

當使用者在該目錄下建立檔案或目錄時,僅有自己與 root 才有權力刪除該檔案

換句話說:當甲這個使用者於 A 目錄是具有群組或其他人的身份,並且擁有該目錄 w 的許可權, 這表示“甲使用者對該目錄內任何人建立的目錄或檔案均可進行 "刪除/更名/搬移" 等動作。” 不過,如果將 A 目錄加上了 SBIT 的許可權專案時, 則甲只能夠針對自己建立的檔案或目錄進行刪除/更名/移動等動作,而無法刪除他人的檔案。

舉例來說,我們的 /tmp 本身的許可權是“drwxrwxrwt”, 在這樣的許可權內容下,任何人都可以在/tmp 內新增、修改檔案,但僅有該檔案/目錄建立者與 root 能夠刪除自己的目錄或檔案。這個特性也是挺重要的啊!你可以這樣做個簡單的測試:

1. 以 root 登陸系統,並且進入 /tmp 當中;

2. touch test,並且更改 test 許可權成為 777 ;

3. 以一般使用者登陸,並進入 /tmp;

4. 嘗試刪除 test 這個檔案!

 

SUID/SGID/SBIT 許可權設定

前面介紹過 SUID 與 SGID 的功能,那麼如何設定檔案使成為具有 SUID 與 SGID 的許可權呢?這就需要之前的數字更改許可權的方法了! 現在你應該已經知道數字體態更改許可權的方式為“三個數字”的組合, 那麼如果在這三個數字之前再加上一個數字的話,最前面的那個數字就代表這幾個許可權了!

4 為 SUID

2 為 SGID

1 為 SBIT

 

假設要將一個檔案許可權改為“-rwsr-xr-x”時,由於 s 在使用者許可權中,所以是 SUID ,因此,在原先的 755 之前還要加上 4 ,也就是:“ chmod 4755 filename ”來設定!此外,還有大 S與大 T 的產生喔!參考下面的範例啦

 

下面的範例只是練習而已,所以鳥哥使用同一個檔案來設定,你必須瞭解 SUID不是用在目錄上,而 SBIT 不是用在檔案上的喔!

[[email protected] ~]# cd /tmp

[[email protected] tmp]# touch test <==建立一個測試用空檔

[[email protected] tmp]# chmod 4755 test; ls -l test <==加入具有 SUID 的許可權

-rwsr-xr-x 1 root root 0 Jun 16 02:53 test

[[email protected] tmp]# chmod 6755 test; ls -l test <==加入具有 SUID/SGID 的許可權

-rwsr-sr-x 1 root root 0 Jun 16 02:53 test

[[email protected] tmp]# chmod 1755 test; ls -l test <==加入 SBIT 的功能!

-rwxr-xr-t 1 root root 0 Jun 16 02:53 test

[[email protected] tmp]# chmod 7666 test; ls -l test <==具有空的 SUID/SGID 許可權

-rwSrwSrwT 1 root root 0 Jun 16 02:53 test

 

最後一個例子就要特別小心啦!怎麼會出現大寫的 S 與 T 呢?不都是小寫的嗎? 因為 s 與 t都是取代 x 這個許可權的,但是你有沒有發現阿,我們是下達 7666 喔!也就是說, user,group 以及 others 都沒有 x 這個可執行的標誌( 因為 666 嘛 ),所以,這個 S, T 代表的就是“空的”啦!怎麼說? SUID 是表示“該檔案在執行的時候,具有檔案擁有者的許可權”,但是檔案 擁有者都無法執行了,哪裡來的許可權給其他人使用?當然就是空的啦!

 

而除了數字法之外,你也可以通過符號法來處理喔!其中 SUID 為 u+s ,而 SGID 為 g+s ,

SBIT 則是 o+t 囉!來看看如下的範例:

# 設定許可權成為 -rws--x--x 的模樣:

[[email protected] tmp]# chmod u=rwxs,go=x test; ls -l test

-rws--x--x 1 root root 0 Jun 16 02:53 test

# 承上,加上 SGID 與 SBIT 在上述的檔案許可權中!

[[email protected] tmp]# chmod g+s,o+t test; ls -l test

-rws--s--t 1 root root 0 Jun 16 02:53 test

 

4,觀察檔案型別:file

如果你想要知道某個檔案的基本資料,例如是屬於 ASCII 或者是 data 檔案,或者是 binary, 且其中有沒有使用到動態函式庫 (share library) 等等的資訊,就可以利用 file 這個指令來檢閱喔!舉例來說:

[[email protected] ~]# file ~/.bashrc

/root/.bashrc: ASCII text <==告訴我們是 ASCII 的純文字檔案啊!

[[email protected] ~]# file /usr/bin/passwd

/usr/bin/passwd: setuid ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically

linked (uses shared libs), for GNU/Linux 2.6.32,

BuildID[sha1]=0xbf35571e607e317bf107b9bcf65199988d0ed5ab, stripped

# 可執行檔案的資料可就多的不得了!包括這個檔案的 suid 許可權、相容於 Intel x86-64 等級的硬體平臺

# 使用的是 Linux 核心 2.6.32 的動態函式庫連結等等。

[[email protected] ~]# file /var/lib/mlocate/mlocate.db

/var/lib/mlocate/mlocate.db: data <== 這是 data 檔案!

 

通過這個指令,我們可以簡單的先判斷這個檔案的格式為何喔!包括未來你也可以用來判斷使用 tar 包裹時,該 tarball 檔案是使用哪一種壓縮功能哩!

 

5,指令與檔案的搜尋

(1)which (尋找“可執行檔案”)

# which [-a] command

選項或引數:

-a :將所有由 PATH 目錄中可以找到的指令均列出,而不止第一個被找到的指令名稱

範例一:搜尋 ifconfig 這個指令的完整檔名

[[email protected] ~]# which ifconfig

/sbin/ifconfig

範例二:用 which 去找出 which 的檔名為何?

[[email protected] ~]# which which

alias which='alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde'

/bin/alias

/usr/bin/which

# 竟然會有兩個 which ,其中一個是 alias 這玩意兒呢!那是啥?

# 那就是所謂的“命令別名”,意思是輸入 which 會等於後面接的那串指令啦!

# 更多的資料我們會在 bash 章節中再來談的!

範例三:請找出 history 這個指令的完整檔名

[[email protected] ~]# which history

/usr/bin/which: no history in (/usr/local/sbin:/usr/local/bin:/sbin:/bin:

/usr/sbin:/usr/bin:/root/bin)

 

[[email protected] ~]# history --help

-bash: history: --: invalid option

history: usage: history [-c] [-d offset] [n] or history -anrw [filename] or history -ps arg

# 瞎密?怎麼可能沒有 history ,我明明就能夠用 root 執行 history 的啊!

 

這個指令是根據“PATH”這個環境變數所規範的路徑,去搜尋“可執行檔案”的檔名~ 所以,重點是找出“可執行檔案”而已!且 which 後面接的是“完整檔名”喔!若加上 -a 選項,則可以列出所有的可以找到的同名可執行檔案,而非僅顯示第一個而已!

 

最後一個範例最有趣,怎麼 history 這個常用的指令竟然找不到啊!為什麼呢?這是因為history 是“bash 內建的指令”啦! 但是 which 預設是找 PATH 內所規範的目錄,所以當然一定找不到的啊(有 bash 就有 history!)!那怎辦?沒關係!我們可以通過 type 這個指令喔!關於 type 的用法我們將在 第十章的 bash 再來談!

 

(2)檔案檔名的搜尋

再來談一談怎麼搜尋檔案吧!在 Linux 下面也有相當優異的搜尋指令呦!通常 find 不很常用的!因為速度慢之外, 也很操硬碟!一般我們都是先使用 whereis 或者是 locate 來檢查,如果真的找不到了,才以 find 來搜尋呦! 為什麼呢?因為 whereis 只找系統中某些特定目錄下面的檔案而已,locate 則是利用資料庫來搜尋檔名,當然兩者就相當的快速, 並且沒有實際的搜尋硬碟內的檔案系統狀態,比較省時間啦!

whereis (由一些特定的目錄中尋找檔案檔名)

# whereis [-bmsu] 檔案或目錄名

選項與引數:

-l :可以列出 whereis 會去查詢的幾個主要目錄而已

-b :只找 binary 格式的檔案

-m :只找在說明文件 manual 路徑下的檔案

-s :只找 source 來原始檔

-u :搜尋不在上述三個專案當中的其他特殊檔案

範例一:請找出 ifconfig 這個檔名

[[email protected] ~]# whereis ifconfig

ifconfig: /sbin/ifconfig /usr/share/man/man8/ifconfig.8.gz

範例二:只找出跟 passwd 有關的“說明文件”檔名(man page)

[[email protected] ~]# whereis passwd # 全部的檔名通通列出來!

passwd: /usr/bin/passwd /etc/passwd /usr/share/man/man1/passwd.1.gz /usr/share/man/man5/passwd.5.gz

[[email protected] ~]# whereis -m passwd # 只有在 man 裡面的檔名才抓出來!

passwd: /usr/share/man/man1/passwd.1.gz /usr/share/man/man5/passwd.5.gz

 

等一下我們會提到 find 這個搜尋指令, find 是很強大的搜尋指令,但時間花用的很大!(因為 find 是直接搜尋硬碟,為如果你的硬碟比較老舊的話,嘿嘿!有的等!) 這個時候whereis 就相當的好用了!另外, whereis 可以加入選項來找尋相關的資料,例如,如果你是要找可可執行檔案 (binary) 那麼加上 -b 就可以啦! 如果不加任何選項的話,那麼就將所有的資料列出來囉!

 

那麼 whereis 到底是使用什麼咚咚呢?為何搜尋的速度會比 find 快這麼多? 其實那也沒有什麼,只是因為 whereis 只找幾個特定的目錄而已~並沒有全系統去查詢之故。所以說,whereis 主要是針對 /bin /sbin 下面的可執行檔案, 以及 /usr/share/man 下面的 man page 檔案,跟幾個比較特定的目錄來處理而已。所以速度當然快的多!不過,就有某些檔案是你找不到的啦! 想要知道 whereis 到底查了多少目錄?可以使用 whereis -l 來確認一下即可!

 

locate / updatedb

[[email protected] ~]# locate [-ir] keyword

選項與引數:

-i :忽略大小寫的差異;

-c :不輸出檔名,僅計算找到的檔案數量

-l :僅輸出幾行的意思,例如輸出五行則是 -l 5

-S :輸出 locate 所使用的資料庫檔案的相關資訊,包括該資料庫紀錄的檔案/目錄數量等

-r :後面可接正則表示式的顯示方式

範例一:找出系統中所有與 passwd 相關的檔名,且只列出 5 個

[[email protected] ~]# locate -l 5 passwd

/etc/passwd

/etc/passwd-

/etc/pam.d/passwd

/etc/security/opasswd

/usr/bin/gpasswd

範例二:列出 locate 查詢所使用的資料庫檔案之檔名與各資料數量

[[email protected] ~]# locate -S

Database /var/lib/mlocate/mlocate.db:

8,086 directories # 總紀錄目錄數

109,605 files # 總紀錄檔案數

5,190,295 Bytes in file names

2,349,150 Bytes used to store database

這個 locate 的使用更簡單,直接在後面輸入“檔案的部分名稱”後,就能夠得到結果。 舉上面的例子來說,我輸入 locate passwd ,那麼在完整檔名 (包含路徑名稱) 當中,只要有passwd 在其中, 就會被顯示出來的!這也是個很方便好用的指令,如果你忘記某個檔案的完整檔名時~~

 

但是,這個東西還是有使用上的限制呦!為什麼呢?你會發現使用 locate 來尋找資料的時候特別的快, 這是因為 locate 尋找的資料是由“已建立的資料庫 /var/lib/mlocate/” 裡面的資料所搜尋到的,所以不用直接在去硬碟當中存取資料,呵呵!當然是很快速囉!

 

那麼有什麼限制呢?就是因為他是經由資料庫來搜尋的,而資料庫的建立預設是在每天執行一次 (每個 distribution 都不同,CentOS 7.x 是每天更新資料庫一次!),所以當你新建立起來的檔案, 卻還在資料庫更新之前搜尋該檔案,那麼 locate 會告訴你“找不到!”呵呵!因為必須要更新資料庫呀!

 

那能否手動更新資料庫哪?當然可以啊!更新 locate 資料庫的方法非常簡單,直接輸入“updatedb ”就可以了! updatedb 指令會去讀取 /etc/updatedb.conf 這個配置檔案的設定,然後再去硬盤裡面進行搜尋檔名的動作, 最後就更新整個資料庫檔案囉!因為 updatedb 會去搜尋硬碟,所以當你執行 updatedb 時,可能會等待數分鐘的時間喔!

 

updatedb:根據 /etc/updatedb.conf 的設定去搜尋系統硬碟內的檔名,並更新/var/lib/mlocate 內的資料庫檔案;

locate:依據 /var/lib/mlocate 內的資料庫記載,找出使用者輸入的關鍵字檔名。

find

 

# find [PATH] [option] [action]

選項與引數:

1\. 與時間有關的選項:共有 -atime, -ctime 與 -mtime ,以 -mtime 說明

-mtime n :n 為數字,意義為在 n 天之前的“一天之內”被更動過內容的檔案;

-mtime +n :列出在 n 天之前(不含 n 天本身)被更動過內容的檔案檔名;

-mtime -n :列出在 n 天之內(含 n 天本身)被更動過內容的檔案檔名。

-newer file :file 為一個存在的檔案,列出比 file 還要新的檔案檔名

範例一:將過去系統上面 24 小時內有更動過內容 (mtime) 的檔案列出

[[email protected] ~]# find / -mtime 0

# 那個 0 是重點!0 代表目前的時間,所以,從現在開始到 24 小時前,

# 有變動過內容的檔案都會被列出來!那如果是三天前的 24 小時內?

# find / -mtime 3 有變動過的檔案都被列出的意思!

範例二:尋找 /etc 下面的檔案,如果檔案日期比 /etc/passwd 新就列出

[[email protected] ~]# find /etc -newer /etc/passwd

# -newer 用在分辨兩個檔案之間的新舊關係是很有用的!

 

時間引數真是挺有意思的!我們現在知道 atime, ctime 與 mtime 的意義,如果你想要找出一天內被更動過的檔名稱, 可以使用上述範例一的作法。但如果我想要找出“4天內被更動過的檔案檔名”呢?那可以使用“ find /var -mtime -4 ”。那如果是“4天前的那一天”就用“ find/var -mtime 4 ”。有沒有加上“+, -”差別很大喔!我們可以用簡單的圖示來說明一下:

圖中最右邊為目前的時間,越往左邊則代表越早之前的時間軸啦。由圖 6.5.1 我們可以清楚的知道:

+4代表大於等於5天前的檔名:ex> find /var -mtime +4

-4代表小於等於4天內的檔案檔名:ex> find /var -mtime -4

4則是代表4-5那一天的檔案檔名:ex> find /var -mtime 4

非常有趣吧!你可以在 /var/ 目錄下搜尋一下,感受一下輸出檔案的差異喔!再來看看其他find 的用法吧!

 

選項與引數:

2. 與使用者或群組名稱有關的引數:

-uid n :n 為數字,這個數字是使用者的帳號 ID,亦即 UID ,這個 UID 是記錄在

/etc/passwd 裡面與帳號名稱對應的數字。這方面我們會在第四篇介紹。

-gid n :n 為數字,這個數字是群組名稱的 ID,亦即 GID,這個 GID 記錄在

/etc/group,相關的介紹我們會第四篇說明~

-user name :name 為使用者帳號名稱喔!例如 dmtsai

-group name:name 為群組名稱喔,例如 users ;

-nouser :尋找檔案的擁有者不存在 /etc/passwd 的人!

-nogroup :尋找檔案的擁有群組不存在於 /etc/group 的檔案!

當你自行安裝軟體時,很可能該軟體的屬性當中並沒有檔案擁有者,

這是可能的!在這個時候,就可以使用 -nouser 與 -nogroup 搜尋。

範例三:搜尋 /home 下面屬於 dmtsai 的檔案

[[email protected] ~]# find /home -user dmtsai

# 這個東西也很有用的~當我們要找出任何一個使用者在系統當中的所有檔案時,

# 就可以利用這個指令將屬於某個使用者的所有檔案都找出來喔!

範例四:搜尋系統中不屬於任何人的檔案

[[email protected] ~]# find / -nouser

# 通過這個指令,可以輕易的就找出那些不太正常的檔案。如果有找到不屬於系統任何人的檔案時,

# 不要太緊張,那有時候是正常的~尤其是你曾經以原始碼自行編譯軟體時。

 

如果你想要找出某個使用者在系統下面建立了啥咚咚,使用上述的選項與引數,就能夠找出來啦! 至於那個 -nouser 或 -nogroup 的選項功能中,除了你自行由網路上面下載檔案時會發生之外, 如果你將系統裡面某個帳號刪除了,但是該帳號已經在系統內建立很多檔案時,就可能會發生無主孤魂的檔案存在! 此時你就得使用這個 -nouser 來找出該型別的檔案囉!

 

選項與引數:

3. 與檔案許可權及名稱有關的引數:

-name filename:搜尋檔名稱為 filename 的檔案;

-size [+-]SIZE:搜尋比 SIZE 還要大(+)或小(-)的檔案。這個 SIZE 的規格有:

c: 代表 Byte, k: 代表 1024Bytes。所以,要找比 50KB

還要大的檔案,就是“ -size +50k ”

-type TYPE :搜尋檔案的型別為 TYPE 的,型別主要有:一般正規檔案 (f), 裝置檔案 (b, c),

目錄 (d), 連結檔案 (l), socket (s), 及 FIFO (p) 等屬性。

-perm mode :搜尋檔案許可權“剛好等於” mode 的檔案,這個 mode 為類似 chmod

的屬性值,舉例來說, -rwsr-xr-x 的屬性為 4755 !

-perm -mode :搜尋檔案許可權“必須要全部囊括 mode 的許可權”的檔案,舉例來說,

我們要搜尋 -rwxr--r-- ,亦即 0744 的檔案,使用 -perm -0744,

當一個檔案的許可權為 -rwsr-xr-x ,亦即 4755 時,也會被列出來,

因為 -rwsr-xr-x 的屬性已經囊括了 -rwxr--r-- 的屬性了。

-perm /mode :搜尋檔案許可權“包含任一 mode 的許可權”的檔案,舉例來說,我們搜尋

-rwxr-xr-x ,亦即 -perm /755 時,但一個檔案屬性為 -rw-------

也會被列出來,因為他有 -rw.... 的屬性存在!

範例五:找出檔名為 passwd 這個檔案

[[email protected] ~]# find / -name passwd

範例五-1:找出檔名包含了 passwd 這個關鍵字的檔案

[[email protected] ~]# find / -name "*passwd*"

# 利用這個 -name 可以搜尋檔名啊!預設是完整檔名,如果想要找關鍵字,

# 可以使用類似 * 的任意字元來處理

範例六:找出 /run 目錄下,檔案型別為 Socket 的檔名有哪些?

[[email protected] ~]# find /run -type s

# 這個 -type 的屬性也很有幫助喔!尤其是要找出那些怪異的檔案,

# 例如 socket 與 FIFO 檔案,可以用 find /run -type p 或 -type s 來找!

範例七:搜尋檔案當中含有 SGID 或 SUID 或 SBIT 的屬性

[[email protected] ~]# find / -perm /7000

# 所謂的 7000 就是 ---s--s--t ,那麼只要含有 s 或 t 的就列出,所以當然要使用 /7000,

# 使用 -7000 表示要同時含有 ---s--s--t 的所有三個許可權。而只需要任意一個,就是 /7000 ~瞭乎?

 

上述範例中比較有趣的就屬 -perm 這個選項啦!他的重點在找出特殊許可權的檔案囉! 我們知道 SUID 與 SGID 都可以設定在二進位制程式上,假設我想要找出來 /usr/bin, /usr/sbin 這兩個目錄下, 只要具有 SUID 或 SGID 就列出來該檔案,你可以這樣做:

[[email protected] ~]# find /usr/bin /usr/sbin -perm /6000

 

因為 SUID 是 4 分,SGID 2 分,總共為 6 分,因此可用 /6000 來處理這個許可權! 至於 find後面可以接多個目錄來進行搜尋!另外, find 本來就會搜尋次目錄,這個特色也要特別注意喔! 最後,我們再來看一下 find 還有什麼特殊功能吧!

 

選項與引數:

4\. 額外可進行的動作:

-exec command :command 為其他指令,-exec 後面可再接額外的指令來處理搜尋到的結果。

-print :將結果列印到螢幕上,這個動作是預設動作!

範例八:將上個範例找到的檔案使用 ls -l 列出來~

[[email protected] ~]# find /usr/bin /usr/sbin -perm /7000 -exec ls -l {} \;

# 注意到,那個 -exec 後面的 ls -l 就是額外的指令,指令不支援命令別名,

# 所以僅能使用 ls -l 不可以使用 ll 喔!注意注意!

範例九:找出系統中,大於 1MB 的檔案

[[email protected] ~]# find / -size +1M

 

find 的特殊功能就是能夠進行額外的動作(action)。我們將範例八的例子以圖解來說明如下:

該範例中特殊的地方有 {} 以及 \; 還有 -exec 這個關鍵字,這些東西的意義為:

{} 代表的是“由 find 找到的內容”,如上圖所示,find 的結果會被放置到 {} 位置中;

-exec 一直到 \; 是關鍵字,代表 find 額外動作的開始 (-exec) 到結束 (\;) ,在這中間的就是 find 指令內的額外動作。 在本例中就是“ ls -l {} ”囉!

因為“ ; ”在 bash 環境下是有特殊意義的,因此利用反斜線來跳脫。

通過圖 6.5.2 你應該就比較容易瞭解 -exec 到 \; 之間的意義了吧!

如果你要找的檔案是具有特殊屬性的,例如 SUID 、檔案擁有者、檔案大小等等, 那麼利用locate 是沒有辦法達成你的搜尋的!此時 find 就顯的很重要啦! 另外,find 還可以利用萬用字元來找尋檔名呢!舉例來說,你想要找出 /etc 下面檔名包含 httpd 的檔案, 那麼你就可以這樣做:

[[email protected] ~]# find /etc -name '*httpd*'

 

不但可以指定搜尋的目錄(連同次目錄),並且可以利用額外的選項與引數來找到最正確的檔名!真是好好用! 不過由於 find 在尋找資料的時後相當的操硬碟!所以沒事情不要使用find 啦!有更棒的指令可以取代呦!那就是上面提到的 whereis 與 locate 囉!