1. Linux 文件權限概念php
$ ls | 察看文件的指令 |
$ ls -al | 出全部的文件詳細的權限與屬性 (包含隱藏檔,就是文件名第一個字符爲『 . 』的文件) |
在你第一次以root身份登入Linux時, 若是你輸入上述指令後,應該有上列的幾個東西,先解釋一下上面七個字段個別的意思:html
這個地方最須要注意了!仔細看的話,你應該能夠發現這一欄其實共有十個字符:(圖2.1.1及圖2.1.2內的權限並沒有關係)node
例題:
如有一個文件的類型與權限數據爲『
-rwxr-xr--』,請說明其意義爲什麼?
答:
先將整個類型與權限數據分開查閱,並將十個字符整理成爲以下所示:
[-][rwx][r-x][r--]1 爲:表明這個文件名爲目錄或文件,本例中爲文件(-); 234爲:擁有者的權限,本例中爲可讀、可寫、可執行(rwx); 567爲:同羣組用戶權力,本例中爲可讀可執行(rx); 890爲:其餘用戶權力,本例中爲可讀(r) 同時注意到,rwx所在的位置是不會改變的,有該權限就會顯示字符,沒有該權限就變成減號(-)就是了。 |
另外,目錄與文件的權限意義並不相同,這是由於目錄與文件所記錄的數據內容不相同所致。 因爲目錄與文件的權限意義很是的重要,因此鳥哥將他獨立到2.3節目錄與文件之權限意義中再來談。linux
每一個文件都會將他的權限與屬性記錄到文件系統的i-node中,不過,咱們使用的目錄樹倒是使用文件名來記錄, 所以每一個檔名就會連結到一個i-node囉!這個屬性記錄的,就是有多少不一樣的檔名連結到相同的一個i-node號碼去就是了。 關於i-node的相關數據咱們會在第八章談到文件系統時再增強介紹的。web
在Linux系統下,你的帳號會附屬於一個或多個的羣組中。舉剛剛咱們提到的例子,class1, class2, class3均屬於projecta這個羣組,假設某個文件所屬的羣組爲projecta,且該文件的權限如圖2.1.2所示(-rwxrwx---), 則class1, class2, class3三人對於該文件都具備可讀、可寫、可執行的權限(看羣組權限)。 但若是是不屬於projecta的其餘帳號,對於此文件就不具備任何權限了。shell
這一欄的內容分別爲日期(月/日)及時間。若是這個文件被修改的時間距離如今過久了,那麼時間部分會僅顯示年份而已。 以下所示:數據庫
[root@www ~]# ls -l /etc/termcap /root/install.log -rw-r--r-- 1 root root 807103 Jan 7 2007 /etc/termcap -rw-r--r-- 1 root root 42304 Sep 4 18:26 /root/install.log # 如上所示,/etc/termcap 爲 2007 年所修改過的文件,離如今太遠之故; # 至於 install.log 是今年 (2009) 所創建的,因此就顯示完整的時間了。 |
若是想要顯示完整的時間格式,能夠利用ls的選項,亦即:『ls -l --full-time』就可以顯示出完整的時間格式了!包括年、月、日、時間喔。 另外,若是你當初是以繁體中文安裝你的Linux系統,那麼日期字段將會以中文來顯示。 惋惜的是,中文並無辦法在純文本的終端機模式中正確的顯示,因此此欄會變成亂碼。 那你就得要使用『LANG=en_US』來修改語系喔!vim
若是想要讓系統默認的語系變成英文的話,那麼你能夠修改系統配置文件『/etc/sysconfig/i18n』,利用第五章談到的nano來修改該文件的內容,使LANG這個變量成爲上述的內容便可。centos
這個字段就是檔名了。比較特殊的是:若是檔名以前多一個『 . 』,則表明這個文件爲『隱藏檔』,例如上表中的.gconf那一行,該文件就是隱藏檔。 你能夠使用『ls』及『ls -a』這兩個指令去感覺一下什麼是隱藏檔囉!數組
Tips: 對於更詳細的 ls 用法,還記得怎麼查詢嗎?對啦!使用 man ls 或 info ls 去看看他的基礎用法去!自我進修是很重要的, 由於『師傅帶進門,修行看我的!』,自古只有天才學生,沒有天才老師呦!加油吧!^_^ |
![]() |
這七個字段的意義是很重要的!務必清楚的知道各個字段表明的意義!尤爲是第一個字段的九個權限, 那是整個Linux文件權限的重點之一。底下咱們來作幾個簡單的練習,你就會比較清楚囉!
例題:
假設test1, test2, test3同屬於testgroup這個羣組,若是有下面的兩個文件,請說明兩個文件的擁有者與其相關的權限爲什麼?
答:
-rw-r--r-- 1 root root 238 Jun 18 17:22 test.txt -rwxr-xr-- 1 test1 testgroup 5238 Jun 19 10:25 ping_tsai
|
例題:
若是個人目錄爲底下的樣式,請問testgroup這個羣組的成員與其餘人(others)是否能夠進入本目錄?
答:
drwxr-xr-- 1 test1 testgroup 5238 Jun 19 10:25 groups/
|
與Windows系統不同的是,在Linux系統當中,每個文件都多加了不少的屬性進來,尤爲是羣組的概念,這樣有什麼用途呢? 其實,最大的用途是在『數據安全性』上面的。
可怕吧!所以,在你修改你的linux文件與目錄的屬性以前,必定要先搞清楚, 什麼數據是可變的,什麼是不可變的!千萬注意囉!接下來咱們來處理一下文件屬性與權限的變動吧!
咱們如今知道文件權限對於一個系統的安全重要性了,也知道文件的權限對於使用者與羣組的相關性, 那麼如何修改一個文件的屬性與權限呢?又!有多少文件的權限咱們能夠修改呢? 其實一個文件的屬性與權限有不少!咱們先介紹幾個經常使用於羣組、擁有者、各類身份的權限之修改的指令,以下所示:
改變一個文件的羣組真是很簡單的,直接以chgrp來改變便可,咦!這個指令就是change group的縮寫嘛!這樣就很好記了吧! ^_^。不過,請記得,要被改變的組名必需要在/etc/group文件內存在才行,不然就會顯示錯誤!
假設你是以root的身份登入Linux系統的,那麼在你的家目錄內有一個install.log的文件, 如何將該文件的羣組改變一下呢?假設你已經知道在/etc/group裏面已經存在一個名爲users的羣組, 可是testing這個羣組名字就不存在/etc/group當中了,此時改變羣組成爲users與testing分別會有什麼現象發生呢?
[root@www ~]# chgrp [-R] dirname/filename ... 選項與參數: -R : 進行遞歸(recursive)的持續變動,亦即連同次目錄下的全部文件、目錄 都更新成爲這個羣組之意。經常用在變動某一目錄內全部的文件之狀況。 範例: [root@www ~]# chgrp users install.log [root@www ~]# ls -l -rw-r--r-- 1 root users 68495 Jun 25 08:53 install.log [root@www ~]# chgrp testing install.log chgrp: invalid group name `testing' <== 發生錯誤訊息囉~找不到這個羣組名~ |
發現了嗎?文件的羣組被改爲users了,可是要改爲testing的時候, 就會發生錯誤~注意喔!發生錯誤訊息仍是要努力的查一查錯誤訊息的內容纔好! 將他英文翻譯成爲中文,就知道問題出在哪裏了。
如何改變一個文件的擁有者呢?很簡單呀!既然改變羣組是change group,那麼改變擁有者就是change owner囉!BINGO!那就是chown這個指令的用途,要注意的是, 用戶必須是已經存在系統中的帳號,也就是在/etc/passwd 這個文件中有紀錄的用戶名稱才能改變。
chown的用途還滿多的,他還能夠順便直接修改羣組的名稱呢!此外,若是要連目錄下的全部次目錄或文件同時更改文件擁有者的話,直接加上 -R 的選項便可!咱們來看看語法與範例:
[root@www ~]# chown [-R] 帳號名稱 文件或目錄 [root@www ~]# chown [-R] 帳號名稱:組名 文件或目錄 選項與參數: -R : 進行遞歸(recursive)的持續變動,亦即連同次目錄下的全部文件都變動 範例:將install.log的擁有者改成bin這個帳號: [root@www ~]# chown bin install.log [root@www ~]# ls -l -rw-r--r-- 1 bin users 68495 Jun 25 08:53 install.log 範例:將install.log的擁有者與羣組改回爲root: [root@www ~]# chown root:root install.log [root@www ~]# ls -l -rw-r--r-- 1 root root 68495 Jun 25 08:53 install.log |
Tips: 事實上,chown也能夠使用『chown user.group file』,亦即在擁有者與羣組間加上小數點『.』也行! 不過不少朋友設定帳號時,喜歡在帳號當中加入小數點(例如vbird.tsai這樣的帳號格式),這就會形成系統的誤判了! 因此咱們比較建議使用冒號『:』來隔開擁有者與羣組啦!此外,chown也能單純的修改所屬羣組呢! 例如『chown .sshd install.log』就是修改羣組~看到了嗎?就是那個小數點的用途! |
![]() |
知道如何改變文件的羣組與擁有者了,那麼何時要使用chown或chgrp呢?或許你會以爲奇怪吧? 是的,確實有時候須要變動文件的擁有者的,最多見的例子就是在複製文件給你以外的其餘人時, 咱們使用最簡單的cp指令來講明好了:
[root@www ~]# cp 來源文件 目標文件
|
假設你今天要將.bashrc這個文件拷貝成爲.bashrc_test檔名,且是要給bin這我的,你能夠這樣作:
[root@www ~]# cp .bashrc .bashrc_test [root@www ~]# ls -al .bashrc* -rw-r--r-- 1 root root 395 Jul 4 11:45 .bashrc -rw-r--r-- 1 root root 395 Jul 13 11:31 .bashrc_test <==新文件的屬性沒變 |
因爲複製行爲(cp)會複製執行者的屬性與權限,因此!怎麼辦?.bashrc_test仍是屬於root所擁有, 如此一來,即便你將文件拿給bin這個使用者了,那他仍然沒法修改的(看屬性/權限就知道了吧), 因此你就必需要將這個文件的擁有者與羣組修改一下囉!知道如何修改了吧?
文件權限的改變使用的是chmod這個指令,可是,權限的設定方法有兩種, 分別能夠使用數字或者是符號來進行權限的變動。咱們就來談一談:
r:4每種身份(owner/group/others)各自的三個權限(r/w/x)分數是須要累加的,例如當權限爲: [-rwxrwx---] 分數則是:
w:2
x:1
owner = rwx = 4+2+1 = 7因此等一下咱們設定權限的變動時,該文件的權限數字就是770啦!變動權限的指令chmod的語法是這樣的:
group = rwx = 4+2+1 = 7
others= --- = 0+0+0 = 0
[root@www ~]# chmod [-R] xyz 文件或目錄 選項與參數: xyz : 就是剛剛提到的數字類型的權限屬性,爲 rwx 屬性數值的相加。 -R : 進行遞歸(recursive)的持續變動,亦即連同次目錄下的全部文件都會變動 |
[root@www ~]# ls -al .bashrc -rw-r--r-- 1 root root 395 Jul 4 11:45 .bashrc [root@www ~]# chmod 777 .bashrc [root@www ~]# ls -al .bashrc -rwxrwxrwx 1 root root 395 Jul 4 11:45 .bashrc |
例題:
將剛剛你的.bashrc這個文件的權限修改回-rw-r--r--的狀況吧!
答:
-rw-r--r--的分數是644,因此指令爲:
chmod 644 .bashrc |
chmod | u g o a |
+(加入) -(除去) =(設定) |
r w x |
文件或目錄 |
[root@www ~]# chmod u=rwx,go=rx .bashrc # 注意喔!那個 u=rwx,go=rx 是連在一塊兒的,中間並無任何空格! [root@www ~]# ls -al .bashrc -rwxr-xr-x 1 root root 395 Jul 4 11:45 .bashrc |
[root@www ~]# ls -al .bashrc -rwxr-xr-x 1 root root 395 Jul 4 11:45 .bashrc [root@www ~]# chmod a+w .bashrc [root@www ~]# ls -al .bashrc -rwxrwxrwx 1 root root 395 Jul 4 11:45 .bashrc |
[root@www ~]# chmod a-x .bashrc [root@www ~]# ls -al .bashrc -rw-rw-rw- 1 root root 395 Jul 4 11:45 .bashrc |
如今咱們知道了Linux系統內文件的三種身份(擁有者、羣組與其餘人),知道每種身份都有三種權限(rwx), 已知道可以使用chown, chgrp, chmod去修改這些權限與屬性,固然,利用ls -l去觀察文件也沒問題。 前兩小節也談到了這些文件權限對於數據安全的重要性。那麼,這些文件權限對於通常文件與目錄文件有何不一樣呢? 有大大的不一樣啊!底下就讓鳥哥來講清楚,講明白!
文件是實際含有數據的地方,包括通常文本文件、數據庫內容文件、二進制可執行文件(binary program)等等。 所以,權限對於文件來講,他的意義是這樣的:
那個可讀(r)表明讀取文件內容是還好了解,那麼可執行(x)呢?這裏你就必需要當心啦! 由於在Windows底下一個文件是否具備執行的能力是藉由『 擴展名 』來判斷的, 例如:.exe, .bat, .com 等等,可是在Linux底下,咱們的文件是否能被執行,則是藉由是否具備『x』這個權限來決定的!跟檔名是沒有絕對的關係的!
至於最後一個w這個權限呢?當你對一個文件具備w權限時,你能夠具備寫入/編輯/新增/修改文件的內容的權限, 但並不具有有刪除該文件自己的權限!對於文件的rwx來講, 主要都是針對『文件的內容』而言,與文件檔名的存在與否沒有關係喔!由於文件記錄的是實際的數據嘛!
文件是存放實際數據的所在,那麼目錄主要是儲存啥玩意啊?目錄主要的內容在記錄文件名列表,文件名與目錄有強烈的關連啦! 因此若是是針對目錄時,那個 r, w, x 對目錄是什麼意義呢?
大體的目錄權限概念是這樣,底下咱們來看幾個範例,讓你瞭解一下啥是目錄的權限囉!
例題:
有個目錄的權限以下所示:
答:
drwxr--r-- 3 root root 4096 Jun 25 08:35 .ssh系統有個帳號名稱爲vbird,這個帳號並無支持root羣組,請問vbird對這個目錄有何權限?是否可切換到此目錄中?
vbird對此目錄僅具備r的權限,所以vbird能夠查詢此目錄下的文件名列表。由於vbird不具備x的權限, 所以vbird並不能切換到此目錄內!(至關重要的概念!)
|
上面這個例題中由於vbird具備r的權限,由於是r乍看之下好像就具備能夠進入此目錄的權限,其實那是錯的。 能不能進入某一個目錄,只與該目錄的x權限有關啦!此外, 工做目錄對於指令的執行是很是重要的,若是你在某目錄下不具備x的權限, 那麼你就沒法切換到該目錄下,也就沒法執行該目錄下的任何指令,即便你具備該目錄的r的權限。
不少朋友在架設網站的時候都會卡在一些權限的設定上,他們開放目錄數據給因特網的任何人來瀏覽, 卻只開放r的權限,如上面的範例所示那樣,那樣的結果就是致使網站服務器軟件沒法到該目錄下讀取文件(最多隻能看到檔名), 最終用戶老是沒法正確的查閱到文件的內容(顯示權限不足啊!)。要注意:要開放目錄給任何人瀏覽時,應該至少也要給予r及x的權限,但w權限不可隨便給! 爲何w不能隨便給,咱們來看下一個例子:
例題:
假設有個帳號名稱爲dmtsai,他的家目錄在/home/dmtsai/,dmtsai對此目錄具備[rwx]的權限。 若在此目錄下有個名爲the_root.data的文件,該文件的權限以下:
答:
-rwx------ 1 root root 4365 Sep 19 23:20 the_root.data請問dmtsai對此文件的權限爲什麼?能否刪除此文件?
如上所示,因爲dmtsai對此文件來講是『others』的身份,所以這個文件他沒法讀、沒法編輯也沒法執行, 也就是說,他沒法變更這個文件的內容就是了。
可是因爲這個文件在他的家目錄下, 他在此目錄下具備rwx的完整權限,所以對於the_root.data這個『檔名』來講,他是可以『刪除』的! 結論就是,dmtsai這個用戶可以刪除the_root.data這個文件! |
仍是看不太懂?有聽沒有懂喔!不要緊~咱們底下就來設計一個練習, 讓你實際玩玩看,應該就可以比較近入情況啦!不過,因爲不少指令咱們尚未教, 因此底下的指令有的先了解便可,詳細的指令用法咱們會在後面繼續介紹的。
咱們用root的身份在全部人均可以工做的/tmp目錄中創建一個名爲testing的目錄, 該目錄的權限爲744且目錄擁有者爲root。另外,在testing目錄下在創建一個空的文件, 檔名亦爲testing。創建目錄可用mkdir(make directory),創建空文件可用touch(下一章會說明)來處理。 因此過程以下所示:
[root@www ~]# cd /tmp <==切換工做目錄到/tmp [root@www tmp]# mkdir testing <==創建新目錄 [root@www tmp]# chmod 744 testing <==變動權限 [root@www tmp]# touch testing/testing <==創建空的文件 [root@www tmp]# chmod 600 testing/testing <==變動權限 [root@www tmp]# ls -ald testing testing/testing drwxr--r-- 2 root root 4096 Sep 19 16:01 testing -rw------- 1 root root 0 Sep 19 16:01 testing/testing # 仔細看一下,目錄的權限是 744 ,且所屬羣組與使用者均是 root 喔! # 那麼在這樣的狀況底下,通常身份用戶對這個目錄/文件的權限爲什麼? |
在上面的例子中,雖然目錄是744的權限設定,通常用戶應該能有 r 的權限, 但這樣的權限使用者能作啥事呢?假設鳥哥的系統中含有一個帳號名爲 vbird 的, 咱們能夠透過『 su - vbird 』這個指令來變換身份喔!看看底下的操做先!
[root@www tmp]# su - vbird <==切換身份成爲 vbird 囉! [vbird@www ~]$ cd /tmp <==看一下,身份變了喔!提示字符也變成 $ 了! [vbird@www tmp]$ ls -l testing/ ?--------- ? ? ? ? ? testing # 由於具備 r 的權限能夠查詢檔名。不過權限不足(沒有x),因此會有一堆問號。 [vbird@www tmp]$ cd testing/ -bash: cd: testing/: Permission denied # 由於不具備 x ,因此固然沒有進入的權限啦!有沒有呼應前面的權限說明啊! |
上面的練習咱們知道了只有r確實可讓用戶讀取目錄的文件名列表,不過詳細的信息卻仍是讀不到的, 同時也不能將該目錄變成工做目錄(用 cd 進入該目錄之意)。那若是咱們讓該目錄變成用戶的, 那麼用戶在這個目錄底下是否可以刪除文件呢?底下的練習作看看:
[vbird@www tmp]$ exit <==讓 vbird 變回本來的 root 身份喔! [root@www tmp]# chown vbird testing <==修改權限,讓vbird擁有此目錄 [root@www tmp]# su - vbird <==再次變成vbird來操做 [vbird@www ~]$ cd /tmp/testing <==能夠進入目錄了呢! [vbird@www testing]$ ls -l -rw------- 1 root root 0 Sep 19 16:01 testing <==文件不是vbird的! [vbird@www testing]$ rm testing <==嘗試刪除這個文件看看! rm: remove write-protected regular empty file `testing'? y # 居然能夠刪除!這樣理解了嗎?! |
透過上面這個簡單的步驟,你就能夠清楚的知道, x 在目錄當中是與『可否進入該目錄』有關, 至於那個 w 則具備至關重要的權限,由於他可讓使用者刪除、更新、新建文件或目錄, 是個很重要的參數啊!這樣能夠理解了嗎?! ^_^
咱們在基礎篇一直強調一個概念,那就是:任何裝置在Linux底下都是文件, 不只如此,連數據溝通的接口也有專屬的文件在負責~因此,你會了解到,Linux的文件種類真的不少~ 除了前面提到的通常文件(-)與目錄文件(d)以外,還有哪些種類的文件呢?
咱們在剛剛提到使用『ls -l』觀察到第一欄那十個字符中,第一個字符爲文件的類型。 除了常見的通常文件(-)與目錄文件(d)以外,還有哪些種類的文件類型呢?
除了設備文件是咱們系統中很重要的文件,最好不要隨意修改以外(一般他也不會讓你修改的啦!), 另外一個比較有趣的文件就是連結檔。若是你經常將應用程序捉到桌面來的話,你就應該知道在 Windows底下有所謂的『快捷方式』。一樣的,你能夠將 linux下的連結檔簡單的視爲一個文件或目錄的快捷方式。 至於socket與FIFO文件比較難理解,由於這兩個咚咚與程序(process)比較有關係, 這個等到將來你瞭解process以後,再回來查閱吧!此外, 你也能夠透過man fifo及man socket來查閱系統上的說明!
基本上,Linux的文件是沒有所謂的『擴展名』的,咱們剛剛就談過,一個Linux文件能不能被執行,與他的第一欄的十個屬性有關, 與檔名根本一點關係也沒有。這個觀念跟Windows的狀況不相同喔!在Windows底下, 能被執行的文件擴展名一般是 .com .exe .bat等等,而在Linux底下,只要你的權限當中具備x的話,例如[ -rwx-r-xr-x ] 即表明這個文件能夠被執行喔!
不過,能夠被執行跟能夠執行成功是不同的~舉例來講,在root家目錄下的install.log 是一個純文本檔,若是經由修改權限成爲 -rwxrwxrwx 後,這個文件可以真的執行成功嗎? 固然不行~由於他的內容根本就沒有能夠執行的數據。因此說,這個x表明這個文件具備可執行的能力, 可是能不能執行成功,固然就得要看該文件的內容囉~
雖然如此,不過咱們仍然但願能夠藉由擴展名來了解該文件是什麼東西,因此, 一般咱們仍是會以適當的擴展名來表示該文件是什麼種類的。底下有數種經常使用的擴展名:
基本上,Linux系統上的文件名真的只是讓你瞭解該文件可能的用途而已, 真正的執行與否仍然須要權限的規範才行!例如雖然有一個文件爲可執行文件, 如常見的/bin/ls這個顯示文件屬性的指令,不過,若是這個文件的權限被修改爲沒法執行時, 那麼ls就變成不能執行囉!
上述的這種問題最常發生在文件傳送的過程當中。例如你在網絡上下載一個可執行文件,可是恰恰在你的 Linux系統中就是沒法執行!呵呵!那麼就是可能文件的屬性被改變了!不要懷疑,從網絡上傳送到你的 Linux系統中,文件的屬性與權限確實是會被改變的喔
2. 目錄與路徑:
由第六章Linux的文件權限與目錄配置中透過FHS瞭解了Linux的『樹狀目錄』概念以後, 接下來就得要實際的來搞定一些基本的路徑問題了!這些目錄的問題當中,最重要的莫過於第六章也談過的『絕對路徑』與『相對路徑』的意義啦! 絕對/相對路徑的寫法並不相同,要特別注意。此外,當你下達命令時,該命令是透過什麼功能來取得的? 這與PATH這個變量有關呢!底下就讓咱們來談談羅!
在開始目錄的切換以前,你必需要先了解一下所謂的『路徑(PATH)』, 有趣的是:什麼是『相對路徑』與『絕對路徑』? 雖然前一章已經稍微針對這個議題提過一次,不過,這裏不厭其煩的再次的強調一下!
那麼相對路徑與絕對路徑有什麼了不得呀?喝!那可真的是了不得了!假設你寫了一個軟件, 這個軟件共須要三個目錄,分別是 etc, bin, man 這三個目錄,然而由於不一樣的人喜歡安裝在不一樣的目錄之下, 假設甲安裝的目錄是 /usr/local/packages/etc, /usr/local/packages/bin 及 /usr/local/packages/man ,不過乙卻喜歡安裝在 /home/packages/etc, /home/packages/bin, /home/packages/man 這三個目錄中,請問若是須要用到絕對路徑的話,那麼是否很麻煩呢?是的! 如此一來每一個目錄下的東西就很難對應的起來!這個時候相對路徑的寫法就顯的特別的重要了!
此外,若是你跟鳥哥同樣,喜歡將路徑的名字寫的很長,好讓本身知道那個目錄是在幹什麼的,例如: /cluster/raid/output/taiwan2006/smoke 這個目錄,而另外一個目錄在 /cluster/raid/output/taiwan2006/cctm ,那麼我從第一個要到第二個目錄去的話,怎麼寫比較方便? 固然是『 cd ../cctm 』比較方便羅!對吧!
可是對於檔名的正確性來講,『絕對路徑的正確度要比較好~』。 通常來講,鳥哥會建議你,若是是在寫程序 (shell scripts) 來管理系統的條件下,務必使用絕對路徑的寫法。 怎麼說呢?由於絕對路徑的寫法雖然比較麻煩,可是能夠確定這個寫法絕對不會有問題。 若是使用相對路徑在程序當中,則可能由於你運行的工做環境不一樣,致使一些問題的發生。 這個問題在工做排程(at, cron, 第十六章)當中尤爲重要!這個現象咱們在十三章、shell script時,會再次的提醒你喔! ^_^
咱們以前稍微提到變換目錄的命令是cd,還有哪些能夠進行目錄操做的命令呢? 例如建立目錄啊、刪除目錄之類的~還有,得要先知道的,就是有哪些比較特殊的目錄呢? 舉例來講,底下這些就是比較特殊的目錄,得要用力的記下來才行:
. 表明此層目錄 .. 表明上一層目錄 - 表明前一個工做目錄 ~ 表明『目前使用者身份』所在的家目錄 ~account 表明 account 這個使用者的家目錄(account是個賬號名稱)
|
須要特別注意的是:在全部目錄底下都會存在的兩個目錄,分別是『.』與『..』 分別表明此層與上一級目錄的意思。那麼來思考一下底下這個例題:
例題:
請問在Linux底下,根目錄下有沒有上一級目錄(..)存在?
答:
若使用『 ls -al / 』去查詢,能夠看到根目錄下確實存在 . 與 .. 兩個目錄,再仔細的查閱, 可發現這兩個目錄的屬性與權限徹底一致,這表明
根目錄的上一層(..)與根目錄本身(.)是同一個目錄。
|
底下咱們就來談一談幾個常見的處理目錄的命令吧:
咱們知道vbird這個使用者的家目錄是/home/vbird/,而root家目錄則是/root/,假設我以root身份在 Linux系統中,那麼簡單的說明一下這幾個特殊的目錄的意義是:
[root@www ~]# cd [相對路徑或絕對路徑] # 最重要的就是目錄的絕對路徑與相對路徑,還有一些特殊目錄的符號羅! [root@www ~]# cd ~vbird # 表明去到 vbird 這個使用者的家目錄,亦即 /home/vbird [root@www vbird]# cd ~ # 表示回到本身的家目錄,亦便是 /root 這個目錄 [root@www ~]# cd # 沒有加上任何路徑,也仍是表明回到本身家目錄的意思喔! [root@www ~]# cd .. # 表示去到目前的上一級目錄,亦便是 /root 的上一級目錄的意思; [root@www /]# cd - # 表示回到剛剛的那個目錄,也就是 /root 羅~ [root@www ~]# cd /var/spool/mail # 這個就是絕對路徑的寫法!直接指定要去的完整路徑名稱! [root@www mail]# cd ../mqueue # 這個是相對路徑的寫法,咱們由/var/spool/mail 去到/var/spool/mqueue 就這樣寫! |
cd是Change Directory的縮寫,這是用來變換工做目錄的命令。注意,目錄名稱與cd命令之間存在一個空格。 一登錄Linux系統後,root會在root的家目錄!那回到上一層目錄能夠用『 cd .. 』。 利用相對路徑的寫法必需要確認你目前的路徑才能正確的去到想要去的目錄。例如上表當中最後一個例子, 你必需要確認你是在/var/spool/mail當中,而且知道在/var/spool當中有個mqueue的目錄才行啊~ 這樣才能使用cd ../mqueue去到正確的目錄說,不然就要直接輸入cd /var/spool/mqueue羅~
其實,咱們的提示字節,亦即那個 [root@www ~]# 當中,就已經有指出目前的目錄了, 剛登錄時會到本身的家目錄,而家目錄還有一個代碼,那就是『 ~ 』符號! 例如上面的例子能夠發現,使用『 cd ~ 』能夠回到我的的家目錄裏頭去呢! 另外,針對 cd 的使用方法,若是僅輸入 cd 時,表明的就是『 cd ~ 』的意思喔~ 亦便是會回到本身的家目錄啦!而那個『 cd - 』比較難以理解,請自行多作幾回練習, 就會比較明白了。
Tips: 仍是要一再地提醒,咱們的 Linux 的默認命令列模式 (bash shell) 具備文件補齊功能, 你要經常利用 [tab] 按鍵來達成你的目錄完整性啊!這但是個好習慣啊~ 能夠避免你按錯鍵盤輸入錯字說~ ^_^ |
![]() |
[root@www ~]# pwd [-P] 選項與參數: -P :顯示出確實的路徑,而非使用連結 (link) 路徑。 範例:單純顯示出目前的工做目錄: [root@www ~]# pwd /root <== 顯示出目錄啦~ 範例:顯示出實際的工做目錄,而非連結檔自己的目錄名而已 [root@www ~]# cd /var/mail <==注意,/var/mail是一個連結檔 [root@www mail]# pwd /var/mail <==列出目前的工做目錄 [root@www mail]# pwd -P /var/spool/mail <==怎麼回事?有沒有加 -P 差不少~ [root@www mail]# ls -ld /var/mail lrwxrwxrwx 1 root root 10 Sep 4 17:54 /var/mail -> spool/mail # 看到這裏應該知道爲啥了吧?由於 /var/mail 是連結檔,連結到 /var/spool/mail # 因此,加上 pwd -P 的選項後,會不以連結檔的數據顯示,而是顯示正確的完整路徑啊! |
pwd是Print Working Directory的縮寫,也就是顯示目前所在目錄的命令, 例如在上個表格最後的目錄是/var/mail這個目錄,可是提示字節僅顯示mail, 若是你想要知道目前所在的目錄,能夠輸入pwd便可。此外,由於不少的套件所使用的目錄名稱都相同,例如 /usr/local/etc還有/etc,可是一般Linux僅列出最後面那一個目錄而已,這個時候你就能夠使用pwd 來知道你的所在目錄羅!省得搞錯目錄,結果...
其實有趣的是那個 -P 的選項啦!他可讓咱們取得正確的目錄名稱,而不是以連結檔的路徑來顯示的。 若是你使用的是CentOS 5.x的話,剛恰好/var/mail是/var/spool/mail的連結檔, 因此,透過到/var/mail下達pwd -P就可以知道這個選項的意義羅~ ^_^
[root@www ~]# mkdir [-mp] 目錄名稱 選項與參數: -m :配置文件的權限喔!直接配置,不須要看默認權限 (umask) 的臉色~ -p :幫助你直接將所須要的目錄(包含上一級目錄)遞迴建立起來! 範例:請到/tmp底下嘗試建立數個新目錄看看: [root@www ~]# cd /tmp [root@www tmp]# mkdir test <==建立一名爲 test 的新目錄 [root@www tmp]# mkdir test1/test2/test3/test4 mkdir: cannot create directory `test1/test2/test3/test4': No such file or directory <== 沒辦法直接建立此目錄啊! [root@www tmp]# mkdir -p test1/test2/test3/test4 # 加了這個 -p 的選項,能夠自行幫你建立多層目錄! 範例:建立權限爲rwx--x--x的目錄 [root@www tmp]# mkdir -m 711 test2 [root@www tmp]# ls -l drwxr-xr-x 3 root root 4096 Jul 18 12:50 test drwxr-xr-x 3 root root 4096 Jul 18 12:53 test1 drwx--x--x 2 root root 4096 Jul 18 12:54 test2 # 仔細看上面的權限部分,若是沒有加上 -m 來強制配置屬性,系統會使用默認屬性。 # 那麼你的默認屬性爲什麼?這要透過底下介紹的 umask 才能瞭解喔! ^_^ |
若是想要建立新的目錄的話,那麼就使用mkdir (make directory)吧! 不過,在默認的狀況下, 你所須要的目錄得一層一層的建立才行!例如:假如你要建立一個目錄爲 /home/bird/testing/test1,那麼首先必需要有 /home 而後 /home/bird ,再來 /home/bird/testing 都必需要存在,才能夠建立 /home/bird/testing/test1 這個目錄!假如沒有 /home/bird/testing 時,就沒有辦法建立 test1 的目錄羅!
不過,如今有個更簡單有效的方法啦!那就是加上 -p 這個選項喔!你能夠直接下達:『 mkdir -p /home/bird/testing/test1』 則系統會自動的幫你將 /home, /home/bird, /home/bird/testing 依序的建立起目錄!而且, 若是該目錄原本就已經存在時,系統也不會顯示錯誤信息喔!挺快樂的吧! ^_^。 不過鳥哥不建議經常使用-p這個選項,由於擔憂若是你打錯字,那麼目錄名稱就會變的亂七八糟的!
另外,有個地方你必需要先有概念,那就是『默認權限』的地方。咱們能夠利用 -m 來強制給予一個新的目錄相關的權限, 例如上表當中,咱們給予 -m 711 來給予新的目錄 drwx--x--x 的權限。不過,若是沒有給予 -m 選項時, 那麼默認的新建目錄權限又是什麼呢?這個跟 umask 有關,咱們在本章後頭會加以介紹的。
[root@www ~]# rmdir [-p] 目錄名稱 選項與參數: -p :連同上一級『空的』目錄也一塊兒刪除 範例:將於mkdir範例中建立的目錄(/tmp底下)刪除掉! [root@www tmp]# ls -l <==看看有多少目錄存在? drwxr-xr-x 3 root root 4096 Jul 18 12:50 test drwxr-xr-x 3 root root 4096 Jul 18 12:53 test1 drwx--x--x 2 root root 4096 Jul 18 12:54 test2 [root@www tmp]# rmdir test <==可直接刪除掉,沒問題 [root@www tmp]# rmdir test1 <==由於尚有內容,因此沒法刪除! rmdir: `test1': Directory not empty [root@www tmp]# rmdir -p test1/test2/test3/test4 [root@www tmp]# ls -l <==您看看,底下的輸出中test與test1不見了! drwx--x--x 2 root root 4096 Jul 18 12:54 test2 # 瞧!利用 -p 這個選項,馬上就能夠將 test1/test2/test3/test4 一次刪除~ # 不過要注意的是,這個 rmdir 僅能『刪除空的目錄』喔! |
若是想要刪除舊有的目錄時,就使用rmdir吧!例如將剛剛建立的test殺掉,使用『 rmdir test 』便可!請注意呦!目錄須要一層一層的刪除才行!並且被刪除的目錄裏面一定不能存在其餘的目錄或文件! 這也是所謂的空的目錄(empty directory)的意思啊!那若是要將全部目錄下的東西都殺掉呢?! 這個時候就必須使用『 rm -r test 』羅!不過,仍是使用 rmdir 比較不危險!你也能夠嘗試以 -p 的選項加入,來刪除上一級的目錄喔!
通過第六章FHS的說明後,咱們知道查閱文件屬性的命令ls完整檔名爲:/bin/ls(這是絕對路徑), 那你會不會以爲很奇怪:『爲何我能夠在任何地方運行/bin/ls這個命令呢? 』 爲何我在任何目錄下輸入 ls 就必定能夠顯示出一些信息而不會說找不到該 /bin/ls 命令呢? 這是由於環境變量 PATH 的幫助所致呀!
當咱們在運行一個命令的時候,舉例來講『ls』好了,系統會依照PATH的配置去每一個PATH定義的目錄下搜尋檔名爲ls的可運行檔, 若是在PATH定義的目錄中含有多個檔名爲ls的可運行檔,那麼先搜尋到的同名命令先被運行!
如今,請下達『echo $PATH』來看看到底有哪些目錄被定義出來了? echo有『顯示、印出』的意思,而 PATH 前面加的 $ 表示後面接的是變量,因此會顯示出目前的 PATH !
範例:先用root的身份列出搜尋的路徑爲什麼? [root@www ~]# echo $PATH /usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin :/bin:/usr/sbin:/usr/bin:/root/bin <==這是同一行! 範例:用vbird的身份列出搜尋的路徑爲什麼? [root@www ~]# su - vbird [vbird@www ~]# echo $PATH /usr/kerberos/bin:/usr/local/bin:/bin:/usr/bin:/home/vbird/bin # 仔細看,通常用戶vbird的PATH中,並不包含任何『sbin』的目錄存在喔! |
PATH(必定是大寫)這個變量的內容是由一堆目錄所組成的,每一個目錄中間用冒號(:)來隔開, 每一個目錄是有『順序』之分的。仔細看一下上面的輸出,你能夠發現到不管是root仍是vbird都有/bin 這個目錄在PATH變量內,因此固然就可以在任何地方運行ls來找到/bin/ls運行檔羅!
咱們用幾個範例來讓你瞭解一下,爲何PATH是那麼重要的項目!
例題:
請問你能不能使用通常身份使用者下達ifconfig eth0這個命令呢?
答:
如上面的範例所示,當你使用vbird這個賬號運行ifconfig時,會出現『-bash: ifconfig: command not found』的字樣, 由於ifconfig的是放置到/sbin底下,而由上表的結果中咱們能夠發現vbird的PATH並無配置/sbin, 因此默認沒法運行。
可是你能夠使用『/sbin/ifconfig eth0』來運行這個命令喔!由於通常用戶仍是能夠使用 ifconfig來查詢系統IP的參數, 既然PATH沒有規範到/sbin,那麼咱們使用『絕對路徑』也能夠運行到該命令的! |
例題:
假設你是root,若是你將ls由/bin/ls移動成爲/root/ls(可用『mv /bin/ls /root』命令達成),而後你本身自己也在/root目錄下, 請問(1)你能不能直接輸入ls來運行?(2)若不能,你該如何運行ls這個命令?(3)若要直接輸入ls便可運行,又該如何進行?
答:
由於這個例題的重點是將某個運行檔移動到非正規目錄去,因此咱們先要進行底下的動做才行:(務必使用root的身份)
(2)由於這個ls確實存在於/root底下,並非被刪除了!因此咱們能夠透過使用絕對路徑或者是相對路徑直接指定這個運行檔檔名, 底下的兩個方法都可以運行ls這個命令:
|
例題:
若是我有兩個ls命令在不一樣的目錄中,例如/usr/local/bin/ls與/bin/ls那麼當我下達 ls 的時候,哪一個ls會被運行?
答:
那還用說,就找出 PATH 裏面哪一個目錄先被查詢,則那個目錄下的命令就會被先運行了!
|
例題:
爲何PATH搜尋的目錄不加入本目錄(.)?加入本目錄的搜尋不是也不錯?
答:
若是在PATH中加入本目錄(.)後,確實咱們就可以在命令所在目錄進行命令的運行了。 可是由於你的工做目錄並不是固定(經常會使用cd來切換到不一樣的目錄), 所以可以運行的命令會有變更(由於每一個目錄底下的可運行檔都不相同嘛!),這對使用者來講並不是好事。
另外,若是有個壞心使用者在/tmp底下作了一個命令,由於/tmp是你們都可以寫入的環境,因此他固然能夠這樣作。 假設該命令可能會竊取使用者的一些數據,若是你使用root的身份來運行這個命令,那不是很糟糕? 若是這個命令的名稱又是常常會被用到的ls時,那『中標』的機率就更高了! 因此, 爲了安全起見,不建議將『.』加入PATH的搜尋目錄中。 |
而由上面的幾個例題咱們也能夠知道幾件事情:
對於PATH更詳細的『變量』說明,咱們會在第三篇的bash shell中詳細說明的!
認識 BASH 這個 Shell
咱們在第一章 Linux 是什麼當中提到了: 管理整個計算機硬件的實際上是操做系統的核心 (kernel),這個核心是須要被保護的! 因此咱們通常使用者就只能透過 shell 來跟核心溝通,以讓核心達到咱們所想要達到的工做。 那麼系統有多少 shell 可用呢?爲何咱們要使用 bash 啊?底下分別來談一談喔!
這應該是個蠻有趣的話題:『什麼是 Shell 』?相信只要摸過計算機,對於操做系統 (不管是 Linux 、 Unix 或者是 Windows) 有點概念的朋友們大多聽過這個名詞,由於只要有『操做系統』那麼就離不開 Shell 這個東西。不過,在討論 Shell 以前,咱們先來了解一下計算機的運行情況吧! 舉個例子來講:當你要計算機傳輸出來『音樂』的時候,你的計算機須要什麼東西呢?
這就是基本的一個輸出聲音所須要的步驟!也就是說,你必需要『輸入』一個命令以後, 『硬件』纔會透過你下達的命令來工做!那麼硬件如何知道你下達的命令呢?那就是 kernel (核心) 的控制工做了!也就是說,咱們必需要透過『 Shell 』將咱們輸入的命令與 Kernel 溝通,好讓 Kernel 能夠控制硬件來正確無誤的工做! 基本上,咱們能夠透過底下這張圖來講明一下:
咱們在第零章內的操做系統小節曾經提到過, 操做系統實際上是一組軟件,因爲這組軟件在控制整個硬件與管理系統的活動監測, 若是這組軟件能被用戶隨意的操做,若使用者應用不當,將會使得整個系統崩潰!由於操做系統管理的就是整個硬件功能嘛! 因此固然不可以隨便被一些沒有管理能力的終端用戶隨意使用囉!
可是咱們老是須要讓用戶操做系統的,因此就有了在操做系統上面發展的應用程序啦!用戶能夠透過應用程序來指揮核心, 讓核心達成咱們所須要的硬件任務!若是考慮如第零章所提供的操做系統圖標(圖4.2.1), 咱們能夠發現應用程序實際上是在最外層,就如同雞蛋的外殼同樣,所以這個咚咚也就被稱呼爲殼程序 (shell) 囉!
其實殼程序的功能只是提供用戶操做系統的一個接口,所以這個殼程序須要能夠呼叫其餘軟件纔好。 咱們在第五章到第十章提到過不少命令,包括 man, chmod, chown, vi, fdisk, mkfs 等等命令,這些命令都是獨立的應用程序, 可是咱們能夠透過殼程序 (就是命令列模式) 來操做這些應用程序,讓這些應用程序呼叫核心來運行所需的工做哩! 這樣對於殼程序是否有了必定的概念了?
Tips: 也就是說,只要可以操做應用程序的接口都可以稱爲殼程序。狹義的殼程序指的是命令列方面的軟件,包括本章要介紹的 bash 等。 廣義的殼程序則包括圖形接口的軟件!由於圖形接口其實也可以操做各類應用程序來呼叫核心工做啊! 不過在本章中,咱們主要仍是在使用 bash 啦! |
![]() |
文字接口的 shell 是很很差學的,可是學了以後好處多多!因此, 在這裏鳥哥要先對您進行一些心理建設,先來了解一下爲啥學習 shell 是有好處的,這樣你纔會有信心繼續玩下去 ^_^
鳥哥經常聽到這個問題:『我幹嗎要學習 shell 呢? 不是已經有不少的工具能夠提供我配置個人主機了?我爲什麼要花這麼多時間去學命令呢?不是以 X Window 按一按幾個按鈕就能夠搞定了嗎?』唉~仍是得一再地強調, X Window 還有 Web 接口的配置工具例如 Webmin (注1) 是真的好用的傢伙, 他真的能夠幫助咱們很簡易的配置好咱們的主機,甚至是一些很進階的配置均可以幫咱們搞定。
可是鳥哥在前面的章節裏面也已經提到過至關屢次了, X Window 與 web 接口的工具,他的接口雖然親善,功能雖然強大, 但畢竟他是將全部利用到的軟件都整合在一塊兒的一組應用程序而已, 並不是是一個完整的套件,因此某些時候當你升級或者是使用其餘套件管理模塊 (例如 tarball 而非 rpm 文件等等) 時,就會形成配置的困擾了。甚至不一樣的 distribution 所設計的 X window 接口也都不相同,這樣也形成學習方面的困擾。
文字接口的 shell 就不一樣了!幾乎各家 distributions 使用的 bash 都是同樣的!如此一來, 你就可以輕輕鬆鬆的轉換不一樣的 distributions ,就像武俠小說裏面提到的『一法通、萬法通!』
此外,Linux 的管理經常須要透過遠程聯機,而聯機時文字接口的傳輸速度必定比較快, 並且,較不容易出現斷線或者是信息外流的問題,所以,shell 真的是得學習的一項工具。並且,他可讓您更深刻 Linux ,更瞭解他,而不是隻會按一按鼠標而已!所謂『天助自助者!』多摸一點文本模式的東西,會讓你與 Linux 更親近呢!
有些朋友也很可愛,常會說:『我學這麼多幹什麼? 又不經常使用,也用不到!』嘿嘿!有沒有聽過『書到用時方恨少?』 當你的主機一切安然無恙的時候,您固然會以爲好像學這麼多的東西一點幫助也沒有呀! 萬一,某一天真的不幸給他中標了,您該如何是好?是直接從新安裝? 仍是先追蹤入侵來源後進行漏洞的修補?或者是乾脆就關站好了?這固然涉及不少的考慮, 但就以鳥哥的觀點來看,多學一點老是好的,尤爲咱們能夠有備而無患嘛!甚至學的不精也沒有關係,瞭解概念也就 OK 啦!畢竟沒有人要您必定要背這麼多的內容啦!瞭解概念就很了不得了!
此外,若是你真的有心想要將您的主機管理的好,那麼良好的 shell 程序編寫是必定須要的啦!就鳥哥本身來講,鳥哥管理的主機雖然還不算多, 只有區區不到十部,可是若是每部主機都要花上幾十分鐘來查閱他的登陸文件信息以及相關的信息, 那麼鳥哥可能會瘋掉!基本上,也太沒有效率了!這個時候,若是可以藉由 shell 提供的數據流重導向以及管線命令,呵呵! 那麼鳥哥分析登陸信息只要花費不到十分鐘就能夠看完全部的主機之重要信息了!至關的好用呢!
因爲學習 shell 的好處真的是多多啦!因此,若是你是個系統管理員,或者有心想要管理系統的話,那麼 shell 與 shell scripts 這個東西真的有必要看一看!由於他就像『打通任督二脈,任何武功都能隨你應用』的說!
知道什麼是 Shell 以後,那麼咱們來了解一下 Linux 使用的是哪個 shell 呢?什麼!哪個?難道說 shell 不就是『一個 shell 嗎?』哈哈!那可不!因爲早年的 Unix 年代,發展者衆,因此因爲 shell 依據發展者的不一樣就有許多的版本,例如常聽到的 Bourne SHell (sh) 、在 Sun 裏頭默認的 C SHell、 商業上經常使用的 K SHell、, 還有 TCSH 等等,每一種 Shell 都各有其特色。至於 Linux 使用的這一種版本就稱爲『 Bourne Again SHell (簡稱 bash) 』,這個 Shell 是 Bourne Shell 的加強版本,也是基準於 GNU 的架構下發展出來的呦!
在介紹 shell 的優勢以前,先來講一說 shell 的簡單歷史吧(注2):第一個流行的 shell 是由 Steven Bourne 發展出來的,爲了記念他因此就稱爲 Bourne shell ,或直接簡稱爲 sh !然後來另外一個廣爲流傳的 shell 是由柏克萊大學的 Bill Joy 設計依附於 BSD 版的 Unix 系統中的 shell ,這個 shell 的語法有點相似 C 語言,因此才得名爲 C shell ,簡稱爲 csh !因爲在學術界 Sun 主機勢力至關的龐大,而 Sun 主要是 BSD 的分支之一,因此 C shell 也是另外一個很重要並且流傳很廣的 shell 之一 。
Tips: 因爲 Linux 爲 C 程序語言撰寫的,不少程序設計師使用 C 來開發軟件,所以 C shell 相對的就很熱門了。 另外,還記得咱們在第一章、Linux 是什麼提到的吧? Sun 公司的創始人就是 Bill Joy,而 BSD 最先就是 Bill Joy 發展出來的啊。 |
![]() |
那麼目前咱們的 Linux (以 CentOS 5.x 爲例) 有多少咱們能夠使用的 shells 呢? 你能夠檢查一下 /etc/shells 這個文件,至少就有底下這幾個能夠用的 shells:
雖然各家 shell 的功能都差很少,可是在某些語法的下達方面則有所不一樣,所以建議你仍是得要選擇某一種 shell 來熟悉一下較佳。 Linux 默認就是使用 bash ,因此最初你只要學會 bash 就很是了不得了! ^_^! 另外,咦!爲何咱們系統上合法的 shell 要寫入 /etc/shells 這個文件啊? 這是由於系統某些服務在運行過程當中,會去檢查使用者可以使用的 shells ,而這些 shell 的查詢就是藉由 /etc/shells 這個文件囉!
舉例來講,某些 FTP 網站會去檢查使用者的可用 shell ,而若是你不想要讓這些使用者使用 FTP 之外的主機資源時,可能會給予該使用者一些怪怪的 shell,讓使用者沒法以其餘服務登錄主機。 這個時候,你就得將那些怪怪的 shell 寫到 /etc/shells 當中了。舉例來講,咱們的 CentOS 5.x 的 /etc/shells 裏頭就有個 /sbin/nologin 文件的存在,這個就是咱們說的怪怪的 shell 囉~
那麼,再想想,我這個使用者何時能夠取得 shell 來工做呢?還有, 我這個使用者默認會取得哪個 shell 啊?還記得咱們在第五章的在終端界面登錄linux小節當中提到的登錄動做吧? 當我登錄的時候,系統就會給我一個 shell 讓我來工做了。 而這個登錄取得的 shell 就記錄在 /etc/passwd 這個文件內!這個文件的內容是啥?
[root@www ~]# cat /etc/passwd root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin .....(底下省略)..... |
如上所示,在每一行的最後一個數據,就是你登錄後能夠取得的默認的 shell 啦!那你也會看到, root 是 /bin/bash ,不過,系統帳號 bin 與 daemon 等等,就使用那個怪怪的 /sbin/nologin 囉~關於使用者這部分的內容,咱們留在第十四章的帳號管理時提供更多的說明。
既然 /bin/bash 是 Linux 默認的 shell ,那麼老是得了解一下這個玩意兒吧!bash 是 GNU 計劃中重要的工具軟件之一,目前也是 Linux distributions 的標準 shell 。 bash 主要兼容於 sh ,而且依據一些使用者需求,而增強的 shell 版本。不論你使用的是那個 distribution ,你都難逃須要學習 bash 的宿命啦!那麼這個 shell 有什麼好處,幹嗎 Linux 要使用他做爲默認的 shell 呢? bash 主要的優勢有底下幾個:
bash 的功能裏頭,鳥哥我的認爲至關棒的一個就是『他能記憶使用過的命令!』 這功能真的至關的棒!由於我只要在命令列按『上下鍵』就能夠找到前/後一個輸入的命令!而在不少 distribution 裏頭,默認的命令記憶功能能夠到達 1000 個!也就是說, 你曾經下達過的命令幾乎都被記錄下來了。
這麼多的命令記錄在哪裏呢?在你的家目錄內的 .bash_history 啦! 不過,須要留意的是,~/.bash_history 記錄的是前一次登錄之前所運行過的命令, 而至於這一次登錄所運行的命令都被緩存在內存中,當你成功的註銷系統後,該命令記憶纔會記錄到 .bash_history 當中!
這有什麼功能呢?最大的好處就是能夠『查詢曾經作過的舉動!』 如此能夠知道你的運行步驟,那麼就能夠追蹤你曾下達過的命令,以做爲除錯的工具! 但如此一來也有個煩惱,就是若是被黑客入侵了,那麼他只要翻你曾經運行過的命令, 恰好你的命令又跟系統有關 (例如直接輸入 MySQL 的密碼在命令列上面),那你的主機可就傷腦筋了! 到底記錄命令的數目越多仍是越少越好?這部份是見仁見智啦,沒有必定的答案的。
還記得咱們在第五章內的重要的幾個熱鍵小節當中提到的 [tab] 這個按鍵嗎?這個按鍵的功能就是在 bash 裏頭纔有的啦!經常在 bash 環境中使用 [tab] 是個很棒的習慣喔!由於至少可讓你 1)少打不少字; 2)肯定輸入的數據是正確的! 使用 [tab] 按鍵的時機依據 [tab] 接在命令後或參數後而有所不一樣。咱們再複習一次:
因此說,若是我想要知道個人環境中,全部能夠運行的命令有幾個? 就直接在 bash 的提示字符後面連續按兩次 [tab] 按鍵就可以顯示全部的可運行命令了。 那若是想要知道系統當中全部以 c 爲開頭的命令呢?就按下『 c[tab][tab] 』就好啦! ^_^
是的!真的是很方便的功能,因此,有事沒事,在 bash shell 底下,多按幾回 [tab] 是一個不錯的習慣啦!
假如我須要知道這個目錄底下的全部文件 (包含隱藏檔) 及全部的文件屬性,那麼我就必需要下達『 ls -al 』這樣的命令串,唉!真麻煩,有沒有更快的取代方式?呵呵!就使用命令別名呀!例如鳥哥最喜歡直接以 lm 這個自定義的命令來取代上面的命令,也就是說, lm 會等於 ls -al 這樣的一個功能,嘿!那麼要如何做呢?就使用 alias 便可!你能夠在命令列輸入 alias 就能夠知道目前的命令別名有哪些了!也能夠直接下達命令來配置別名呦:
alias lm='ls -al'
這部分咱們在第十七章 Linux 過程控制中再說起! 使用前、背景的控制可讓工做進行的更爲順利!至於工做控制(jobs)的用途則更廣, 可讓咱們隨時將工做丟到背景中運行!而不怕不當心使用了 [Ctrl] + c 來停掉該程序!真是好樣的!此外,也能夠在單一登陸的環境中,達到多任務的目的呢!
在 DOS 年代還記得將一堆命令寫在一塊兒的所謂的『批處理文件』吧?在 Linux 底下的 shell scripts 則發揮更爲強大的功能,能夠將你平時管理系統常須要下達的連續命令寫成一個文件, 該文件而且能夠透過對談交互式的方式來進行主機的偵測工做!也能夠藉由 shell 提供的環境變量及相關命令來進行設計,哇!整個設計下來幾乎就是一個小型的程序語言了!該 scripts 的功能真的是超乎個人想象以外!之前在 DOS 底下須要程序語言才能寫的東西,在 Linux 底下使用簡單的 shell scripts 就能夠幫你達成了!真的厲害!這部分咱們在第十三章再來談!
除了完整的字符串以外, bash 還支持許多的通配符來幫助用戶查詢與命令下達。 舉例來講,想要知道 /usr/bin 底下有多少以 X 爲開頭的文件嗎?使用:『 ls -l /usr/bin/X* 』就可以知道囉~此外,還有其餘可供利用的通配符, 這些都可以加快使用者的操做呢!
咱們在第五章提到關於 Linux 的聯機幫助文件部分,也就是 man page 的內容,那麼 bash 有沒有什麼說明文件啊?開玩笑~ 這麼棒的東西怎麼可能沒有說明文件!請你在 shell 的環境下,直接輸入 man bash 瞧一瞧, 嘿嘿!不是蓋的吧!讓你看個幾天幾夜也沒法看完的 bash 說明文件,但是很詳盡的數據啊! ^_^
不過,在這個 bash 的 man page 當中,不知道你是否有察覺到,咦! 怎麼這個說明文件裏面有其餘的文件說明啊?舉例來講,那個 cd 命令的說明就在這個 man page 內? 而後我直接輸入 man cd 時,怎麼出現的畫面中,最上方居然出現一堆命令的介紹?這是怎麼回事? 爲了方便 shell 的操做,其實 bash 已經『內建』了不少命令了,例如上面提到的 cd , 還有例如 umask 等等的命令,都是內建在 bash 當中的呢!
那我怎麼知道這個命令是來自於外部命令(指的是其餘非 bash 所提供的命令) 或是內建在 bash 當中的呢? 嘿嘿!利用 type 這個命令來觀察便可!舉例來講:
[root@www ~]# type [-tpa] name 選項與參數: :不加任何選項與參數時,type 會顯示出 name 是外部命令仍是 bash 內建命令 -t :當加入 -t 參數時,type 會將 name 以底下這些字眼顯示出他的意義: file :表示爲外部命令; alias :表示該命令爲命令別名所配置的名稱; builtin :表示該命令爲 bash 內建的命令功能; -p :若是後面接的 name 爲外部命令時,纔會顯示完整文件名; -a :會由 PATH 變量定義的路徑中,將全部含 name 的命令都列出來,包含 alias 範例一:查詢一下 ls 這個命令是否爲 bash 內建? [root@www ~]# type ls ls is aliased to `ls --color=tty' <==未加任何參數,列出 ls 的最主要使用狀況 [root@www ~]# type -t ls alias <==僅列出 ls 運行時的依據 [root@www ~]# type -a ls ls is aliased to `ls --color=tty' <==最早使用 aliase ls is /bin/ls <==還有找到外部命令在 /bin/ls 範例二:那麼 cd 呢? [root@www ~]# type cd cd is a shell builtin <==看到了嗎? cd 是 shell 內建命令 |
透過 type 這個命令咱們能夠知道每一個命令是否爲 bash 的內建命令。 此外,因爲利用 type 搜尋後面的名稱時,若是後面接的名稱並不能以運行檔的狀態被找到, 那麼該名稱是不會被顯示出來的。也就是說, type 主要在找出『運行檔』而不是通常文件檔名喔! 呵呵!因此,這個 type 也能夠用來做爲相似 which 命令的用途啦!找命令用的!
咱們在第五章的開始下達命令小節已經提到過在 shell 環境下的命令下達方法,若是你忘記了請回到第五章再去回憶一下!這裏不重複說明了。 鳥哥這裏僅就反斜槓 (\) 來講明一下命令下達的方式囉!
範例:若是命令串太長的話,如何使用兩行來輸出? [vbird@www ~]# cp /var/spool/mail/root /etc/crontab \ > /etc/fstab /root |
上面這個命令用途是將三個文件複製到 /root 這個目錄下而已。不過,由於命令太長, 因而鳥哥就利用『 \[Enter] 』來將 [Enter] 這個按鍵『跳脫!』開來,讓 [Enter] 按鍵再也不具備『開始運行』的功能!好讓命令能夠繼續在下一行輸入。 須要特別留意, [Enter] 按鍵是緊接着反斜槓 (\) 的,二者中間沒有其餘字符。 由於 \ 僅跳脫『緊接着的下一個字符』而已!因此,萬一我寫成: 『 \ [Enter] 』,亦即 [Enter] 與反斜槓中間有一個空格時,則 \ 跳脫的是『空格鍵』而不是 [Enter] 按鍵!這個地方請再仔細的看一遍!很重要!
若是順利跳脫 [Enter] 後,下一行最前面就會主動出現 > 的符號, 你能夠繼續輸入命令囉!也就是說,那個 > 是系統自動出現的,你不須要輸入。
總之,當咱們順利的在終端機 (tty) 上面登錄後, Linux 就會依據 /etc/passwd 文件的配置給咱們一個 shell (默認是 bash),而後咱們就能夠依據上面的命令下達方式來操做 shell, 以後,咱們就能夠透過 man 這個在線查詢來查詢命令的使用方式與參數說明, 很不錯吧!那麼咱們就趕忙更進一步來操做 bash 這個好玩的東西囉!
變量是 bash 環境中很是重要的一個玩意兒,咱們知道 Linux 是多人多任務的環境,每一個人登錄系統都能取得一個 bash , 每一個人都可以使用 bash 下達 mail 這個命令來收受『本身』的郵件,問題是, bash 是如何得知你的郵件信箱是哪一個文件? 這就須要『變量』的幫助啦!因此,你說變量重不重要呢?底下咱們將介紹重要的環境變量、變量的取用與配置等數據, 呼呼!動動腦時間又來到囉!^_^
那麼,什麼是『變量』呢?簡單的說,就是讓某一個特定字符串表明不固定的內容就是了。舉個你們在國中都會學到的數學例子, 那就是:『 y = ax + b 』這東西,在等號左邊的(y)就是變量,在等號右邊的(ax+b)就是變量內容。 要注意的是,左邊是未知數,右邊是已知數喔! 講的更簡單一點,咱們能夠『用一個簡單的 "字眼" 來取代另外一個比較複雜或者是容易變更的數據』。這有什麼好處啊?最大的好處就是『方便!』。
舉例來講,咱們每一個帳號的郵件信箱默認是以 MAIL 這個變量來進行存取的, 當 dmtsai 這個使用者登錄時,他便會取得 MAIL 這個變量,而這個變量的內容其實就是 /var/spool/mail/dmtsai, 那若是 vbird 登錄呢?他取得的 MAIL 這個變量的內容其實就是 /var/spool/mail/vbird 。 而咱們使用信件讀取命令 mail 來讀取本身的郵件信箱時,嘿嘿,這支程序能夠直接讀取 MAIL 這個變量的內容, 就可以自動的分辨出屬於本身的信箱信件囉!這樣一來,設計程序的設計師就真的很方便的啦!
如上圖所示,因爲系統已經幫咱們規劃好 MAIL 這個變量,因此用戶只要知道 mail 這個命令如何使用便可, mail 會主動的取用 MAIL 這個變量,就可以如上圖所示的取得本身的郵件信箱了!(注意大小寫,小寫的 mail 是命令, 大寫的 MAIL 則是變量名稱喔!)
那麼使用變量真的比較好嗎?這是固然的!想象一個例子,若是 mail 這個命令將 root 收信的郵件信箱 (mailbox) 檔名爲 /var/spool/mail/root 直接寫入程序代碼中。那麼當 dmtsai 要使用 mail 時,將會取得 /var/spool/mail/root 這個文件的內容! 不合理吧!因此你就須要幫 dmtsai 也設計一個 mail 的程序,將 /var/spool/mail/dmtsai 寫死到 mail 的程序代碼當中! 天吶!那系統要有多少個 mail 命令啊?反過來講,使用變量就變的很簡單了!由於你不須要更動到程序代碼啊! 只要將 MAIL 這個變量帶入不一樣的內容便可讓全部使用者透過 mail 取得本身的信件!固然簡單多了!
某些特定變量會影響到 bash 的環境喔!舉例來講,咱們前面已經提到過不少次的那個 PATH 變量! 你能不能在任何目錄下運行某個命令,與 PATH 這個變量有很大的關係。例如你下達 ls 這個命令時,系統就是透過 PATH 這個變量裏面的內容所記錄的路徑順序來搜尋命令的呢!若是在搜尋完 PATH 變量內的路徑還找不到 ls 這個命令時, 就會在屏幕上顯示『 command not found 』的錯誤信息了。
若是說的學理一點,那麼因爲在 Linux System 下面,全部的線程都是須要一個運行碼, 而就如同上面提到的,你『真正以 shell 來跟 Linux 溝通,是在正確的登錄 Linux 以後!』這個時候你就有一個 bash 的運行程序,也才能夠真正的經由 bash 來跟系統溝通囉!而在進入 shell 以前,也正如同上面提到的,因爲系統須要一些變量來提供他數據的存取 (或者是一些環境的配置參數值, 例如是否要顯示彩色等等的) ,因此就有一些所謂的『環境變量』 須要來讀入系統中了!這些環境變量例如 PATH、HOME、MAIL、SHELL 等等,都是很重要的, 爲了區別與自定義變量的不一樣,環境變量一般以大寫字符來表示呢!
這些還都只是系統默認的變量的目的,若是是我的的配置方面的應用呢:例如你要寫一個大型的 script 時,有些數據由於可能因爲用戶習慣的不一樣而有差別,好比說路徑好了,因爲該路徑在 script 被使用在至關多的地方,若是下次換了一部主機,都要修改 script 裏面的全部路徑,那麼我必定會瘋掉! 這個時候若是使用變量,而將該變量的定義寫在最前面,後面相關的路徑名稱都以變量來取代, 嘿嘿!那麼你只要修改一行就等於修改整篇 script 了!方便的很!因此,良好的程序設計師都會善用變量的定義!
最後咱們就簡單的對『什麼是變量』做個簡單定義好了: 『變量就是以一組文字或符號等,來取代一些配置或者是一串保留的數據!』, 例如:我配置了『myname』就是『VBird』,因此當你讀取 myname 這個變量的時候,系統天然就會知道!哈!那就是 VBird 啦! 那麼如何『顯示變量』呢?這就須要使用到 echo 這個命令啦!
說的口沫橫飛的,也不知道『變量』與『變量表明的內容』有啥關係? 那咱們就將『變量』的『內容』拿出來給您瞧瞧好了。你能夠利用 echo 這個命令來取用變量, 可是,變量在被取用時,前面必需要加上錢字號『 $ 』才行,舉例來講,要知道 PATH 的內容,該如何是好?
[root@www ~]# echo $variable [root@www ~]# echo $PATH /usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin [root@www ~]# echo ${PATH} |
變量的取用就如同上面的範例,利用 echo 就可以讀出,只是須要在變量名稱前面加上 $ , 或者是以 ${變量} 的方式來取用均可以!固然啦,那個 echo 的功能但是不少的, 咱們這裏單純是拿 echo 來讀出變量的內容而已,更多的 echo 使用,請自行給他 man echo 吧! ^_^
例題:
請在屏幕上面顯示出您的環境變量 HOME 與 MAIL:
答:
echo $HOME 或者是 echo ${HOME} echo $MAIL 或者是 echo ${MAIL} |
如今咱們知道了變量與變量內容之間的相關性了,好了,那麼我要如何『配置』或者是『修改』 某個變量的內容啊?很簡單啦!用『等號(=)』鏈接變量與他的內容就好啦!舉例來講: 我要將 myname 這個變量名稱的內容配置爲 VBird ,那麼:
[root@www ~]# echo $myname <==這裏並無任何數據~由於這個變量還沒有被配置!是空的! [root@www ~]# myname=VBird [root@www ~]# echo $myname VBird <==出現了!由於這個變量已經被配置了! |
瞧!如此一來,這個變量名稱 myname 的內容就帶有 VBird 這個數據囉~ 而由上面的例子當中,咱們也能夠知道: 在 bash 當中,當一個變量名稱還沒有被配置時,默認的內容是『空』的。 另外,變量在配置時,仍是須要符合某些規定的,不然會配置失敗喔! 這些守則以下所示啊!
底下讓鳥哥舉幾個例子來讓你試看看,就知道怎麼配置好你的變量囉!
範例一:配置一變量 name ,且內容爲 VBird [root@www ~]# 12name=VBird -bash: 12name=VBird: command not found <==屏幕會顯示錯誤!由於不能以數字開頭! [root@www ~]# name = VBird <==仍是錯誤!由於有空白! [root@www ~]# name=VBird <==OK 的啦! 範例二:承上題,若變量內容爲 VBird's name 呢,就是變量內容含有特殊符號時: [root@www ~]# name=VBird's name # 單引號與雙引號必需要成對,在上面的配置中僅有一個單引號,所以當你按下 enter 後, # 你還能夠繼續輸入變量內容。這與咱們所須要的功能不一樣,失敗啦! # 記得,失敗後要復原請按下 [ctrl]-c 結束! [root@www ~]# name="VBird's name" <==OK 的啦! # 命令是由左邊向右找→,先遇到的引號先有用,所以如上所示,單引號會失效! [root@www ~]# name='VBird's name' <==失敗的啦! # 由於前兩個單引號已成對,後面就多了一個不成對的單引號了!所以也就失敗了! [root@www ~]# name=VBird\'s\ name <==OK 的啦! # 利用反斜槓 (\) 跳脫特殊字符,例如單引號與空格鍵,這也是 OK 的啦! 範例三:我要在 PATH 這個變量當中『累加』:/home/dmtsai/bin 這個目錄 [root@www ~]# PATH=$PATH:/home/dmtsai/bin [root@www ~]# PATH="$PATH":/home/dmtsai/bin [root@www ~]# PATH=${PATH}:/home/dmtsai/bin # 上面這三種格式在 PATH 裏頭的配置都是 OK 的!可是底下的例子就不見得囉! 範例四:承範例三,我要將 name 的內容多出 "yes" 呢? [root@www ~]# name=$nameyes # 知道了吧?若是沒有雙引號,那麼變量成了啥?name 的內容是 $nameyes 這個變量! # 呵呵!咱們可沒有配置過 nameyes 這個變量吶!因此,應該是底下這樣纔對! [root@www ~]# name="$name"yes [root@www ~]# name=${name}yes <==以此例較佳! 範例五:如何讓我剛剛配置的 name=VBird 能夠用在下個 shell 的程序? [root@www ~]# name=VBird [root@www ~]# bash <==進入到所謂的子程序 [root@www ~]# echo $name <==子程序:再次的 echo 一下; <==嘿嘿!並無剛剛配置的內容喔! [root@www ~]# exit <==子程序:離開這個子程序 [root@www ~]# export name [root@www ~]# bash <==進入到所謂的子程序 [root@www ~]# echo $name <==子程序:在此運行! VBird <==看吧!出現配置值了! [root@www ~]# exit <==子程序:離開這個子程序 |
什麼是『子程序』呢?就是說,在我目前這個 shell 的狀況下,去激活另外一個新的 shell ,新的那個 shell 就是子程序啦!在通常的狀態下,父程序的自定義變量是沒法在子程序內使用的。可是透過 export 將變量變成環境變量後,就可以在子程序底下應用了!很不賴吧!至於程序的相關概念, 咱們會在第十七章程序管理當中提到的喔!
範例六:如何進入到您目前核心的模塊目錄? [root@www ~]# cd /lib/modules/`uname -r`/kernel [root@www ~]# cd /lib/modules/$(uname -r)/kernel |
每一個 Linux 都可以擁有多個核心版本,且幾乎 distribution 的核心版本都不相同。以 CentOS 5.3 (未升級前) 爲例,他的默認核心版本是 2.6.18-128.el5 ,因此核心模塊目錄在 /lib/modules/2.6.18-128.el5/kernel/ 內。 也因爲每一個 distributions 的這個值都不相同,可是咱們卻能夠利用 uname -r 這個命令先取得版本信息。因此囉,就能夠透過上面命令當中的內含命令 `uname -r` 先取得版本輸出到 cd ... 那個命令當中,就可以順利的進入目前核心的驅動程序所放置的目錄囉!很方便吧!
其實上面的命令能夠說是做了兩次動做,亦便是:
範例七:取消剛剛配置的 name 這個變量內容 [root@www ~]# unset name |
根據上面的案例你能夠試試看!就能夠了解變量的配置囉!這個是很重要的呦!請勤加練習! 其中,較爲重要的一些特殊符號的使用囉!例如單引號、雙引號、跳脫字符、錢字號、反單引號等等,底下的例題想想吧!
例題:
在變量的配置當中,單引號與雙引號的用途有何不一樣?
答:
單引號與雙引號的最大不一樣在於
雙引號仍然能夠保有變量的內容,但單引號內僅能是通常字符 ,而不會有特殊符號。咱們以底下的例子作說明:假設您定義了一個變量, name=VBird ,如今想以 name 這個變量的內容定義出 myname 顯示 VBird its me 這個內容,要如何訂定呢?
[root@www ~]# name=VBird發現了嗎?沒錯!使用了單引號的時候,那麼 $name 將失去原有的變量內容,僅爲通常字符的顯示型態而已!這裏必須要特別當心在乎! |
例題:
在命令下達的過程當中,反單引號( ` )這個符號表明的意義爲什麼?
答:
在一串命令中,在 ` 以內的命令將會被先運行,而其運行出來的結果將作爲外部的輸入信息!例如 uname -r 會顯示出目前的核心版本,而咱們的核心版本在 /lib/modules 裏面,所以,你能夠先運行 uname -r 找出核心版本,而後再以『 cd 目錄』到該目錄下,固然也能夠運行如同上面範例六的運行內容囉。
另外再舉個例子,咱們也知道, locate 命令能夠列出全部的相關文件檔名,可是,若是我想要知道各個文件的權限呢?舉例來講,我想要知道每一個 crontab 相關檔名的權限: [root@www ~]# ls -l `locate crontab`如此一來,先以 locate 將文件名數據都列出來,再以 ls 命令來處理的意思啦!瞭了嗎? ^_^ |
例題:
若你有一個常去的工做目錄名稱爲:『/cluster/server/work/taiwan_2005/003/』,如何進行該目錄的簡化?
答:
在通常的狀況下,若是你想要進入上述的目錄得要『cd /cluster/server/work/taiwan_2005/003/』, 以鳥哥本身的案例來講,鳥哥跑數值模式經常會配置很長的目錄名稱(避免忘記),但如此一來變換目錄就很麻煩。 此時,鳥哥習慣利用底下的方式來下降命令下達錯誤的問題:
[root@www ~]# work="/cluster/server/work/taiwan_2005/003/"將來我想要使用其餘目錄做爲個人模式工做目錄時,只要變動 work 這個變量便可!而這個變量又能夠在 bash 的配置文件中直接指定,那我每次登錄只要運行『 cd $work 』就可以去到數值模式仿真的工做目錄了!是否很方便呢? ^_^ |
Tips: 老實說,使用『 version=$(uname -r) 』來取代『 version=`uname -r` 』比較好,由於反單引號你們總是容易打錯或看錯! 因此如今鳥哥都習慣使用 $( 命令 ) 來介紹這個功能! |
![]() |
環境變量能夠幫咱們達到不少功能~包括家目錄的變換啊、提示字符的顯示啊、運行文件搜尋的路徑啊等等的, 還有不少不少啦!那麼,既然環境變量有那麼多的功能,問一下,目前個人 shell 環境中, 有多少默認的環境變量啊?咱們能夠利用兩個命令來查閱,分別是 env 與 export 呢!
範例一:列出目前的 shell 環境下的全部環境變量與其內容。 [root@www ~]# env HOSTNAME=www.vbird.tsai <== 這部主機的主機名 TERM=xterm <== 這個終端機使用的環境是什麼類型 SHELL=/bin/bash <== 目前這個環境下,使用的 Shell 是哪個程序? HISTSIZE=1000 <== 『記錄命令的筆數』在 CentOS 默承認記錄 1000 筆 USER=root <== 使用者的名稱啊! LS_COLORS=no=00:fi=00:di=00;34:ln=00;36:pi=40;33:so=00;35:bd=40;33;01:cd=40;33;01: or=01;05;37;41:mi=01;05;37;41:ex=00;32:*.cmd=00;32:*.exe=00;32:*.com=00;32:*.btm=0 0;32:*.bat=00;32:*.sh=00;32:*.csh=00;32:*.tar=00;31:*.tgz=00;31:*.arj=00;31:*.taz= 00;31:*.lzh=00;31:*.zip=00;31:*.z=00;31:*.Z=00;31:*.gz=00;31:*.bz2=00;31:*.bz=00;3 1:*.tz=00;31:*.rpm=00;31:*.cpio=00;31:*.jpg=00;35:*.gif=00;35:*.bmp=00;35:*.xbm=00 ;35:*.xpm=00;35:*.png=00;35:*.tif=00;35: <== 一些顏色顯示 MAIL=/var/spool/mail/root <== 這個用戶所取用的 mailbox 位置 PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/X11R6/bin:/usr/local/bin:/usr/local/sbin: /root/bin <== 再也不多講啊!是運行文件命令搜尋路徑 INPUTRC=/etc/inputrc <== 與鍵盤按鍵功能有關。能夠配置特殊按鍵! PWD=/root <== 目前用戶所在的工做目錄 (利用 pwd 取出!) LANG=en_US <== 這個與語系有關,底下會再介紹! HOME=/root <== 這個用戶的家目錄啊! _=/bin/env <== 上一次使用的命令的最後一個參數(或命令自己) |
env 是 environment (環境) 的簡寫啊,上面的例子當中,是列出來全部的環境變量。固然,若是使用 export 也會是同樣的內容~ 只不過, export 還有其餘額外的功能就是了,咱們等一下再提這個 export 命令。 那麼上面這些變量有些什麼功用呢?底下咱們就一個一個來分析分析!
[root@www ~]# declare -i number=$RANDOM*10/32768 ; echo $number 8 <== 此時會隨機取出 0~9 之間的數值喔! |
大體上是有這些環境變量啦~裏面有些比較重要的參數,在底下咱們都會另外進行一些說明的~
bash 可不僅有環境變量喔,還有一些與 bash 操做接口有關的變量,以及用戶本身定義的變量存在的。 那麼這些變量如何觀察呢?這個時候就得要使用 set 這個命令了。 set 除了環境變量以外, 還會將其餘在 bash 內的變量統統顯示出來哩!信息不少,底下鳥哥僅列出幾個重要的內容:
[root@www ~]# set BASH=/bin/bash <== bash 的主程序放置路徑 BASH_VERSINFO=([0]="3" [1]="2" [2]="25" [3]="1" [4]="release" [5]="i686-redhat-linux-gnu") <== bash 的版本啊! BASH_VERSION='3.2.25(1)-release' <== 也是 bash 的版本啊! COLORS=/etc/DIR_COLORS.xterm <== 使用的顏色紀錄文件 COLUMNS=115 <== 在目前的終端機環境下,使用的字段有幾個字符長度 HISTFILE=/root/.bash_history <== 歷史命令記錄的放置文件,隱藏檔 HISTFILESIZE=1000 <== 存起來(與上個變量有關)的文件之命令的最大紀錄筆數。 HISTSIZE=1000 <== 目前環境下,可記錄的歷史命令最大筆數。 HOSTTYPE=i686 <== 主機安裝的軟件主要類型。咱們用的是 i686 兼容機器軟件 IFS=$' \t\n' <== 默認的分隔符 LINES=35 <== 目前的終端機下的最大行數 MACHTYPE=i686-redhat-linux-gnu <== 安裝的機器類型 MAILCHECK=60 <== 與郵件有關。每 60 秒去掃瞄一次信箱有無新信! OLDPWD=/home <== 上個工做目錄。咱們能夠用 cd - 來取用這個變量。 OSTYPE=linux-gnu <== 操做系統的類型! PPID=20025 <== 父程序的 PID (會在後續章節才介紹) PS1='[\u@\h \W]\$ ' <== PS1 就厲害了。這個是命令提示字符,也就是咱們常見的 [root@www ~]# 或 [dmtsai ~]$ 的配置值啦!能夠更動的! PS2='> ' <== 若是你使用跳脫符號 (\) 第二行之後的提示字符也 name=VBird <== 剛剛配置的自定義變量也能夠被列出來喔! $ <== 目前這個 shell 所使用的 PID ? <== 剛剛運行完命令的回傳值。 |
通常來講,不管是否爲環境變量,只要跟咱們目前這個 shell 的操做接口有關的變量, 一般都會被配置爲大寫字符,也就是說,『基本上,在 Linux 默認的狀況中,使用{大寫的字母}來配置的變量通常爲系統內定須要的變量』。 OK!OK!那麼上頭那些變量當中,有哪些是比較重要的?大概有這幾個吧!
[root@www /home/dmtsai 16:50 #12]#那個 # 表明第 12 次下達的命令。那麼應該如何配置 PS1 呢?能夠這樣啊:
[root@www ~ ]# cd /home [root@www home]# PS1='[\u@\h \w \A #\#]\$ ' [root@www /home 17:02 #85]# # 看到了嗎?提示字符變了!變的頗有趣吧!其中,那個 #85 比較有趣, # 若是您再隨便輸入幾回 ls 後,該數字就會添加喔!爲啥?上面有說明滴! |
[root@www ~]# echo $SHELL /bin/bash <==可順利顯示!沒有錯誤! [root@www ~]# echo $? 0 <==由於沒問題,因此回傳值爲 0 [root@www ~]# 12name=VBird -bash: 12name=VBird: command not found <==發生錯誤了!bash回報有問題 [root@www ~]# echo $? 127 <==由於有問題,回傳錯誤代碼(非爲0) # 錯誤代碼回傳值依據軟件而有不一樣,咱們能夠利用這個代碼來搜尋錯誤的緣由喔! [root@www ~]# echo $? 0 # 咦!怎麼又變成正確了?這是由於 "?" 只與『上一個運行命令』有關, # 因此,咱們上一個命令是運行『 echo $? 』,固然沒有錯誤,因此是 0 沒錯! |
談了 env 與 set 如今知道有所謂的環境變量與自定義變量,那麼這二者之間有啥差別呢?其實這二者的差別在於『 該變量是否會被子程序所繼續引用』啦!唔!那麼啥是父程序?子程序? 這就得要了解一下命令的下達行爲了。
當你登錄 Linux 並取得一個 bash 以後,你的 bash 就是一個獨立的程序,被稱爲 PID 的就是。 接下來你在這個 bash 底下所下達的任何命令都是由這個 bash 所衍生出來的,那些被下達的命令就被稱爲子程序了。 咱們能夠用底下的圖示來簡單的說明一下父程序與子程序的概念:
如上所示,咱們在本來的 bash 底下運行另外一個 bash ,結果操做的環境接口會跑到第二個 bash 去(就是子程序), 那本來的 bash 就會在暫停的狀況 (睡着了,就是 sleep)。整個命令運行的環境是實線的部分!若要回到本來的 bash 去, 就只有將第二個 bash 結束掉 (下達 exit 或 logout) 才行。更多的程序概念咱們會在第四篇談及,這裏只要有這個概念便可。
這個程序概念與變量有啥關係啊?關係可大了!由於子程序僅會繼承父程序的環境變量, 子程序不會繼承父程序的自定義變量啦!因此你在本來 bash 的自定義變量在進入了子程序後就會消失不見, 一直到你離開子程序並回到本來的父程序後,這個變量纔會又出現!
換個角度來想,也就是說,若是我能將自定義變量變成環境變量的話,那不就可讓該變量值繼續存在於子程序了? 呵呵!沒錯!此時,那個 export 命令就頗有用啦!如你想要讓該變量內容繼續的在子程序中使用,那麼就請運行:
[root@www ~]# export 變量名稱
|
這東西用在『分享本身的變量配置給後來呼叫的文件或其餘程序』啦! 像鳥哥經常在本身的主控文件後面呼叫其餘附屬文件(相似函式的功能),可是主控文件與附屬文件內都有相同的變量名稱, 若一再重複配置時,要修改也很麻煩,此時只要在本來的第一個文件內配置好『 export 變量 』, 後面所呼叫的文件就可以使用這個變量配置了!而不須要重複配置,這很是實用於 shell script 當中喔! 若是僅下達 export 而沒有接變量時,那麼此時將會把全部的『環境變量』秀出來喔!例如:
[root@www ~]# export declare -x HISTSIZE="1000" declare -x HOME="/root" declare -x HOSTNAME="www.vbird.tsai" declare -x INPUTRC="/etc/inputrc" declare -x LANG="en_US" declare -x LOGNAME="root" # 後面的鳥哥就都直接省略了!否則....浪費版面~ ^_^ |
那如何將環境變量轉成自定義變量呢?能夠使用本章後續介紹的 declare 呢!
還記得咱們在第五章裏面提到的語系問題嗎? 就是當咱們使用 man command 的方式去查詢某個數據的說明文件時,該說明檔的內容可能會由於咱們使用的語系不一樣而產生亂碼。 另外,利用 ls 查詢文件的時間時,也可能會有亂碼出如今時間的部分。那個問題其實就是語系的問題啦。
目前大多數的 Linux distributions 已經都是支持日漸流行的萬國碼了,也都支持大部分的國家語系。 這有賴於 i18n (注4)支持的幫助呢! 那麼咱們的 Linux 到底支持了多少的語系呢?這能夠由 locale 這個命令來查詢到喔!
[root@www ~]# locale -a ....(前面省略).... zh_TW zh_TW.big5 <==大五碼的中文編碼 zh_TW.euctw zh_TW.utf8 <==萬國碼的中文編碼 zu_ZA zu_ZA.iso88591 zu_ZA.utf8 |
正體中文語系至少支持了兩種以上的編碼,一種是目前仍是很常見的 big5 ,另外一種則是愈來愈熱門的 utf-8 編碼。 那麼咱們如何修訂這些編碼呢?其實能夠透過底下這些變量的說:
[root@www ~]# locale <==後面不加任何選項與參數便可! LANG=en_US <==主語言的環境 LC_CTYPE="en_US" <==字符(文字)辨識的編碼 LC_NUMERIC="en_US" <==數字系統的顯示信息 LC_TIME="en_US" <==時間系統的顯示數據 LC_COLLATE="en_US" <==字符串的比較與排序等 LC_MONETARY="en_US" <==幣值格式的顯示等 LC_MESSAGES="en_US" <==信息顯示的內容,如菜單、錯誤信息等 LC_ALL= <==總體語系的環境 ....(後面省略).... |
基本上,你能夠逐一配置每一個與語系有關的變量數據,但事實上,若是其餘的語系變量都未配置, 且你有配置 LANG 或者是 LC_ALL 時,則其餘的語系變量就會被這兩個變量所取代! 這也是爲何咱們在 Linux 當中,一般說明僅配置 LANG 這個變量而已,由於他是最主要的配置變量! 好了,那麼你應該要以爲奇怪的是,爲何在 Linux 主機的終端機接口 (tty1 ~ tty6) 的環境下,若是配置『 LANG=zh_TW.big5 』這個配置值生效後,使用 man 或者其餘信息輸出時, 都會有一堆亂碼,尤爲是使用 ls -l 這個參數時?
由於在 Linux 主機的終端機接口環境下是沒法顯示像中文這麼複雜的編碼文字, 因此就會產生亂碼了。也就是如此,咱們纔會必需要在 tty1 ~ tty6 的環境下, 加裝一些中文化接口的軟件,纔可以看到中文啊!不過,若是你是在 MS Windows 主機以遠程聯機服務器的軟件聯機到主機的話,那麼,嘿嘿!其實文字接口確實是能夠看到中文的。 此時反而你得要在 LANG 配置中文編碼纔好呢!
Tips: 不管如何,若是發生一些亂碼的問題,那麼配置系統裏面保有的語系編碼, 例如: en_US 或 en_US.utf8 等等的配置,應該就 OK 的啦!好了,那麼系統默認支持多少種語系呢? 當咱們使用 locale 時,系統是列出目前 Linux 主機內保有的語系文件, 這些語系文件都放置在:/usr/lib/locale/ 這個目錄中。 |
![]() |
你固然可讓每一個使用者本身去調整本身喜愛的語系,可是總體系統默認的語系定義在哪裏呢? 其實就是在 /etc/sysconfig/i18n 囉!這個文件在 CentOS 5.x 的內容有點像這樣:
[root@www ~]# cat /etc/sysconfig/i18n
LANG="zh_TW.UTF-8"
|
由於鳥哥在第四章的安裝時選擇的是中文語系安裝畫面, 因此這個文件默認就會使用中文編碼啦!你也能夠自行將他改爲你想要的語系編碼便可。
Tips: 假設你有一個純文本文件本來是在 Windows 底下建立的,那麼這個文件默認應該是 big5 的編碼格式。 在你將這個文件上傳到 Linux 主機後,在 X window 底下打開時,咦!怎麼中文字統統變成亂碼了? 別擔憂!由於如上所示, i18n 默認是萬國碼系統嘛!你只要將開啓該文件的軟件編碼由 utf8 改爲 big5 就可以看到正確的中文了! |
![]() |
什麼?變量也有使用的『範圍』?沒錯啊~咱們在上頭的 export 命令說明中,就提到了這個概念了。若是在跑程序的時候,有父程序與子程序的不一樣程序關係時, 則『變量』能否被引用與 export 有關。被 export 後的變量,咱們能夠稱他爲『環境變量』! 環境變量能夠被子程序所引用,可是其餘的自定義變量內容就不會存在於子程序中。
Tips: 在某些不一樣的書籍會談到『全局變量, global variable』與『局部變量, local variable』。 基本上你能夠這樣看待: 環境變量=全局變量 自定義變量=局部變量 |
![]() |
在學理方面,爲何環境變量的數據能夠被子程序所引用呢?這是由於內存配置的關係!理論上是這樣的:
透過這樣的關係,咱們就可讓某些變量在相關的程序之間存在,以幫助本身更方便的操做環境喔! 不過要提醒的是,這個『環境變量』與『bash 的操做環境』意思不太同樣,舉例來講, PS1 並非環境變量, 可是這個 PS1 會影響到 bash 的接口 (提示字符嘛)!相關性要釐清喔!^_^
咱們上面提到的變量配置功能,都是由命令列直接配置的,那麼,可不可讓用戶可以經由鍵盤輸入? 什麼意思呢?是否記得某些程序運行的過程中,會等待使用者輸入 "yes/no" 之類的信息啊? 在 bash 裏面也有相對應的功能喔!此外,咱們還能夠宣告這個變量的屬性, 例如:數組或者是數字等等的。底下就來看看吧!
要讀取來自鍵盤輸入的變量,就是用 read 這個命令了。這個命令最常被用在 shell script 的撰寫當中, 想要跟使用者對談?用這個命令就對了。關於 script 的寫法,咱們會在第十三章介紹,底下先來瞧一瞧 read 的相關語法吧!
[root@www ~]# read [-pt] variable 選項與參數: -p :後面能夠接提示字符! -t :後面能夠接等待的『秒數!』這個比較有趣~不會一直等待使用者啦! 範例一:讓用戶由鍵盤輸入一內容,將該內容變成名爲 atest 的變量 [root@www ~]# read atest This is a test <==此時光標會等待你輸入!請輸入左側文字看看 [root@www ~]# echo $atest This is a test <==你剛剛輸入的數據已經變成一個變量內容! 範例二:提示使用者 30 秒內輸入本身的大名,將該輸入字符串做爲名爲 named 的變量內容 [root@www ~]# read -p "Please keyin your name: " -t 30 named Please keyin your name: VBird Tsai <==注意看,會有提示字符喔! [root@www ~]# echo $named VBird Tsai <==輸入的數據又變成一個變量的內容了! |
read 以後不加任何參數,直接加上變量名稱,那麼底下就會主動出現一個空白行等待你的輸入(如範例一)。 若是加上 -t 後面接秒數,例如上面的範例二,那麼 30 秒以內沒有任何動做時, 該命令就會自動略過了~若是是加上 -p ,嘿嘿!在輸入的光標前就會有比較多能夠用的提示字符給咱們參考! 在命令的下達裏面,比較美觀啦! ^_^
declare 或 typeset 是同樣的功能,就是在『宣告變量的類型』。若是使用 declare 後面並無接任何參數,那麼 bash 就會主動的將全部的變量名稱與內容統統叫出來,就好像使用 set 同樣啦! 那麼 declare 還有什麼語法呢?看看先:
[root@www ~]# declare [-aixr] variable 選項與參數: -a :將後面名爲 variable 的變量定義成爲數組 (array) 類型 -i :將後面名爲 variable 的變量定義成爲整數數字 (integer) 類型 -x :用法與 export 同樣,就是將後面的 variable 變成環境變量; -r :將變量配置成爲 readonly 類型,該變量不可被更改內容,也不能 unset 範例一:讓變量 sum 進行 100+300+50 的加總結果 [root@www ~]# sum=100+300+50 [root@www ~]# echo $sum 100+300+50 <==咦!怎麼沒有幫我計算加總?由於這是文字型態的變量屬性啊! [root@www ~]# declare -i sum=100+300+50 [root@www ~]# echo $sum 450 <==瞭乎?? |
因爲在默認的狀況底下, bash 對於變量有幾個基本的定義:
如今你曉得爲啥你須要進行變量宣告了吧?若是須要非字符串類型的變量,那就得要進行變量的宣告才行啦! 底下繼續來玩些其餘的 declare 功能。
範例二:將 sum 變成環境變量 [root@www ~]# declare -x sum [root@www ~]# export | grep sum declare -ix sum="450" <==果真出現了!包括有 i 與 x 的宣告! 範例三:讓 sum 變成只讀屬性,不可更動! [root@www ~]# declare -r sum [root@www ~]# sum=tesgting -bash: sum: readonly variable <==老天爺~不能改這個變量了! 範例四:讓 sum 變成非環境變量的自定義變量吧! [root@www ~]# declare +x sum <== 將 - 變成 + 能夠進行『取消』動做 [root@www ~]# declare -p sum <== -p 能夠單獨列出變量的類型 declare -ir sum="450" <== 看吧!只剩下 i, r 的類型,不具備 x 囉! |
declare 也是個頗有用的功能~尤爲是當咱們須要使用到底下的數組功能時, 他也能夠幫咱們宣告數組的屬性喔!不過,老話一句,數組也是在 shell script 比較經常使用的啦! 比較有趣的是,若是你不當心將變量配置爲『只讀』,一般得要註銷再登錄才能復原該變量的類型了! @_@
某些時候,咱們必須使用數組來宣告一些變量,這有什麼好處啊?在通常人的使用上, 果真是看不出來有什麼好處的!不過,若是您曾經寫過程序的話,那纔會比較瞭解數組的意義~ 數組對寫數值程序的設計師來講,但是不能錯過學習的重點之一哩!好!不囉唆~ 那麼要如何配置數組的變量與內容呢?在 bash 裏頭,數組的配置方式是:
var[index]=content
意思是說,我有一個數組名爲 var ,而這個數組的內容爲 var[1]=小明, var[2]=大明, var[3]=好明 .... 等等,那個 index 就是一些數字啦,重點是用中刮號 ([ ]) 來配置的。 目前咱們 bash 提供的是一維數組。老實說,若是您沒必要寫一些複雜的程序, 那麼這個數組的地方,能夠先略過,等到有須要再來學習便可!由於要製做出數組, 一般與循環或者其餘判斷式交互使用纔有比較高的存在乎義!
範例:配置上面提到的 var[1] ~ var[3] 的變量。 [root@www ~]# var[1]="small min" [root@www ~]# var[2]="big min" [root@www ~]# var[3]="nice min" [root@www ~]# echo "${var[1]}, ${var[2]}, ${var[3]}" small min, big min, nice min |
數組的變量類型比較有趣的地方在於『讀取』,通常來講,建議直接以 ${數組} 的方式來讀取,比較正確無誤的啦!
想象一個情況:個人 Linux 主機裏面同時登錄了十我的,這十我的不知怎麼搞的, 同時開啓了 100 個文件,每一個文件的大小約 10MBytes ,請問一下, 個人 Linux 主機的內存要有多大才夠? 10*100*10 = 10000 MBytes = 10GBytes ... 老天爺,這樣,系統不掛點纔有鬼哩!爲了要預防這個狀況的發生,因此咱們的 bash 是能夠『限制用戶的某些系統資源』的,包括能夠開啓的文件數量, 能夠使用的 CPU 時間,能夠使用的內存總量等等。如何配置?用 ulimit 吧!
[root@www ~]# ulimit [-SHacdfltu] [配額] 選項與參數: -H :hard limit ,嚴格的配置,一定不能超過這個配置的數值; -S :soft limit ,警告的配置,能夠超過這個配置值,可是若超過則有警告信息。 在配置上,一般 soft 會比 hard 小,舉例來講,soft 可配置爲 80 而 hard 配置爲 100,那麼你能夠使用到 90 (由於沒有超過 100),但介於 80~100 之間時, 系統會有警告信息通知你! -a :後面不接任何選項與參數,可列出全部的限制額度; -c :當某些程序發生錯誤時,系統可能會將該程序在內存中的信息寫成文件(除錯用), 這種文件就被稱爲核心文件(core file)。此爲限制每一個核心文件的最大容量。 -f :此 shell 能夠建立的最大文件容量(通常可能配置爲 2GB)單位爲 Kbytes -d :程序可以使用的最大斷裂內存(segment)容量; -l :可用於鎖定 (lock) 的內存量 -t :可以使用的最大 CPU 時間 (單位爲秒) -u :單一用戶能夠使用的最大程序(process)數量。 範例一:列出你目前身份(假設爲root)的全部限制數據數值 [root@www ~]# ulimit -a core file size (blocks, -c) 0 <==只要是 0 就表明沒限制 data seg size (kbytes, -d) unlimited scheduling priority (-e) 0 file size (blocks, -f) unlimited <==可建立的單一文件的大小 pending signals (-i) 11774 max locked memory (kbytes, -l) 32 max memory size (kbytes, -m) unlimited open files (-n) 1024 <==同時可開啓的文件數量 pipe size (512 bytes, -p) 8 POSIX message queues (bytes, -q) 819200 real-time priority (-r) 0 stack size (kbytes, -s) 10240 cpu time (seconds, -t) unlimited max user processes (-u) 11774 virtual memory (kbytes, -v) unlimited file locks (-x) unlimited 範例二:限制用戶僅能建立 10MBytes 如下的容量的文件 [root@www ~]# ulimit -f 10240 [root@www ~]# ulimit -a file size (blocks, -f) 10240 <==最大量爲10240Kbyes,至關10Mbytes [root@www ~]# dd if=/dev/zero of=123 bs=1M count=20 File size limit exceeded <==嘗試建立 20MB 的文件,結果失敗了! |
還記得咱們在第八章 Linux 磁盤文件系統裏面提到過,單一 filesystem 可以支持的單一文件大小與 block 的大小有關。例如 block size 爲 1024 byte 時,單一文件可達 16GB 的容量。可是,咱們能夠用 ulimit 來限制使用者能夠建立的文件大小喔! 利用 ulimit -f 就能夠來配置了!例如上面的範例二,要注意單位喔!單位是 Kbytes。 若改天你一直沒法建立一個大容量的文件,記得瞧一瞧 ulimit 的信息喔!
Tips: 想要復原 ulimit 的配置最簡單的方法就是註銷再登錄,不然就是得要從新以 ulimit 配置才行! 不過,要注意的是,通常身份使用者若是以 ulimit 配置了 -f 的文件大小, 那麼他『只能繼續減少文件容量,不能添加文件容量喔!』另外,若想要管控使用者的 ulimit 限值, 能夠參考第十四章的 pam 的介紹。 |
![]() |
變量除了能夠直接配置來修改本來的內容以外,有沒有辦法透過簡單的動做來將變量的內容進行微調呢? 舉例來講,進行變量內容的刪除、取代與替換等!是能夠的!咱們能夠透過幾個簡單的小步驟來進行變量內容的微調喔! 底下就來試試看!
變量的內容能夠很簡單的透過幾個咚咚來進行刪除喔!咱們使用 PATH 這個變量的內容來作測試好了。 請你依序進行底下的幾個例子來玩玩,比較容易感覺的到鳥哥在這裏想要表達的意義:
範例一:先讓小寫的 path 自定義變量配置的與 PATH 內容相同 [root@www ~]# path=${PATH} [root@www ~]# echo $path /usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin: /usr/sbin:/usr/bin:/root/bin <==這兩行實際上是同一行啦! 範例二:假設我不喜歡 kerberos,因此要將前兩個目錄刪除掉,如何顯示? [root@www ~]# echo ${path#/*kerberos/bin:} /usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin |
上面這個範例頗有趣的!他的重點能夠用底下這張表格來講明:
${variable#/*kerberos/bin:} 上面的特殊字體部分是關鍵詞!用在這種刪除模式所必須存在的 ${variable#/*kerberos/bin:} 這就是本來的變量名稱,以上面範例二來講,這裏就填寫 path 這個『變量名稱』啦! ${variable#/*kerberos/bin:} 這是重點!表明『從變量內容的最前面開始向右刪除』,且僅刪除最短的那個 ${variable#/*kerberos/bin:} 表明要被刪除的部分,因爲 # 表明由前面開始刪除,因此這裏便由開始的 / 寫起。 須要注意的是,咱們還能夠透過通配符 * 來取代 0 到無窮多個任意字符 以上面範例二的結果來看, path 這個變量被刪除的內容以下所示: /usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin: /usr/sbin:/usr/bin:/root/bin <==這兩行實際上是同一行啦! |
頗有趣吧!這樣瞭解了 # 的功能了嗎?接下來讓咱們來看看底下的範例三!
範例三:我想要刪除前面全部的目錄,僅保留最後一個目錄 [root@www ~]# echo ${path#/*:} /usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin: /root/bin <==這兩行實際上是同一行啦! # 因爲一個 # 僅刪除掉最短的那個,所以他刪除的狀況能夠用底下的刪除線來看: # /usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin: # /usr/sbin:/usr/bin:/root/bin <==這兩行實際上是同一行啦! [root@www ~]# echo ${path##/*:} /root/bin # 嘿!多加了一個 # 變成 ## 以後,他變成『刪除掉最長的那個數據』!亦便是: # /usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin: # /usr/sbin:/usr/bin:/root/bin <==這兩行實際上是同一行啦! |
很是有趣!不是嗎?由於在 PATH 這個變量的內容中,每一個目錄都是以冒號『:』隔開的, 因此要從頭刪除掉目錄就是介於斜線 (/) 到冒號 (:) 之間的數據!可是 PATH 中不止一個冒號 (:) 啊! 因此 # 與 ## 就分別表明:
上面談到的是『從前面開始刪除變量內容』,那麼若是想要『從後面向前刪除變量內容』呢? 這個時候就得使用百分比 (%) 符號了!來看看範例四怎麼作吧!
範例四:我想要刪除最後面那個目錄,亦即從 : 到 bin 爲止的字符串 [root@www ~]# echo ${path%:*bin} /usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin: /usr/sbin:/usr/bin <==注意啊!最後面一個目錄不見去! # 這個 % 符號表明由最後面開始向前刪除!因此上面獲得的結果實際上是來自以下: # /usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin: # /usr/sbin:/usr/bin:/root/bin <==這兩行實際上是同一行啦! 範例五:那若是我只想要保留第一個目錄呢? [root@www ~]# echo ${path%%:*bin} /usr/kerberos/sbin # 一樣的, %% 表明的則是最長的符合字符串,因此結果實際上是來自以下: # /usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin: # /usr/sbin:/usr/bin:/root/bin <==這兩行實際上是同一行啦! |
因爲我是想要由變量內容的後面向前面刪除,而我這個變量內容最後面的結尾是『/root/bin』, 因此你能夠看到上面我刪除的數據最終必定是『bin』,亦便是『:*bin』那個 * 表明通配符! 至於 % 與 %% 的意義其實與 # 及 ## 相似!這樣理解否?
例題:
假設你是 root ,那你的 MAIL 變量應該是 /var/spool/mail/root 。假設你只想要保留最後面那個檔名 (root), 前面的目錄名稱都不要了,如何利用 $MAIL 變量來達成?
答:
題意實際上是這樣『
/var/spool/mail/root』,亦即刪除掉兩條斜線間的全部數據(最長符合)。 這個時候你就能夠這樣作便可:
|
瞭解了刪除功能後,接下來談談取代吧!繼續玩玩範例六囉!
範例六:將 path 的變量內容內的 sbin 取代成大寫 SBIN: [root@www ~]# echo ${path/sbin/SBIN} /usr/kerberos/SBIN:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin: /usr/sbin:/usr/bin:/root/bin # 這個部分就容易理解的多了!關鍵詞在於那兩個斜線,兩斜線中間的是舊字符串 # 後面的是新字符串,因此結果就會出現如上述的特殊字體部分囉! [root@www ~]# echo ${path//sbin/SBIN} /usr/kerberos/SBIN:/usr/kerberos/bin:/usr/local/SBIN:/usr/local/bin:/SBIN:/bin: /usr/SBIN:/usr/bin:/root/bin # 若是是兩條斜線,那麼就變成全部符合的內容都會被取代喔! |
咱們將這部份做個總結說明一下:
變量配置方式 | 說明 |
${變量#關鍵詞} ${變量##關鍵詞} |
若變量內容從頭開始的數據符合『關鍵詞』,則將符合的最短數據刪除 若變量內容從頭開始的數據符合『關鍵詞』,則將符合的最長數據刪除 |
${變量%關鍵詞} ${變量%%關鍵詞} |
若變量內容從尾向前的數據符合『關鍵詞』,則將符合的最短數據刪除 若變量內容從尾向前的數據符合『關鍵詞』,則將符合的最長數據刪除 |
${變量/舊字符串/新字符串} ${變量//舊字符串/新字符串} |
若變量內容符合『舊字符串』則『第一個舊字符串會被新字符串取代』 若變量內容符合『舊字符串』則『所有的舊字符串會被新字符串取代』 |
在某些時刻咱們經常須要『判斷』某個變量是否存在,若變量存在則使用既有的配置,若變量不存在則給予一個經常使用的配置。 咱們舉底下的例子來講明好了,看看能不能較容易被你所理解呢!
範例一:測試一下是否存在 username 這個變量,若不存在則給予 username 內容爲 root [root@www ~]# echo $username <==因爲出現空白,因此 username 可能不存在,也多是空字符串 [root@www ~]# username=${username-root} [root@www ~]# echo $username root <==由於 username 沒有配置,因此主動給予名爲 root 的內容。 [root@www ~]# username="vbird tsai" <==主動配置 username 的內容 [root@www ~]# username=${username-root} [root@www ~]# echo $username vbird tsai <==由於 username 已經配置了,因此使用舊有的配置而不以 root 取代 |
在上面的範例中,重點在於減號『 - 』後面接的關鍵詞!基本上你能夠這樣理解:
new_var=${old_var-content} 新的變量,主要用來取代舊變量。新舊變量名稱其實經常是同樣的 new_var=${old_var-content} 這是本範例中的關鍵詞部分!必需要存在的哩! new_var=${old_var-content} 舊的變量,被測試的項目! new_var=${old_var-content} 變量的『內容』,在本範例中,這個部分是在『給予未配置變量的內容』 |
不過這仍是有點問題!由於 username 可能已經被配置爲『空字符串』了!果然如此的話,那你還能夠使用底下的範例來給予 username 的內容成爲 root 喔!
範例二:若 username 未配置或爲空字符串,則將 username 內容配置爲 root [root@www ~]# username="" [root@www ~]# username=${username-root} [root@www ~]# echo $username <==由於 username 被配置爲空字符串了!因此固然仍是保留爲空字符串! [root@www ~]# username=${username:-root} [root@www ~]# echo $username root <==加上『 : 』後若變量內容爲空或者是未配置,都可以之後面的內容替換! |
在大括號內有沒有冒號『 : 』的差異是很大的!加上冒號後,被測試的變量未被配置或者是已被配置爲空字符串時, 都可以用後面的內容 (本例中是使用 root 爲內容) 來替換與配置!這樣能夠了解了嗎?除了這樣的測試以外, 還有其餘的測試方法喔!鳥哥將他整理以下:
Tips: 底下的例子當中,那個 var 與 str 爲變量,咱們想要針對 str 是否有配置來決定 var 的值喔! 通常來講, str: 表明『str 沒配置或爲空的字符串時』;至於 str 則僅爲『沒有該變量』。 |
![]() |
變量配置方式 | str 沒有配置 | str 爲空字符串 | str 已配置非爲空字符串 |
var=${str-expr} | var=expr | var= | var=$str |
var=${str:-expr} | var=expr | var=expr | var=$str |
var=${str+expr} | var= | var=expr | var=expr |
var=${str:+expr} | var= | var= | var=expr |
var=${str=expr} | str=expr var=expr |
str 不變 var= |
str 不變 var=$str |
var=${str:=expr} | str=expr var=expr |
str=expr var=expr |
str 不變 var=$str |
var=${str?expr} | expr 輸出至 stderr | var= | var=$str |
var=${str:?expr} | expr 輸出至 stderr | expr 輸出至 stderr | var=$str |
根據上面這張表,咱們來進行幾個範例的練習吧! ^_^!首先讓咱們來測試一下,若是舊變量 (str) 不存在時, 咱們要給予新變量一個內容,若舊變量存在則新變量內容以舊變量來替換,結果以下:
測試:先假設 str 不存在 (用 unset) ,而後測試一下減號 (-) 的用法: [root@www ~]# unset str; var=${str-newvar} [root@www ~]# echo var="$var", str="$str" var=newvar, str= <==由於 str 不存在,因此 var 爲 newvar 測試:若 str 已存在,測試一下 var 會變怎樣?: [root@www ~]# str="oldvar"; var=${str-newvar} [root@www ~]# echo var="$var", str="$str" var=oldvar, str=oldvar <==由於 str 存在,因此 var 等於 str 的內容 |
關於減號 (-) 其實上面咱們談過了!這裏的測試只是要讓你更加了解,這個減號的測試並不會影響到舊變量的內容。 若是你想要將舊變量內容也一塊兒替換掉的話,那麼就使用等號 (=) 吧!
測試:先假設 str 不存在 (用 unset) ,而後測試一下等號 (=) 的用法: [root@www ~]# unset str; var=${str=newvar} [root@www ~]# echo var="$var", str="$str" var=newvar, str=newvar <==由於 str 不存在,因此 var/str 均爲 newvar 測試:若是 str 已存在了,測試一下 var 會變怎樣? [root@www ~]# str="oldvar"; var=${str=newvar} [root@www ~]# echo var="$var", str="$str" var=oldvar, str=oldvar <==由於 str 存在,因此 var 等於 str 的內容 |
那若是我只是想知道,若是舊變量不存在時,整個測試就告知我『有錯誤』,此時就可以使用問號『 ? 』的幫忙啦! 底下這個測試練習一下先!
測試:若 str 不存在時,則 var 的測試結果直接顯示 "無此變量" [root@www ~]# unset str; var=${str?無此變量} -bash: str: 無此變量 <==由於 str 不存在,因此輸出錯誤信息 測試:若 str 存在時,則 var 的內容會與 str 相同! [root@www ~]# str="oldvar"; var=${str?novar} [root@www ~]# echo var="$var", str="$str" var=oldvar, str=oldvar <==由於 str 存在,因此 var 等於 str 的內容 |
基本上這種變量的測試也可以透過 shell script 內的 if...then... 來處理, 不過既然 bash 有提供這麼簡單的方法來測試變量,那咱們也能夠多學一些嘛! 不過這種變量測試一般是在程序設計當中比較容易出現,若是這裏看不懂就先略過,將來有用到判斷變量值時,再回來看看吧! ^_^
咱們知道在早期的 DOS 年代,清除屏幕上的信息能夠使用 cls 來清除,可是在 Linux 裏面, 咱們則是使用 clear 來清除畫面的。那麼能否讓 cls 等於 clear 呢?能夠啊!用啥方法? link file 仍是什麼的?別急!底下咱們介紹不用 link file 的命令別名來達成。那麼什麼又是歷史命令? 曾經作過的舉動咱們能夠將他記錄下來喔!那就是歷史命令囉~底下分別來談一談這兩個玩意兒。
命令別名是一個頗有趣的東西,特別是你的慣用命令特別長的時候!還有, 增設默認的選項在一些慣用的命令上面,能夠預防一些不當心誤殺文件的狀況發生的時候! 舉個例子來講,若是你要查詢隱藏檔,而且須要長的列出與一頁一頁翻看,那麼須要下達『 ls -al | more 』這個命令,我是以爲很煩啦! 要輸入好幾個單字!那可不能夠使用 lm 來簡化呢?固然能夠,你能夠在命令行下面下達:
[root@www ~]# alias lm='ls -al | more'
|
馬上多出了一個能夠運行的命令喔!這個命令名稱爲 lm ,且其實他是運行 ls -al | more 啊!真是方便。不過, 要注意的是:『alias 的定義守則與變量定義守則幾乎相同』, 因此你只要在 alias 後面加上你的 {『別名』='命令 選項...' }, 之後你只要輸入 lm 就至關於輸入了 ls -al|more 這一串命令!很方便吧!
另外,命令別名的配置還能夠取代既有的命令喔!舉例來講,咱們知道 root 能夠移除 (rm) 任何數據!因此當你以 root 的身份在進行工做時,須要特別當心, 可是總有失手的時候,那麼 rm 提供了一個選項來讓咱們確認是否要移除該文件,那就是 -i 這個選項!因此,你能夠這樣作:
[root@www ~]# alias rm='rm -i'
|
那麼之後使用 rm 的時候,就不用太擔憂會有錯誤刪除的狀況了!這也是命令別名的優勢囉! 那麼如何知道目前有哪些的命令別名呢?就使用 alias 呀!
[root@www ~]# alias
alias cp='cp -i'
alias l.='ls -d .* --color=tty'
alias ll='ls -l --color=tty'
alias lm='ls -l | more'
alias ls='ls --color=tty'
alias mv='mv -i'
alias rm='rm -i'
alias which='alias | /usr/bin/which --tty-only --show-dot --show-tilde'
|
由上面的數據當中,你也會發現一件事情啊,咱們在第十章的 vim 程序編輯器裏面提到 vi 與 vim 是不太同樣的,vim 能夠多做一些額外的語法檢驗與顏色顯示,默認的 root 是單純使用 vi 而已。 若是你想要使用 vi 就直接以 vim 來開啓文件的話,使用『 alias vi='vim' 』這個配置便可。 至於若是要取消命令別名的話,那麼就使用 unalias 吧!例如要將剛剛的 lm 命令別名拿掉,就使用:
[root@www ~]# unalias lm
|
那麼命令別名與變量有什麼不一樣呢?命令別名是『新創一個新的命令, 你能夠直接下達該命令』的,至於變量則須要使用相似『 echo 』命令纔可以呼叫出變量的內容! 這二者固然不同!不少初學者在這裏總是搞不清楚!要注意啊! ^_^
例題:
DOS 年代,列出目錄與文件就是 dir ,而清除屏幕就是 cls ,那麼若是我想要在 linux 裏面也使用相同的命令呢?
答:
很簡單,透過 clear 與 ls 來進行命令別名的建置:
alias cls='clear' |
前面咱們提過 bash 有提供命令歷史的服務!那麼如何查詢咱們曾經下達過的命令呢?就使用 history 囉!固然,若是以爲 histsory 要輸入的字符太多太麻煩,能夠使用命令別名來配置呢! 不要跟我說還不會配置呦! ^_^
[root@www ~]# alias h='history'
|
如此則輸入 h 等於輸入 history 囉!好了,咱們來談一談 history 的用法吧!
[root@www ~]# history [n] [root@www ~]# history [-c] [root@www ~]# history [-raw] histfiles 選項與參數: n :數字,意思是『要列出最近的 n 筆命令行表』的意思! -c :將目前的 shell 中的全部 history 內容所有消除 -a :將目前新增的 history 命令新增入 histfiles 中,若沒有加 histfiles , 則默認寫入 ~/.bash_history -r :將 histfiles 的內容讀到目前這個 shell 的 history 記憶中; -w :將目前的 history 記憶內容寫入 histfiles 中! 範例一:列出目前內存內的全部 history 記憶 [root@www ~]# history # 前面省略 1017 man bash 1018 ll 1019 history 1020 history # 列出的信息當中,共分兩欄,第一欄爲該命令在這個 shell 當中的代碼, # 另外一個則是命令自己的內容喔!至於會秀出幾筆命令記錄,則與 HISTSIZE 有關! 範例二:列出目前最近的 3 筆數據 [root@www ~]# history 3 1019 history 1020 history 1021 history 3 範例三:馬上將目前的數據寫入 histfile 當中 [root@www ~]# history -w # 在默認的狀況下,會將歷史紀錄寫入 ~/.bash_history 當中! [root@www ~]# echo $HISTSIZE 1000 |
在正常的狀況下,歷史命令的讀取與記錄是這樣的:
那麼 history 這個歷史命令只可讓我查詢命令而已嗎?呵呵!固然不止啊! 咱們能夠利用相關的功能來幫咱們運行命令呢!舉例來講囉:
[root@www ~]# !number [root@www ~]# !command [root@www ~]# !! 選項與參數: number :運行第幾筆命令的意思; command :由最近的命令向前搜尋『命令串開頭爲 command』的那個命令,並運行; !! :就是運行上一個命令(至關於按↑按鍵後,按 Enter) [root@www ~]# history 66 man rm 67 alias 68 man history 69 history [root@www ~]# !66 <==運行第 66 筆命令 [root@www ~]# !! <==運行上一個命令,本例中亦即 !66 [root@www ~]# !al <==運行最近以 al 爲開頭的命令(上頭列出的第 67 個) |
通過上面的介紹,瞭乎?歷史命令用法可多了!若是我想要運行上一個命令, 除了使用上下鍵以外,我能夠直接以『 !! 』 來下達上個命令的內容,此外, 我也能夠直接選擇下達第 n 個命令,『 !n 』來運行,也能夠使用命令標頭,例如 『 !vi 』來運行最近命令開頭是 vi 的命令列!至關的方便而好用!
基本上 history 的用途很大的!可是須要當心安全的問題!尤爲是 root 的歷史紀錄文件,這是 Cracker 的最愛!由於不當心的 root 會將不少的重要數據在運行的過程當中會被紀錄在 ~/.bash_history 當中,若是這個文件被解析的話,後果不堪吶!不管如何,使用 history 配合『 ! 』曾經使用過的命令下達是頗有效率的一個命令下達方法!
有些朋友在練習 linux 的時候喜歡同時開好幾個 bash 接口,這些 bash 的身份都是 root 。 這樣會有 ~/.bash_history 的寫入問題嗎?想想,由於這些 bash 在同時以 root 的身份登錄, 所以全部的 bash 都有本身的 1000 筆記錄在內存中。由於等到註銷時纔會升級記錄文件,因此囉, 最後註銷的那個 bash 纔會是最後寫入的數據。唔!如此一來其餘 bash 的命令操做就不會被記錄下來了 (其實有被記錄,只是被後來的最後一個 bash 所覆蓋升級了) 。
因爲多重登錄有這樣的問題,因此不少朋友都習慣單一 bash 登錄,再用工做控制 (job control, 第四篇會介紹) 來切換不一樣工做! 這樣纔可以將全部曾經下達過的命令記錄下來,也才方便將來系統管理員進行命令的 debug 啊!
歷史命令還有一個問題,那就是沒法記錄命令下達的時間。因爲這 1000 筆歷史命令是依序記錄的, 可是並無記錄時間,因此在查詢方面會有一些不方便。若是讀者們有興趣,其實能夠透過 ~/.bash_logout 來進行 history 的記錄,並加上 date 來添加時間參數,也是一個能夠應用的方向喔! 有興趣的朋友能夠先看看情境模擬題一吧!
是否記得咱們登錄主機的時候,屏幕上頭會有一些說明文字,告知咱們的 Linux 版本啊什麼的, 還有,登錄的時候咱們還能夠給予用戶一些信息或者歡迎文字呢。此外, 咱們習慣的環境變量、命令別名等等的,是否能夠登錄就主動的幫我配置好? 這些都是須要注意的。另外,這些配置值又能夠分爲系統總體配置值與各人喜愛配置值, 僅是一些文件放置的地點不一樣啦!這咱們後面也會來談一談的!
咱們在第六章與第七章都曾談過『相對路徑與絕對路徑』的關係, 在本章的前幾小節也談到了 alias 與 bash 的內建命令。如今咱們知道系統裏面其實有很多的 ls 命令, 或者是包括內建的 echo 命令,那麼來想想,若是一個命令 (例如 ls) 被下達時, 究竟是哪個 ls 被拿來運行?頗有趣吧!基本上,命令運行的順序能夠這樣看:
舉例來講,你能夠下達 /bin/ls 及單純的 ls 看看,會發現使用 ls 有顏色可是 /bin/ls 則沒有顏色。 由於 /bin/ls 是直接取用該命令來下達,而 ls 會由於『 alias ls='ls --color=tty' 』這個命令別名而先使用! 若是想要了解命令搜尋的順序,其實透過 type -a ls 也能夠查詢的到啦!上述的順序最好先了解喔!
例題:
配置 echo 的命令別名成爲 echo -n ,而後再觀察 echo 運行的順序
答:
|
什麼! bash 也有進站畫面與歡迎信息喔?真假?真的啊! 還記得在終端機接口 (tty1 ~ tty6) 登錄的時候,會有幾行提示的字符串嗎?那就是進站畫面啊! 那個字符串寫在哪裏啊?呵呵!在 /etc/issue 裏面啊!先來看看:
[root@www ~]# cat /etc/issue
CentOS release 5.3 (Final)
Kernel \r on an \m
|
鳥哥是以徹底未升級過的 CentOS 5.3 做爲範例,裏面默認有三行,較有趣的地方在於 \r 與 \m。 就如同 $PS1 這變量同樣,issue 這個文件的內容也是能夠使用反斜槓做爲變量取用喔!你能夠 man issue 配合 man mingetty 獲得底下的結果:
issue 內的各代碼意義 |
\d 本地端時間的日期; \l 顯示第幾個終端機接口; \m 顯示硬件的等級 (i386/i486/i586/i686...); \n 顯示主機的網絡名稱; \o 顯示 domain name; \r 操做系統的版本 (至關於 uname -r) \t 顯示本地端時間的時間; \s 操做系統的名稱; \v 操做系統的版本。 |
作一下底下這個練習,看看能不能取得你要的進站畫面?
例題:
若是你在 tty3 的進站畫面看到以下顯示,該如何配置才能獲得以下畫面?
答:
CentOS release 5.3 (Final) (terminal: tty3)注意,tty3 在不一樣的 tty 有不一樣顯示,日期則是再按下 [enter] 後就會全部不一樣。
很簡單,參考上述的反斜槓功能去修改 /etc/issue 成爲以下模樣便可(共五行):
|
你要注意的是,除了 /etc/issue 以外還有個 /etc/issue.net 呢!這是啥?這個是提供給 telnet 這個遠程登陸程序用的。 當咱們使用 telnet 鏈接到主機時,主機的登錄畫面就會顯示 /etc/issue.net 而不是 /etc/issue 呢!
至於若是您想要讓使用者登錄後取得一些信息,例如您想要讓你們都知道的信息, 那麼能夠將信息加入 /etc/motd 裏面去!例如:當登錄後,告訴登錄者, 系統將會在某個固定時間進行維護工做,能夠這樣作:
[root@www ~]# vi /etc/motd Hello everyone, Our server will be maintained at 2009/02/28 0:00 ~ 24:00. Please don't login server at that time. ^_^ |
那麼當你的使用者(包括全部的通常帳號與 root)登錄主機後,就會顯示這樣的信息出來:
Last login: Thu Feb 5 22:35:47 2009 from 127.0.0.1 Hello everyone, Our server will be maintained at 2009/02/28 0:00 ~ 24:00. Please don't login server at that time. ^_^ |
你是否會以爲奇怪,怎麼咱們什麼動做都沒有進行,可是一進入 bash 就取得一堆有用的變量了? 這是由於系統有一些環境配置文件案的存在,讓 bash 在啓動時直接讀取這些配置文件,以規劃好 bash 的操做環境啦! 而這些配置文件又能夠分爲全體系統的配置文件以及用戶我的偏好配置文件。要注意的是, 咱們前幾個小節談到的命令別名啦、自定義的變量啦,在你註銷 bash 後就會失效,因此你想要保留你的配置, 就得要將這些配置寫入配置文件才行。底下就讓咱們來聊聊吧!
在開始介紹 bash 的配置文件前,咱們必定要先知道的就是 login shell 與 non-login shell! 重點在於有沒有登錄 (login) 啦!
爲何要介紹 login, non-login shell 呢?這是由於這兩個取得 bash 的狀況中,讀取的配置文件數據並不同所致。 因爲咱們須要登錄系統,因此先談談 login shell 會讀取哪些配置文件?通常來講,login shell 其實只會讀取這兩個配置文件:
那麼,就讓咱們來聊一聊這兩個文件吧!這兩個文件的內容但是很是繁複的喔!
你能夠使用 vim 去閱讀一下這個文件的內容。這個配置文件能夠利用使用者的標識符 (UID) 來決定不少重要的變量數據, 這也是每一個使用者登錄取得 bash 時必定會讀取的配置文件! 因此若是你想要幫全部使用者配置總體環境,那就是改這裏囉!不過,沒事仍是不要隨便改這個文件喔 這個文件配置的變量主要有:
/etc/profile 可不止會作這些事而已,他還會去呼叫外部的配置數據喔!在 CentOS 5.x 默認的狀況下, 底下這些數據會依序的被呼叫進來:
反正你只要記得,bash 的 login shell 狀況下所讀取的總體環境配置文件其實只有 /etc/profile,可是 /etc/profile 還會呼叫出其餘的配置文件,因此讓咱們的 bash 操做接口變的很是的友善啦! 接下來,讓咱們來瞧瞧,那麼我的偏好的配置文件又是怎麼回事?
bash 在讀完了總體環境配置的 /etc/profile 並藉此呼叫其餘配置文件後,接下來則是會讀取使用者的我的配置文件。 在 login shell 的 bash 環境中,所讀取的我的偏好配置文件其實主要有三個,依序分別是:
其實 bash 的 login shell 配置只會讀取上面三個文件的其中一個, 而讀取的順序則是依照上面的順序。也就是說,若是 ~/.bash_profile 存在,那麼其餘兩個文件不論有無存在,都不會被讀取。 若是 ~/.bash_profile 不存在纔會去讀取 ~/.bash_login,而前二者都不存在纔會讀取 ~/.profile 的意思。 會有這麼多的文件,實際上是因應其餘 shell 轉換過來的使用者的習慣而已。 先讓咱們來看一下 root 的 /root/.bash_profile 的內容是怎樣呢?
[root@www ~]# cat ~/.bash_profile # .bash_profile # Get the aliases and functions if [ -f ~/.bashrc ]; then <==底下這三行在判斷並讀取 ~/.bashrc . ~/.bashrc fi # User specific environment and startup programs PATH=$PATH:$HOME/bin <==底下這幾行在處理我的化配置 export PATH unset USERNAME |
這個文件內有配置 PATH 這個變量喔!並且還使用了 export 將 PATH 變成環境變量呢! 因爲 PATH 在 /etc/profile 當中已經配置過,因此在這裏就以累加的方式添加用戶家目錄下的 ~/bin/ 爲額外的運行文件放置目錄。這也就是說,你能夠將本身建立的運行檔放置到你本身家目錄下的 ~/bin/ 目錄啦! 那就能夠直接運行該運行檔而不須要使用絕對/相對路徑來運行該文件。
這個文件的內容比較有趣的地方在於 if ... then ... 那一段!那一段程序代碼咱們會在第十三章 shell script 談到,假設你如今是看不懂的。 該段的內容指的是『判斷家目錄下的 ~/.bashrc 存在否,若存在則讀入 ~/.bashrc 的配置』。 bash 配置文件的讀入方式比較有趣,主要是透過一個命令『 source 』來讀取的! 也就是說 ~/.bash_profile 其實會再呼叫 ~/.bashrc 的配置內容喔!最後,咱們來看看整個 login shell 的讀取流程:
實線的的方向是主線流程,虛線的方向則是被呼叫的配置文件!從上面咱們也能夠清楚的知道,在 CentOS 的 login shell 環境下,最終被讀取的配置文件是『 ~/.bashrc 』這個文件喔!因此,你固然能夠將本身的偏好配置寫入該文件便可。 底下咱們還要討論一下 source 與 ~/.bashrc 喔!
因爲 /etc/profile 與 ~/.bash_profile 都是在取得 login shell 的時候纔會讀取的配置文件,因此, 若是你將本身的偏好配置寫入上述的文件後,一般都是得註銷再登錄後,該配置纔會生效。那麼,能不能直接讀取配置文件而不註銷登錄呢? 能夠的!那就得要利用 source 這個命令了!
[root@www ~]# source 配置文件檔名 範例:將家目錄的 ~/.bashrc 的配置讀入目前的 bash 環境中 [root@www ~]# source ~/.bashrc <==底下這兩個命令是同樣的! [root@www ~]# . ~/.bashrc |
利用 source 或小數點 (.) 均可以將配置文件的內容讀進來目前的 shell 環境中! 舉例來講,我修改了 ~/.bashrc ,那麼不須要註銷,當即以 source ~/.bashrc 就能夠將剛剛最新配置的內容讀進來目前的環境中!很不錯吧!還有,包括 ~/bash_profile 以及 /etc/profile 的配置中, 不少時候也都是利用到這個 source (或小數點) 的功能喔!
有沒有可能會使用到不一樣環境配置文件的時候?有啊! 最常發生在一我的的工做環境分爲多種狀況的時候了!舉個例子來講,在鳥哥的大型主機中, 經常須要負責兩到三個不一樣的案子,每一個案子所須要處理的環境變量訂定並不相同, 那麼鳥哥就將這兩三個案子分別編寫屬於該案子的環境變量配置文件案,當須要該環境時,就直接『 source 變量文件 』,如此一來,環境變量的配置就變的更簡便而靈活了!
談完了 login shell 後,那麼 non-login shell 這種非登錄狀況取得 bash 操做接口的環境配置文件又是什麼? 當你取得 non-login shell 時,該 bash 配置文件僅會讀取 ~/.bashrc 而已啦!那麼默認的 ~/.bashrc 內容是如何?
[root@www ~]# cat ~/.bashrc # .bashrc # User specific aliases and functions alias rm='rm -i' <==使用者的我的配置 alias cp='cp -i' alias mv='mv -i' # Source global definitions if [ -f /etc/bashrc ]; then <==總體的環境配置 . /etc/bashrc fi |
特別注意一下,因爲 root 的身份與通常使用者不一樣,鳥哥是以 root 的身份取得上述的數據, 若是是通常使用者的 ~/.bashrc 會有些許不一樣。看一下,你會發如今 root 的 ~/.bashrc 中其實已經規範了較爲保險的命令別名了。 此外,我們的 CentOS 5.x 還會主動的呼叫 /etc/bashrc 這個文件喔!爲何須要呼叫 /etc/bashrc 呢? 由於 /etc/bashrc 幫咱們的 bash 定義出底下的數據:
你要注意的是,這個 /etc/bashrc 是 CentOS 特有的 (實際上是 Red Hat 系統特有的),其餘不一樣的 distributions 可能會放置在不一樣的檔名就是了。因爲這個 ~/.bashrc 會呼叫 /etc/bashrc 及 /etc/profile.d/*.sh , 因此,萬一你沒有 ~/.bashrc (可能本身不當心將他刪除了),那麼你會發現你的 bash 提示字符可能會變成這個樣子:
-bash-3.2$ |
不要太擔憂啦!這是正常的,由於你並無呼叫 /etc/bashrc 來規範 PS1 變量啦!並且這樣的狀況也不會影響你的 bash 使用。 若是你想要將命令提示字符捉回來,那麼能夠複製 /etc/skel/.bashrc 到你的家目錄,再修訂一下你所想要的內容, 並使用 source 去呼叫 ~/.bashrc ,那你的命令提示字符就會回來啦!
事實上還有一些配置文件可能會影響到你的 bash 操做的,底下就來談一談:
咱們在第五章首次登錄 Linux 時就提過,能夠在 tty1 ~ tty6 這六個文字接口的終端機 (terminal) 環境中登錄,登錄的時候咱們能夠取得一些字符配置的功能喔! 舉例來講,咱們能夠利用退格鍵 (backspace,就是那個←符號的按鍵) 來刪除命令行上的字符, 也能夠使用 [ctrl]+c 來強制終止一個命令的運行,當輸入錯誤時,就會有聲音跑出來警告。這是怎麼辦到的呢? 很簡單啊!由於登錄終端機的時候,會自動的取得一些終端機的輸入環境的配置啊!
事實上,目前咱們使用的 Linux distributions 都幫咱們做了最棒的使用者環境了, 因此你們能夠不用擔憂操做環境的問題。不過,在某些 Unix like 的機器中,仍是可能須要動用一些手腳, 纔可以讓咱們的輸入比較快樂~舉例來講,利用 [backspace] 刪除,要比利用 [Del] 按鍵來的順手吧! 可是某些 Unix 恰恰是以 [del] 來進行字符的刪除啊!因此,這個時候就能夠動動手腳囉~
那麼如何查閱目前的一些按鍵內容呢?能夠利用 stty (setting tty 終端機的意思) 呢! stty 也能夠幫助配置終端機的輸入按鍵表明意義喔!
[root@www ~]# stty [-a] 選項與參數: -a :將目前全部的 stty 參數列出來; 範例一:列出全部的按鍵與按鍵內容 [root@www ~]# stty -a speed 38400 baud; rows 24; columns 80; line = 0; intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>; eol2 = <undef>; swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V; flush = ^O; min = 1; time = 0; ....(如下省略).... |
咱們能夠利用 stty -a 來列出目前環境中全部的按鍵列表,在上頭的列表當中,須要注意的是特殊字體那幾個, 此外,若是出現 ^ 表示 [Ctrl] 那個按鍵的意思。舉例來講, intr = ^C 表示利用 [ctrl] + c 來達成的。幾個重要的表明意義是:
記不記得咱們在第五章講過幾個 Linux 熱鍵啊?沒錯! 就是這個 stty 配置值內的 intr / eof 囉~至於刪除字符,就是 erase 那個配置值啦! 若是你想要用 [ctrl]+h 來進行字符的刪除,那麼能夠下達:
[root@www ~]# stty erase ^h
|
那麼今後以後,你的刪除字符就得要使用 [ctrl]+h 囉,按下 [backspace] 則會出現 ^? 字樣呢! 若是想要回複利用 [backspace] ,就下達 stty erase ^? 便可啊! 至於更多的 stty 說明,記得參考一下 man stty 的內容喔!
除了 stty 以外,其實咱們的 bash 還有本身的一些終端機配置值呢!那就是利用 set 來配置的! 咱們以前提到一些變量時,能夠利用 set 來顯示,除此以外,其實 set 還能夠幫咱們配置整個命令輸出/輸入的環境。 例如記錄歷史命令、顯示錯誤內容等等。
[root@www ~]# set [-uvCHhmBx] 選項與參數: -u :默認不激活。若激活後,當使用未配置變量時,會顯示錯誤信息; -v :默認不激活。若激活後,在信息被輸出前,會先顯示信息的原始內容; -x :默認不激活。若激活後,在命令被運行前,會顯示命令內容(前面有 ++ 符號) -h :默認激活。與歷史命令有關; -H :默認激活。與歷史命令有關; -m :默認激活。與工做管理有關; -B :默認激活。與刮號 [] 的做用有關; -C :默認不激活。若使用 > 等,則若文件存在時,該文件不會被覆蓋。 範例一:顯示目前全部的 set 配置值 [root@www ~]# echo $- himBH # 那個 $- 變量內容就是 set 的全部配置啦! bash 默認是 himBH 喔! 範例二:配置 "若使用未定義變量時,則顯示錯誤信息" [root@www ~]# set -u [root@www ~]# echo $vbirding -bash: vbirding: unbound variable # 默認狀況下,未配置/未宣告 的變量都會是『空的』,不過,若配置 -u 參數, # 那麼當使用未配置的變量時,就會有問題啦!不少的 shell 都默認激活 -u 參數。 # 若要取消這個參數,輸入 set +u 便可! 範例三:運行前,顯示該命令內容。 [root@www ~]# set -x [root@www ~]# echo $HOME + echo /root /root ++ echo -ne '\033]0;root@www:~' # 看見否?要輸出的命令都會先被打印到屏幕上喔!前面會多出 + 的符號! |
另外,其實咱們還有其餘的按鍵配置功能呢!就是在前一小節提到的 /etc/inputrc 這個文件裏面配置。
[root@www ~]# cat /etc/inputrc # do not bell on tab-completion #set bell-style none set meta-flag on set input-meta on set convert-meta off set output-meta on .....如下省略..... |
還有例如 /etc/DIR_COLORS* 與 /etc/termcap 等,也都是與終端機有關的環境配置文件案呢! 不過,事實上,鳥哥並不建議您修改 tty 的環境呢,這是由於 bash 的環境已經配置的很親和了, 咱們不須要額外的配置或者修改,不然反而會產生一些困擾。不過,寫在這裏的數據, 只是但願你們可以清楚的知道咱們的終端機是如何進行配置的喔! ^_^! 最後,咱們將 bash 默認的組合鍵給他彙整以下:
組合按鍵 | 運行結果 |
Ctrl + C | 終止目前的命令 |
Ctrl + D | 輸入結束 (EOF),例如郵件結束的時候; |
Ctrl + M | 就是 Enter 啦! |
Ctrl + S | 暫停屏幕的輸出 |
Ctrl + Q | 恢復屏幕的輸出 |
Ctrl + U | 在提示字符下,將整列命令刪除 |
Ctrl + Z | 『暫停』目前的命令 |
在 bash 的操做環境中還有一個很是有用的功能,那就是通配符 (wildcard) ! 咱們利用 bash 處理數據就更方便了!底下咱們列出一些經常使用的通配符喔:
符號 | 意義 |
* | 表明『 0 個到無窮多個』任意字符 |
? | 表明『必定有一個』任意字符 |
[ ] | 一樣表明『必定有一個在括號內』的字符(非任意字符)。例如 [abcd] 表明『必定有一個字符, 多是 a, b, c, d 這四個任何一個』 |
[ - ] | 如有減號在中括號內時,表明『在編碼順序內的全部字符』。例如 [0-9] 表明 0 到 9 之間的全部數字,由於數字的語系編碼是連續的! |
[^ ] | 若中括號內的第一個字符爲指數符號 (^) ,那表示『反向選擇』,例如 [^abc] 表明 必定有一個字符,只要是非 a, b, c 的其餘字符就接受的意思。 |
接下來讓咱們利用通配符來玩些東西吧!首先,利用通配符配合 ls 找檔名看看:
[root@www ~]# LANG=C <==因爲與編碼有關,先配置語系一下 範例一:找出 /etc/ 底下以 cron 爲開頭的檔名 [root@www ~]# ll -d /etc/cron* <==加上 -d 是爲了僅顯示目錄而已 範例二:找出 /etc/ 底下文件名『恰好是五個字母』的文件名 [root@www ~]# ll -d /etc/????? <==因爲 ? 必定有一個,因此五個 ? 就對了 範例三:找出 /etc/ 底下文件名含有數字的文件名 [root@www ~]# ll -d /etc/*[0-9]* <==記得中括號左右兩邊均需 * 範例四:找出 /etc/ 底下,檔名開頭非爲小寫字母的文件名: [root@www ~]# ll -d /etc/[^a-z]* <==注意中括號左邊沒有 * 範例五:將範例四找到的文件複製到 /tmp 中 [root@www ~]# cp -a /etc/[^a-z]* /tmp |
除了通配符以外,bash 環境中的特殊符號有哪些呢?底下咱們先彙整一下:
符號 | 內容 |
# | 批註符號:這個最常被使用在 script 當中,視爲說明!在後的數據均不運行 |
\ | 跳脫符號:將『特殊字符或通配符』還原成通常字符 |
| | 管線 (pipe):分隔兩個管線命令的界定(後兩節介紹); |
; | 連續命令下達分隔符:連續性命令的界定 (注意!與管線命令並不相同) |
~ | 用戶的家目錄 |
$ | 取用變量前導符:亦便是變量以前須要加的變量取代值 |
& | 工做控制 (job control):將命令變成背景下工做 |
! | 邏輯運算意義上的『非』 not 的意思! |
/ | 目錄符號:路徑分隔的符號 |
>, >> | 數據流重導向:輸出導向,分別是『取代』與『累加』 |
<, << | 數據流重導向:輸入導向 (這兩個留待下節介紹) |
' ' | 單引號,不具備變量置換的功能 |
" " | 具備變量置換的功能! |
` ` | 兩個『 ` 』中間爲能夠先運行的命令,亦可以使用 $( ) |
( ) | 在中間爲子 shell 的起始與結束 |
{ } | 在中間爲命令區塊的組合! |
以上爲 bash 環境中常見的特殊符號彙整!理論上,你的『檔名』儘可能不要使用到上述的字符啦!
數據流重導向 (redirect) 由字面上的意思來看,好像就是將『數據給他傳導到其餘地方去』的樣子? 沒錯~數據流重導向就是將某個命令運行後應該要出如今屏幕上的數據, 給他傳輸到其餘的地方,例如文件或者是裝置 (例如打印機之類的)!這玩意兒在 Linux 的文本模式底下可重要的! 尤爲是若是咱們想要將某些數據儲存下來時,就更有用了!
什麼是數據流重導向啊?這得要由命令的運行結果談起!通常來講,若是你要運行一個命令,一般他會是這樣的:
咱們運行一個命令的時候,這個命令可能會由文件讀入數據,通過處理以後,再將數據輸出到屏幕上。 在上圖當中, standard output 與 standard error output 分別表明『標準輸出』與『標準錯誤輸出』, 這兩個玩意兒默認都是輸出到屏幕上面來的啊!那麼什麼是標準輸出與標準錯誤輸出呢?
簡單的說,標準輸出指的是『命令運行所回傳的正確的信息』,而標準錯誤輸出可理解爲『 命令運行失敗後,所回傳的錯誤信息』。舉個簡單例子來講,咱們的系統默認有 /etc/crontab 但卻無 /etc/vbirdsay, 此時若下達『 cat /etc/crontab /etc/vbirdsay 』這個命令時,cat 會進行:
無論正確或錯誤的數據都是默認輸出到屏幕上,因此屏幕固然是亂亂的!那能不能透過某些機制將這兩股數據分開呢? 固然能夠啊!那就是數據流重導向的功能啊!數據流重導向能夠將 standard output (簡稱 stdout) 與 standard error output (簡稱 stderr) 分別傳送到其餘的文件或裝置去,而分別傳送所用的特殊字符則以下所示:
爲了理解 stdout 與 stderr ,咱們先來進行一個範例的練習:
範例一:觀察你的系統根目錄 (/) 下各目錄的文件名、權限與屬性,並記錄下來 [root@www ~]# ll / <==此時屏幕會顯示出文件名信息 [root@www ~]# ll / > ~/rootfile <==屏幕並沒有任何信息 [root@www ~]# ll ~/rootfile <==有個新檔被建立了! -rw-r--r-- 1 root root 1089 Feb 6 17:00 /root/rootfile |
怪了!屏幕怎麼會徹底沒有數據呢?這是由於本來『 ll / 』所顯示的數據已經被從新導向到 ~/rootfile 文件中了! 那個 ~/rootfile 的檔名能夠隨便你取。若是你下達『 cat ~/rootfile 』那就能夠看到本來應該在屏幕上面的數據囉。 若是我再次下達:『 ll /home > ~/rootfile 』後,那個 ~/rootfile 文件的內容變成什麼? 他將變成『僅有 ll /home 的數據』而已!咦!本來的『 ll / 』數據就不見了嗎?是的!由於該文件的建立方式是:
那若是我想要將數據累加而不想要將舊的數據刪除,那該如何是好?利用兩個大於的符號 (>>) 就好啦!以上面的範例來講,你應該要改爲『 ll / >> ~/rootfile 』便可。 如此一來,當 (1) ~/rootfile 不存在時系統會主動建立這個文件;(2)若該文件已存在, 則數據會在該文件的最下方累加進去!
上面談到的是 standard output 的正確數據,那若是是 standard error output 的錯誤數據呢?那就透過 2> 及 2>> 囉!一樣是覆蓋 (2>) 與累加 (2>>) 的特性!咱們在剛剛纔談到 stdout 代碼是 1 而 stderr 代碼是 2 , 因此這個 2> 是很容易理解的,而若是僅存在 > 時,則表明默認的代碼 1 囉!也就是說:
要注意喔,『 1>> 』以及『 2>> 』中間是沒有空格的!OK!有些概念以後讓咱們繼續聊一聊這傢伙怎麼應用吧! 當你以通常身份運行 find 這個命令的時候,因爲權限的問題可能會產生一些錯誤信息。例如運行『 find / -name testing 』時,可能會產生相似『 find: /root: Permission denied 』之類的信息。 例如底下這個範例:
範例二:利用通常身份帳號搜尋 /home 底下是否有名爲 .bashrc 的文件存在 [root@www ~]# su - dmtsai <==假設個人系統有名爲 dmtsai 的帳號 [dmtsai@www ~]$ find /home -name .bashrc <==身份是 dmtsai 喔! find: /home/lost+found: Permission denied <== Standard error find: /home/alex: Permission denied <== Standard error find: /home/arod: Permission denied <== Standard error /home/dmtsai/.bashrc <== Standard output |
因爲 /home 底下還有咱們以前建立的帳號存在,那些帳號的家目錄你固然不能進入啊!因此就會有錯誤及正確數據了。 好了,那麼假如我想要將數據輸出到 list 這個文件中呢?運行『 find /home -name .bashrc > list 』 會有什麼結果?呵呵,你會發現 list 裏面存了剛剛那個『正確』的輸出數據, 至於屏幕上仍是會有錯誤的信息出現呢!傷腦筋!若是想要將正確的與錯誤的數據分別存入不一樣的文件中須要怎麼作?
範例三:承範例二,將 stdout 與 stderr 分存到不一樣的文件去 [dmtsai@www ~]$ find /home -name .bashrc > list_right 2> list_error |
注意喔,此時『屏幕上不會出現任何信息』!由於剛剛運行的結果中,有 Permission 的那幾行錯誤信息都會跑到 list_error 這個文件中,至於正確的輸出數據則會存到 list_right 這個文件中囉!這樣能夠了解了嗎? 若是有點混亂的話,去休息一下再來看看吧!
想象一下,若是我知道錯誤信息會發生,因此要將錯誤信息忽略掉而不顯示或儲存呢? 這個時候黑洞裝置 /dev/null 就很重要了!這個 /dev/null 能夠吃掉任何導向這個裝置的信息喔!將上述的範例修訂一下:
範例四:承範例三,將錯誤的數據丟棄,屏幕上顯示正確的數據 [dmtsai@www ~]$ find /home -name .bashrc 2> /dev/null /home/dmtsai/.bashrc <==只有 stdout 會顯示到屏幕上, stderr 被丟棄了 |
再想象一下,若是我要將正確與錯誤數據統統寫入同一個文件去呢?這個時候就得要使用特殊的寫法了! 咱們一樣用底下的案例來講明:
範例五:將命令的數據所有寫入名爲 list 的文件中 [dmtsai@www ~]$ find /home -name .bashrc > list 2> list <==錯誤 [dmtsai@www ~]$ find /home -name .bashrc > list 2>&1 <==正確 [dmtsai@www ~]$ find /home -name .bashrc &> list <==正確 |
上述表格第一行錯誤的緣由是,因爲兩股數據同時寫入一個文件,又沒有使用特殊的語法, 此時兩股數據可能會交叉寫入該文件內,形成次序的錯亂。因此雖然最終 list 文件仍是會產生,可是裏面的數據排列就會怪怪的,而不是本來屏幕上的輸出排序。 至於寫入同一個文件的特殊語法如上表所示,你能夠使用 2>&1 也能夠使用 &> ! 通常來講,鳥哥比較習慣使用 2>&1 的語法啦!
瞭解了 stderr 與 stdout 後,那麼那個 < 又是什麼呀?呵呵!以最簡單的說法來講, 那就是『將本來須要由鍵盤輸入的數據,改由文件內容來取代』的意思。 咱們先由底下的 cat 命令操做來了解一下什麼叫作『鍵盤輸入』吧!
範例六:利用 cat 命令來建立一個文件的簡單流程 [root@www ~]# cat > catfile testing cat file test <==這裏按下 [ctrl]+d 來離開 [root@www ~]# cat catfile testing cat file test |
因爲加入 > 在 cat 後,因此那個 catfile 會被主動的建立,而內容就是剛剛鍵盤上面輸入的那兩行數據了。 唔!那我能不能用純文本文件取代鍵盤的輸入,也就是說,用某個文件的內容來取代鍵盤的敲擊呢? 能夠的!以下所示:
範例七:用 stdin 取代鍵盤的輸入以建立新文件的簡單流程 [root@www ~]# cat > catfile < ~/.bashrc [root@www ~]# ll catfile ~/.bashrc -rw-r--r-- 1 root root 194 Sep 26 13:36 /root/.bashrc -rw-r--r-- 1 root root 194 Feb 6 18:29 catfile # 注意看,這兩個文件的大小會如出一轍!幾乎像是使用 cp 來複制通常! |
這東西很是的有幫助!尤爲是用在相似 mail 這種命令的使用上。 理解 < 以後,再來則是怪可怕一把的 << 這個連續兩個小於的符號了。 他表明的是『結束的輸入字符』的意思!舉例來說:『我要用 cat 直接將輸入的信息輸出到 catfile 中, 且當由鍵盤輸入 eof 時,該次輸入就結束』,那我能夠這樣作:
[root@www ~]# cat > catfile << "eof" > This is a test. > OK now stop > eof <==輸入這關鍵詞,馬上就結束而不須要輸入 [ctrl]+d [root@www ~]# cat catfile This is a test. OK now stop <==只有這兩行,不會存在關鍵詞那一行! |
看到了嗎?利用 << 右側的控制字符,咱們能夠終止一次輸入, 而沒必要輸入 [crtl]+d 來結束哩!這對程序寫做頗有幫助喔!好了,那麼爲什麼要使用命令輸出重導向呢?咱們來講一說吧!
固然還有不少的功能的,最簡單的就是網友們經常問到的:『爲什麼個人 root 都會收到系統 crontab 寄來的錯誤信息呢』這個咚咚是常見的錯誤, 而若是咱們已經知道這個錯誤信息是能夠忽略的時候,嗯!『 2> errorfile 』這個功能就很重要了吧! 瞭解了嗎?
在某些狀況下,不少命令我想要一次輸入去運行,而不想要分次運行時,該如何是好?基本上你有兩個選擇, 一個是透過第十三章要介紹的 shell script 撰寫腳本去運行,一種則是透過底下的介紹來一次輸入多重命令喔!
在某些時候,咱們但願能夠一次運行多個命令,例如在關機的時候我但願能夠先運行兩次 sync 同步化寫入磁盤後才 shutdown 計算機,那麼能夠怎麼做呢?這樣作呀:
[root@www ~]# sync; sync; shutdown -h now
|
在命令與命令中間利用分號 (;) 來隔開,這樣一來,分號前的命令運行完後就會馬上接着運行後面的命令了。 這真是方便啊~再來,換個角度來想,萬一我想要在某個目錄底下建立一個文件,也就是說,若是該目錄存在的話, 那我才建立這個文件,若是不存在,那就算了。也就是說這兩個命令彼此之間是有相關性的, 前一個命令是否成功的運行與後一個命令是否要運行有關!那就得動用到 && 或 || 囉!
如同上面談到的,兩個命令之間有相依性,而這個相依性主要判斷的地方就在於前一個命令運行的結果是否正確。 還記得本章以前咱們曾介紹過命令回傳值吧!嘿嘿!沒錯,您真聰明!就是透過這個回傳值啦! 再複習一次『若前一個命令運行的結果爲正確,在 Linux 底下會回傳一個 $? = 0 的值』。 那麼咱們怎麼透過這個回傳值來判斷後續的命令是否要運行呢?這就得要藉由『 && 』及『 || 』的幫忙了! 注意喔,兩個 & 之間是沒有空格的!那個 | 則是 [Shift]+[\] 的按鍵結果。
命令下達狀況 | 說明 |
cmd1 && cmd2 | 1. 若 cmd1 運行完畢且正確運行($?=0),則開始運行 cmd2。 2. 若 cmd1 運行完畢且爲錯誤 ($?≠0),則 cmd2 不運行。 |
cmd1 || cmd2 | 1. 若 cmd1 運行完畢且正確運行($?=0),則 cmd2 不運行。 2. 若 cmd1 運行完畢且爲錯誤 ($?≠0),則開始運行 cmd2。 |
上述的 cmd1 及 cmd2 都是命令。好了,回到咱們剛剛假想的狀況,就是想要: (1)先判斷一個目錄是否存在; (2)若存在纔在該目錄底下建立一個文件。因爲咱們還沒有介紹如何判斷式 (test) 的使用,在這裏咱們使用 ls 以及回傳值來判斷目錄是否存在啦! 讓咱們進行底下這個練習看看:
範例一:使用 ls 查閱目錄 /tmp/abc 是否存在,若存在則用 touch 建立 /tmp/abc/hehe [root@www ~]# ls /tmp/abc && touch /tmp/abc/hehe ls: /tmp/abc: No such file or directory # ls 很乾脆的說明找不到該目錄,但並無 touch 的錯誤,表示 touch 並無運行 [root@www ~]# mkdir /tmp/abc [root@www ~]# ls /tmp/abc && touch /tmp/abc/hehe [root@www ~]# ll /tmp/abc -rw-r--r-- 1 root root 0 Feb 7 12:43 hehe |
看到了吧?若是 /tmp/abc 不存在時,touch 就不會被運行,若 /tmp/abc 存在的話,那麼 touch 就會開始運行囉! 很不錯用吧!不過,咱們還得手動自行建立目錄,傷腦筋~能不能自動判斷,若是沒有該目錄就給予建立呢? 參考一下底下的例子先:
範例二:測試 /tmp/abc 是否存在,若不存在則予以建立,若存在就不做任何事情 [root@www ~]# rm -r /tmp/abc <==先刪除此目錄以方便測試 [root@www ~]# ls /tmp/abc || mkdir /tmp/abc ls: /tmp/abc: No such file or directory <==真的不存在喔! [root@www ~]# ll /tmp/abc total 0 <==結果出現了!有進行 mkdir |
若是你一再重複『 ls /tmp/abc || mkdir /tmp/abc 』畫面也不會出現重複 mkdir 的錯誤!這是由於 /tmp/abc 已經存在, 因此後續的 mkdir 就不會進行!這樣理解否?好了,讓咱們再次的討論一下,若是我想要建立 /tmp/abc/hehe 這個文件, 但我並不知道 /tmp/abc 是否存在,那該如何是好?試看看:
範例三:我不清楚 /tmp/abc 是否存在,但就是要建立 /tmp/abc/hehe 文件 [root@www ~]# ls /tmp/abc || mkdir /tmp/abc && touch /tmp/abc/hehe |
上面這個範例三老是會建立 /tmp/abc/hehe 的喔!不論 /tmp/abc 是否存在。那麼範例三應該如何解釋呢? 因爲Linux 底下的命令都是由左往右運行的,因此範例三有幾種結果咱們來分析一下:
整個流程圖示以下:
上面這張圖顯示的兩股數據中,上方的線段爲不存在 /tmp/abc 時所進行的命令行爲,下方的線段則是存在 /tmp/abc 所在的命令行爲。如上所述,下方線段因爲存在 /tmp/abc 因此致使 $?=0 ,讓中間的 mkdir 就不運行了! 並將 $?=0 繼續日後傳給後續的 touch 去利用啦!瞭乎?在任什麼時候刻你均可以拿上面這張圖做爲示意! 讓咱們來想一想底下這個例題吧!
例題:
以 ls 測試 /tmp/vbirding 是否存在,若存在則顯示 "exist" ,若不存在,則顯示 "not exist"!
答:
這又牽涉到邏輯判斷的問題,若是存在就顯示某個數據,若不存在就顯示其餘數據,那我能夠這樣作:
ls /tmp/vbirding && echo "exist" || echo "not exist"意思是說,當 ls /tmp/vbirding 運行後,若正確,就運行 echo "exist" ,如有問題,就運行 echo "not exist" !那若是寫成以下的情況會出現什麼? ls /tmp/vbirding || echo "not exist" && echo "exist"這實際上是有問題的,爲何呢?由圖 5.2.1 的流程介紹咱們知道命令是一個一個日後運行, 所以在上面的例子當中,若是 /tmp/vbirding 不存在時,他會進行以下動做:
|
通過這個例題的練習,你應該會了解,因爲命令是一個接着一個去運行的,所以,若是真要使用判斷, 那麼這個 && 與 || 的順序就不能搞錯。通常來講,假設判斷式有三個,也就是:
command1 && command2 || command3
並且順序一般不會變,由於通常來講, command2 與 command3 會放置確定能夠運行成功的命令, 所以,依據上面例題的邏輯分析,您就會曉得爲什麼要如此放置囉~這頗有用的啦!並且.....考試也很常考~
就如同前面所說的, bash 命令運行的時候有輸出的數據會出現! 那麼若是這羣數據必須要通過幾道手續以後才能獲得咱們所想要的格式,應該如何來配置? 這就牽涉到管線命令的問題了 (pipe) ,管線命令使用的是『 | 』這個界定符號! 另外,管線命令與『連續下達命令』是不同的呦! 這點底下咱們會再說明。底下咱們先舉一個例子來講明一下簡單的管線命令。
假設咱們想要知道 /etc/ 底下有多少文件,那麼能夠利用 ls /etc 來查閱,不過, 由於 /etc 底下的文件太多,致使一口氣就將屏幕塞滿了~不知道前面輸出的內容是啥?此時,咱們能夠透過 less 命令的協助,利用:
[root@www ~]# ls -al /etc | less
|
如此一來,使用 ls 命令輸出後的內容,就可以被 less 讀取,而且利用 less 的功能,咱們就可以先後翻動相關的信息了!很方即是吧?咱們就來了解一下這個管線命令『 | 』的用途吧! 其實這個管線命令『 | 』僅能處理經由前面一個命令傳來的正確信息,也就是 standard output 的信息,對於 stdandard error 並無直接處理的能力。那麼總體的管線命令能夠使用下圖表示:
在每一個管線後面接的第一個數據一定是『命令』喔!並且這個命令必需要可以接受 standard input 的數據才行,這樣的命令才能夠是爲『管線命令』,例如 less, more, head, tail 等都是能夠接受 standard input 的管線命令啦。至於例如 ls, cp, mv 等就不是管線命令了!由於 ls, cp, mv 並不會接受來自 stdin 的數據。 也就是說,管線命令主要有兩個比較須要注意的地方:
多說無益,讓咱們來玩一些管線命令吧!底下的咚咚對系統管理很是有幫助喔!
什麼是擷取命令啊?說穿了,就是將一段數據通過分析後,取出咱們所想要的。或者是經由分析關鍵詞,取得咱們所想要的那一行! 不過,要注意的是,通常來講,擷取信息一般是針對『一行一行』來分析的, 並非整篇信息分析的喔~底下咱們介紹兩個很經常使用的信息擷取命令:
cut 不就是『切』嗎?沒錯啦!這個命令能夠將一段信息的某一段給他『切』出來~ 處理的信息是以『行』爲單位喔!底下咱們就來談一談:
cut 主要的用途在於將『同一行裏面的數據進行分解!』最常使用在分析一些數據或文字數據的時候! 這是由於有時候咱們會以某些字符看成分割的參數,而後來將數據加以切割,以取得咱們所須要的數據。 鳥哥也很常使用這個功能呢!尤爲是在分析 log 文件的時候!不過,cut 在處理多空格相連的數據時,可能會比較吃力一點。
剛剛的 cut 是將一行信息當中,取出某部分咱們想要的,而 grep 則是分析一行信息, 若當中有咱們所須要的信息,就將該行拿出來~簡單的語法是這樣的:
[root@www ~]# grep [-acinv] [--color=auto] '搜尋字符串' filename 選項與參數: -a :將 binary 文件以 text 文件的方式搜尋數據 -c :計算找到 '搜尋字符串' 的次數 -i :忽略大小寫的不一樣,因此大小寫視爲相同 -n :順便輸出行號 -v :反向選擇,亦即顯示出沒有 '搜尋字符串' 內容的那一行! --color=auto :能夠將找到的關鍵詞部分加上顏色的顯示喔! 範例一:將 last 當中,有出現 root 的那一行就取出來; [root@www ~]# last | grep 'root' 範例二:與範例一相反,只要沒有 root 的就取出! [root@www ~]# last | grep -v 'root' 範例三:在 last 的輸出信息中,只要有 root 就取出,而且僅取第一欄 [root@www ~]# last | grep 'root' |cut -d ' ' -f1 # 在取出 root 以後,利用上個命令 cut 的處理,就可以僅取得第一欄囉! 範例四:取出 /etc/man.config 內含 MANPATH 的那幾行 [root@www ~]# grep --color=auto 'MANPATH' /etc/man.config ....(前面省略).... MANPATH_MAP /usr/X11R6/bin /usr/X11R6/man MANPATH_MAP /usr/bin/X11 /usr/X11R6/man MANPATH_MAP /usr/bin/mh /usr/share/man # 神奇的是,若是加上 --color=auto 的選項,找到的關鍵詞部分會用特殊顏色顯示喔! |
grep 是個很棒的命令喔!他支持的語法實在是太多了~用在正規表示法裏頭, 可以處理的數據實在是多的很~不過,咱們這裏先不談正規表示法~下一章再來講明~ 您先了解一下, grep 能夠解析一行文字,取得關鍵詞,若該行有存在關鍵詞,就會整行列出來!
不少時候,咱們都會去計算一次數據裏頭的相同型態的數據總數,舉例來講, 使用 last 能夠查得這個月份有登錄主機者的身份。那麼我能夠針對每一個使用者查出他們的總登錄次數嗎? 此時就得要排序與計算之類的命令來輔助了!底下咱們介紹幾個好用的排序與統計命令喔!
sort 是頗有趣的命令,他能夠幫咱們進行排序,並且能夠依據不一樣的數據型態來排序喔! 例如數字與文字的排序就不同。此外,排序的字符與語系的編碼有關,所以, 若是您須要排序時,建議使用 LANG=C 來讓語系統一,數據排序比較好一些。
[root@www ~]# sort [-fbMnrtuk] [file or stdin] 選項與參數: -f :忽略大小寫的差別,例如 A 與 a 視爲編碼相同; -b :忽略最前面的空格符部分; -M :以月份的名字來排序,例如 JAN, DEC 等等的排序方法; -n :使用『純數字』進行排序(默認是以文字型態來排序的); -r :反向排序; -u :就是 uniq ,相同的數據中,僅出現一行表明; -t :分隔符,默認是用 [tab] 鍵來分隔; -k :以那個區間 (field) 來進行排序的意思 範例一:我的帳號都記錄在 /etc/passwd 下,請將帳號進行排序。 [root@www ~]# cat /etc/passwd | sort adm:x:3:4:adm:/var/adm:/sbin/nologin apache:x:48:48:Apache:/var/www:/sbin/nologin bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin # 鳥哥省略不少的輸出~由上面的數據看起來, sort 是默認『以第一個』數據來排序, # 並且默認是以『文字』型態來排序的喔!因此由 a 開始排到最後囉! 範例二:/etc/passwd 內容是以 : 來分隔的,我想以第三欄來排序,該如何? [root@www ~]# cat /etc/passwd | sort -t ':' -k 3 root:x:0:0:root:/root:/bin/bash uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin operator:x:11:0:operator:/root:/sbin/nologin bin:x:1:1:bin:/bin:/sbin/nologin games:x:12:100:games:/usr/games:/sbin/nologin # 看到特殊字體的輸出部分了吧?怎麼會這樣排列啊?呵呵!沒錯啦~ # 若是是以文字型態來排序的話,本來就會是這樣,想要使用數字排序: # cat /etc/passwd | sort -t ':' -k 3 -n # 這樣才行啊!用那個 -n 來告知 sort 以數字來排序啊! 範例三:利用 last ,將輸出的數據僅取帳號,並加以排序 [root@www ~]# last | cut -d ' ' -f1 | sort |
sort 一樣是很經常使用的命令呢!由於咱們經常須要比較一些信息啦! 舉個上面的第二個例子來講好了!今天假設你有不少的帳號,並且你想要知道最大的使用者 ID 目前到哪一號了!呵呵!使用 sort 一會兒就能夠知道答案咯!固然其使用還不止此啦! 有空的話不妨玩一玩!
若是我排序完成了,想要將重複的數據僅列出一個顯示,能夠怎麼作呢?
[root@www ~]# uniq [-ic] 選項與參數: -i :忽略大小寫字符的不一樣; -c :進行計數 範例一:使用 last 將帳號列出,僅取出帳號欄,進行排序後僅取出一位; [root@www ~]# last | cut -d ' ' -f1 | sort | uniq 範例二:承上題,若是我還想要知道每一個人的登錄總次數呢? [root@www ~]# last | cut -d ' ' -f1 | sort | uniq -c 1 12 reboot 41 root 1 wtmp # 從上面的結果能夠發現 reboot 有 12 次, root 登錄則有 41 次! # wtmp 與第一行的空白都是 last 的默認字符,那兩個能夠忽略的! |
這個命令用來將『重複的行刪除掉只顯示一個』,舉個例子來講, 你要知道這個月份登錄你主機的用戶有誰,而不在意他的登錄次數,那麼就使用上面的範例, (1)先將全部的數據列出;(2)再將人名獨立出來;(3)通過排序;(4)只顯示一個! 因爲這個命令是在將重複的東西減小,因此固然須要『配合排序過的文件』來處理囉!
若是我想要知道 /etc/man.config 這個文件裏面有多少字?多少行?多少字符的話, 能夠怎麼作呢?其實能夠利用 wc 這個命令來達成喔!他能夠幫咱們計算輸出的信息的總體數據!
[root@www ~]# wc [-lwm] 選項與參數: -l :僅列出行; -w :僅列出多少字(英文單字); -m :多少字符; 範例一:那個 /etc/man.config 裏面到底有多少相關字、行、字符數? [root@www ~]# cat /etc/man.config | wc 141 722 4617 # 輸出的三個數字中,分別表明: 『行、字數、字符數』 範例二:我知道使用 last 能夠輸出登錄者,可是 last 最後兩行並不是帳號內容, 那麼請問,我該如何以一行命令串取得這個月份登錄系統的總人次? [root@www ~]# last | grep [a-zA-Z] | grep -v 'wtmp' | wc -l # 因爲 last 會輸出空白行與 wtmp 字樣在最底下兩行,所以,我利用 # grep 取出非空白行,以及去除 wtmp 那一行,在計算行數,就可以瞭解囉! |
wc 也能夠看成命令?這可不是上洗手間的 WC 呢!這是至關有用的計算文件內容的一個工具組喔!舉個例子來講, 當你要知道目前你的帳號文件中有多少個帳號時,就使用這個方法:『 cat /etc/passwd | wc -l 』啦!由於 /etc/passwd 裏頭一行表明一個使用者呀! 因此知道行數就曉得有多少的帳號在裏頭了!而若是要計算一個文件裏頭有多少個字符時,就使用 wc -m 這個選項吧!
想個簡單的東西,咱們由前一節知道 > 會將數據流整個傳送給文件或裝置,所以咱們除非去讀取該文件或裝置, 不然就沒法繼續利用這個數據流。萬一我想要將這個數據流的處理過程當中將某段信息存下來,應該怎麼作? 利用 tee 就能夠囉~咱們能夠這樣簡單的看一下:
tee 會同時將數據流分送到文件去與屏幕 (screen);而輸出到屏幕的,其實就是 stdout ,可讓下個命令繼續處理喔!
[root@www ~]# tee [-a] file 選項與參數: -a :以累加 (append) 的方式,將數據加入 file 當中! [root@www ~]# last | tee last.list | cut -d " " -f1 # 這個範例可讓咱們將 last 的輸出存一份到 last.list 文件中; [root@www ~]# ls -l /home | tee ~/homefile | more # 這個範例則是將 ls 的數據存一份到 ~/homefile ,同時屏幕也有輸出信息! [root@www ~]# ls -l / | tee -a ~/homefile | more # 要注意! tee 後接的文件會被覆蓋,若加上 -a 這個選項則能將信息累加。 |
tee 可讓 standard output 轉存一份到文件內並將一樣的數據繼續送到屏幕去處理! 這樣除了可讓咱們同時分析一份數據並記錄下來以外,還能夠做爲處理一份數據的中間緩存盤記錄之用! tee 這傢伙在不少選擇/填充的認證考試中很容易考呢!
咱們在 vim 程序編輯器當中,提到過 DOS 斷行字符與 Unix 斷行字符的不一樣,而且能夠使用 dos2unix 與 unix2dos 來完成轉換。好了,那麼思考一下,是否還有其餘經常使用的字符替代? 舉例來講,要將大寫改爲小寫,或者是將數據中的 [tab] 按鍵轉成空格鍵?還有,如何將兩篇信息整合成一篇? 底下咱們就來介紹一下這些字符轉換命令在管線當中的使用方法:
tr 能夠用來刪除一段信息當中的文字,或者是進行文字信息的替換!
[root@www ~]# tr [-ds] SET1 ... 選項與參數: -d :刪除信息當中的 SET1 這個字符串; -s :取代掉重複的字符! 範例一:將 last 輸出的信息中,全部的小寫變成大寫字符: [root@www ~]# last | tr '[a-z]' '[A-Z]' # 事實上,沒有加上單引號也是能夠運行的,如:『 last | tr [a-z] [A-Z] 』 範例二:將 /etc/passwd 輸出的信息中,將冒號 (:) 刪除 [root@www ~]# cat /etc/passwd | tr -d ':' 範例三:將 /etc/passwd 轉存成 dos 斷行到 /root/passwd 中,再將 ^M 符號刪除 [root@www ~]# cp /etc/passwd /root/passwd && unix2dos /root/passwd [root@www ~]# file /etc/passwd /root/passwd /etc/passwd: ASCII text /root/passwd: ASCII text, with CRLF line terminators <==就是 DOS 斷行 [root@www ~]# cat /root/passwd | tr -d '\r' > /root/passwd.linux # 那個 \r 指的是 DOS 的斷行字符,關於更多的字符,請參考 man tr [root@www ~]# ll /etc/passwd /root/passwd* -rw-r--r-- 1 root root 1986 Feb 6 17:55 /etc/passwd -rw-r--r-- 1 root root 2030 Feb 7 15:55 /root/passwd -rw-r--r-- 1 root root 1986 Feb 7 15:57 /root/passwd.linux # 處理事後,發現文件大小與本來的 /etc/passwd 就一致了! |
其實這個命令也能夠寫在『正規表示法』裏頭!由於他也是由正規表示法的方式來取代數據的! 以上面的例子來講,使用 [] 能夠配置一串字呢!也經常用來取代文件中的怪異符號! 例如上面第三個例子當中,能夠去除 DOS 文件留下來的 ^M 這個斷行的符號!這東西至關的有用!相信處理 Linux & Windows 系統中的人們最麻煩的一件事就是這個事情啦!亦便是 DOS 底下會自動的在每行行尾加入 ^M 這個斷行符號!這個時候咱們能夠使用這個 tr 來將 ^M 去除! ^M 能夠使用 \r 來代替之!
[root@www ~]# col [-xb] 選項與參數: -x :將 tab 鍵轉換成對等的空格鍵 -b :在文字內有反斜槓 (/) 時,僅保留反斜槓最後接的那個字符 範例一:利用 cat -A 顯示出全部特殊按鍵,最後以 col 將 [tab] 轉成空白 [root@www ~]# cat -A /etc/man.config <==此時會看到不少 ^I 的符號,那就是 tab [root@www ~]# cat /etc/man.config | col -x | cat -A | more # 嘿嘿!如此一來, [tab] 按鍵會被取代成爲空格鍵,輸出就美觀多了! 範例二:將 col 的 man page 轉存成爲 /root/col.man 的純文本檔 [root@www ~]# man col > /root/col.man [root@www ~]# vi /root/col.man COL(1) BSD General Commands Manual COL(1) N^HNA^HAM^HME^HE c^Hco^Hol^Hl - filter reverse line feeds from input S^HSY^HYN^HNO^HOP^HPS^HSI^HIS^HS c^Hco^Hol^Hl [-^H-b^Hbf^Hfp^Hpx^Hx] [-^H-l^Hl _^Hn_^Hu_^Hm] # 你沒看錯!因爲 man page 內有些特殊按鈕會用來做爲相似特殊按鍵與顏色顯示, # 因此這個文件內就會出現如上所示的一堆怪異字符(有 ^ 的) [root@www ~]# man col | col -b > /root/col.man |
雖然 col 有他特殊的用途,不過,不少時候,他能夠用來簡單的處理將 [tab] 按鍵取代成爲空格鍵! 例如上面的例子當中,若是使用 cat -A 則 [tab] 會以 ^I 來表示。 但通過 col -x 的處理,則會將 [tab] 取代成爲對等的空格鍵!此外, col 常常被利用於將 man page 轉存爲純文本文件以方便查閱的功能!如上述的範例二!
join 看字面上的意義 (加入/參加) 就能夠知道,他是在處理兩個文件之間的數據, 並且,主要是在處理『兩個文件當中,有 "相同數據" 的那一行,纔將他加在一塊兒』的意思。咱們利用底下的簡單例子來講明:
[root@www ~]# join [-ti12] file1 file2 選項與參數: -t :join 默認以空格符分隔數據,而且比對『第一個字段』的數據, 若是兩個文件相同,則將兩筆數據聯成一行,且第一個字段放在第一個! -i :忽略大小寫的差別; -1 :這個是數字的 1 ,表明『第一個文件要用那個字段來分析』的意思; -2 :表明『第二個文件要用那個字段來分析』的意思。 範例一:用 root 的身份,將 /etc/passwd 與 /etc/shadow 相關數據整合成一欄 [root@www ~]# head -n 3 /etc/passwd /etc/shadow ==> /etc/passwd <== root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin ==> /etc/shadow <== root:$1$/3AQpE5e$y9A/D0bh6rElAs:14120:0:99999:7::: bin:*:14126:0:99999:7::: daemon:*:14126:0:99999:7::: # 由輸出的數據能夠發現這兩個文件的最左邊字段都是帳號!且以 : 分隔 [root@www ~]# join -t ':' /etc/passwd /etc/shadow root:x:0:0:root:/root:/bin/bash:$1$/3AQpE5e$y9A/D0bh6rElAs:14120:0:99999:7::: bin:x:1:1:bin:/bin:/sbin/nologin:*:14126:0:99999:7::: daemon:x:2:2:daemon:/sbin:/sbin/nologin:*:14126:0:99999:7::: # 透過上面這個動做,咱們能夠將兩個文件第一字段相同者整合成一行! # 第二個文件的相同字段並不會顯示(由於已經在第一行了嘛!) 範例二:咱們知道 /etc/passwd 第四個字段是 GID ,那個 GID 記錄在 /etc/group 當中的第三個字段,請問如何將兩個文件整合? [root@www ~]# head -n 3 /etc/passwd /etc/group ==> /etc/passwd <== root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin ==> /etc/group <== root:x:0:root bin:x:1:root,bin,daemon daemon:x:2:root,bin,daemon # 從上面能夠看到,確實有相同的部分喔!趕忙來整合一下! [root@www ~]# join -t ':' -1 4 /etc/passwd -2 3 /etc/group 0:root:x:0:root:/root:/bin/bash:root:x:root 1:bin:x:1:bin:/bin:/sbin/nologin:bin:x:root,bin,daemon 2:daemon:x:2:daemon:/sbin:/sbin/nologin:daemon:x:root,bin,daemon # 一樣的,相同的字段部分被移動到最前面了!因此第二個文件的內容就沒再顯示。 # 請讀者們配合上述顯示兩個文件的實際內容來比對! |
這個 join 在處理兩個相關的數據文件時,就真的是頗有幫助的啦! 例如上面的案例當中,個人 /etc/passwd, /etc/shadow, /etc/group 都是有相關性的, 其中 /etc/passwd, /etc/shadow 以帳號爲相關性,至於 /etc/passwd, /etc/group 則以所謂的 GID (帳號的數字定義) 來做爲他的相關性。根據這個相關性, 咱們能夠將有關係的數據放置在一塊兒!這在處理數據但是至關有幫助的! 可是上面的例子有點難,但願您能夠靜下心好好的看一看緣由喔!
此外,須要特別注意的是,在使用 join 以前,你所須要處理的文件應該要事先通過排序 (sort) 處理! 不然有些比對的項目會被略過呢!特別注意了!
這個 paste 就要比 join 簡單多了!相對於 join 必需要比對兩個文件的數據相關性, paste 就直接『將兩行貼在一塊兒,且中間以 [tab] 鍵隔開』而已!簡單的使用方法:
[root@www ~]# paste [-d] file1 file2 選項與參數: -d :後面能夠接分隔字符。默認是以 [tab] 來分隔的! - :若是 file 部分寫成 - ,表示來自 standard input 的數據的意思。 範例一:將 /etc/passwd 與 /etc/shadow 同一行貼在一塊兒 [root@www ~]# paste /etc/passwd /etc/shadow bin:x:1:1:bin:/bin:/sbin/nologin bin:*:14126:0:99999:7::: daemon:x:2:2:daemon:/sbin:/sbin/nologin daemon:*:14126:0:99999:7::: adm:x:3:4:adm:/var/adm:/sbin/nologin adm:*:14126:0:99999:7::: # 注意喔!同一行中間是以 [tab] 按鍵隔開的! 範例二:先將 /etc/group 讀出(用 cat),而後與範例一貼上一塊兒!且僅取出前三行 [root@www ~]# cat /etc/group|paste /etc/passwd /etc/shadow -|head -n 3 # 這個例子的重點在那個 - 的使用!那玩意兒經常表明 stdin 喔! |
這玩意兒就是在將 [tab] 按鍵轉成空格鍵啦~能夠這樣玩:
[root@www ~]# expand [-t] file 選項與參數: -t :後面能夠接數字。通常來講,一個 tab 按鍵能夠用 8 個空格鍵取代。 咱們也能夠自行定義一個 [tab] 按鍵表明多少個字符呢! 範例一:將 /etc/man.config 內行首爲 MANPATH 的字樣就取出;僅取前三行; [root@www ~]# grep '^MANPATH' /etc/man.config | head -n 3 MANPATH /usr/man MANPATH /usr/share/man MANPATH /usr/local/man # 行首的表明標誌爲 ^ ,這個咱們留待下節介紹!先有概念便可! 範例二:承上,若是我想要將全部的符號都列出來?(用 cat) [root@www ~]# grep '^MANPATH' /etc/man.config | head -n 3 |cat -A MANPATH^I/usr/man$ MANPATH^I/usr/share/man$ MANPATH^I/usr/local/man$ # 發現差異了嗎?沒錯~ [tab] 按鍵能夠被 cat -A 顯示成爲 ^I 範例三:承上,我將 [tab] 按鍵配置成 6 個字符的話? [root@www ~]# grep '^MANPATH' /etc/man.config | head -n 3 | \ > expand -t 6 - | cat -A MANPATH /usr/man$ MANPATH /usr/share/man$ MANPATH /usr/local/man$ 123456123456123456..... # 仔細看一下上面的數字說明,由於我是以 6 個字符來表明一個 [tab] 的長度,因此, # MAN... 到 /usr 之間會隔 12 (兩個 [tab]) 個字符喔!若是 tab 改爲 9 的話, # 狀況就又不一樣了!這裏也很差理解~您能夠多配置幾個數字來查閱就曉得! |
expand 也是挺好玩的~他會自動將 [tab] 轉成空格鍵~因此,以上面的例子來講, 使用 cat -A 就會查不到 ^I 的字符囉~此外,由於 [tab] 最大的功能就是格式排列整齊! 咱們轉成空格鍵後,這個空格鍵也會依據咱們本身的定義來添加大小~ 因此,並非一個 ^I 就會換成 8 個空白喔!這個地方要特別注意的哩! 此外,您也能夠參考一下 unexpand 這個將空白轉成 [tab] 的命令功能啊! ^_^
若是你有文件太大,致使一些攜帶式裝置沒法複製的問題,嘿嘿!找 split 就對了! 他能夠幫你將一個大文件,依據文件大小或行數來分割,就能夠將大文件分割成爲小文件了! 快速又有效啊!真不錯~
[root@www ~]# split [-bl] file PREFIX 選項與參數: -b :後面可接欲分割成的文件大小,可加單位,例如 b, k, m 等; -l :以行數來進行分割。 PREFIX :表明前導符的意思,可做爲分割文件的前導文字。 範例一:個人 /etc/termcap 有七百多K,若想要分紅 300K 一個文件時? [root@www ~]# cd /tmp; split -b 300k /etc/termcap termcap [root@www tmp]# ll -k termcap* -rw-r--r-- 1 root root 300 Feb 7 16:39 termcapaa -rw-r--r-- 1 root root 300 Feb 7 16:39 termcapab -rw-r--r-- 1 root root 189 Feb 7 16:39 termcapac # 那個檔名能夠隨意取的啦!咱們只要寫上前導文字,小文件就會以 # xxxaa, xxxab, xxxac 等方式來建立小文件的! 範例二:如何將上面的三個小文件合成一個文件,檔名爲 termcapback [root@www tmp]# cat termcap* >> termcapback # 很簡單吧?就用數據流重導向就好啦!簡單! 範例三:使用 ls -al / 輸出的信息中,每十行記錄成一個文件 [root@www tmp]# ls -al / | split -l 10 - lsroot [root@www tmp]# wc -l lsroot* 10 lsrootaa 10 lsrootab 6 lsrootac 26 total # 重點在那個 - 啦!通常來講,若是須要 stdout/stdin 時,但恰恰又沒有文件, # 有的只是 - 時,那麼那個 - 就會被當成 stdin 或 stdout ~ |
在 Windows 操做系統下,你要將文件分割須要如何做?傷腦筋吧!在 Linux 底下就簡單的多了!你要將文件分割的話,那麼就使用 -b size 來將一個分割的文件限制其大小,若是是行數的話,那麼就使用 -l line 來分割!好用的很!如此一來,你就能夠輕易的將你的文件分割成軟盤 (floppy) 的大小,方便你 copy 囉!
xargs 是在作什麼的呢?就以字面上的意義來看, x 是加減乘除的乘號,args 則是 arguments (參數) 的意思,因此說,這個玩意兒就是在產生某個命令的參數的意思! xargs 能夠讀入 stdin 的數據,而且以空格符或斷行字符做爲分辨,將 stdin 的數據分隔成爲 arguments 。 由於是以空格符做爲分隔,因此,若是有一些檔名或者是其餘意義的名詞內含有空格符的時候, xargs 可能就會誤判了~他的用法其實也還滿簡單的!就來看一看先!
[root@www ~]# xargs [-0epn] command 選項與參數: -0 :若是輸入的 stdin 含有特殊字符,例如 `, \, 空格鍵等等字符時,這個 -0 參數 能夠將他還原成通常字符。這個參數能夠用於特殊狀態喔! -e :這個是 EOF (end of file) 的意思。後面能夠接一個字符串,當 xargs 分析到 這個字符串時,就會中止繼續工做! -p :在運行每一個命令的 argument 時,都會詢問使用者的意思; -n :後面接次數,每次 command 命令運行時,要使用幾個參數的意思。看範例三。 當 xargs 後面沒有接任何的命令時,默認是以 echo 來進行輸出喔! 範例一:將 /etc/passwd 內的第一欄取出,僅取三行,使用 finger 這個命令將每一個 帳號內容秀出來 [root@www ~]# cut -d':' -f1 /etc/passwd |head -n 3| xargs finger Login: root Name: root Directory: /root Shell: /bin/bash Never logged in. No mail. No Plan. ......底下省略..... # 由 finger account 能夠取得該帳號的相關說明內容,例如上面的輸出就是 finger root # 後的結果。在這個例子當中,咱們利用 cut 取出帳號名稱,用 head 取出三個帳號, # 最後則是由 xargs 將三個帳號的名稱變成 finger 後面須要的參數! 範例二:同上,可是每次運行 finger 時,都要詢問使用者是否動做? [root@www ~]# cut -d':' -f1 /etc/passwd |head -n 3| xargs -p finger finger root bin daemon ?...y .....(底下省略).... # 呵呵!這個 -p 的選項可讓用戶的使用過程當中,被詢問到每一個命令是否運行! 範例三:將全部的 /etc/passwd 內的帳號都以 finger 查閱,但一次僅查閱五個帳號 [root@www ~]# cut -d':' -f1 /etc/passwd | xargs -p -n 5 finger finger root bin daemon adm lp ?...y .....(中間省略).... finger uucp operator games gopher ftp ?...y .....(底下省略).... # 在這裏鳥哥使用了 -p 這個參數來讓您對於 -n 更有概念。通常來講,某些命令後面 # 能夠接的 arguments 是有限制的,不能無限制的累加,此時,咱們能夠利用 -n # 來幫助咱們將參數分紅數個部分,每一個部分分別再以命令來運行!這樣就 OK 啦!^_^ 範例四:同上,可是當分析到 lp 就結束這串命令? [root@www ~]# cut -d':' -f1 /etc/passwd | xargs -p -e'lp' finger finger root bin daemon adm ?... # 仔細與上面的案例作比較。也同時注意,那個 -e'lp' 是連在一塊兒的,中間沒有空格鍵。 # 上個例子當中,第五個參數是 lp 啊,那麼咱們下達 -e'lp' 後,則分析到 lp # 這個字符串時,後面的其餘 stdin 的內容就會被 xargs 捨棄掉了! |
其實,在 man xargs 裏面就有三四個小范例,您能夠自行參考一下內容。 此外, xargs 真的是很好用的一個玩意兒!您真的須要好好的參詳參詳!會使用 xargs 的緣由是, 不少命令其實並不支持管線命令,所以咱們能夠透過 xargs 來提供該命令引用 standard input 之用!舉例來講,咱們使用以下的範例來講明:
範例五:找出 /sbin 底下具備特殊權限的檔名,並使用 ls -l 列出詳細屬性 [root@www ~]# find /sbin -perm +7000 | ls -l # 結果居然僅有列出 root 所在目錄下的文件!這不是咱們要的! # 由於 ll (ls) 並非管線命令的緣由啊! [root@www ~]# find /sbin -perm +7000 | xargs ls -l -rwsr-xr-x 1 root root 70420 May 25 2008 /sbin/mount.nfs -rwsr-xr-x 1 root root 70424 May 25 2008 /sbin/mount.nfs4 -rwxr-sr-x 1 root root 5920 Jun 15 2008 /sbin/netreport ....(底下省略).... |
管線命令在 bash 的連續的處理程序中是至關重要的!另外,在 log file 的分析當中也是至關重要的一環, 因此請特別留意!另外,在管線命令當中,經常會使用到前一個命令的 stdout 做爲此次的 stdin , 某些命令須要用到文件名 (例如 tar) 來進行處理時,該 stdin 與 stdout 能夠利用減號 "-" 來替代, 舉例來講:
[root@www ~]# tar -cvf - /home | tar -xvf -
|
上面這個例子是說:『我將 /home 裏面的文件給他打包,但打包的數據不是紀錄到文件,而是傳送到 stdout; 通過管線後,將 tar -cvf - /home 傳送給後面的 tar -xvf - 』。後面的這個 - 則是取用前一個命令的 stdout, 所以,咱們就不須要使用 file 了!這是很常見的例子喔!注意注意!