Linux是由命令行組成的操做系統,精髓在命令行,不管圖形界面發展到什麼水平,命令行方式的操做永遠是不會變的。Linux命令有許多強大的功能:從簡單的磁盤操做、文件存取,到進行復雜的多媒體圖像和流媒體文件的製做,都離不開命令行。雖然Linux也有桌面系統,可是X-window也只是運行在命令行模式下的一個應用程序。linux
所以,能夠說命令是學習Linux系統的基礎,在很大程度上學習Linux就是學習命令,不少Linux高手其實都是玩兒命令很熟練的人。shell
也許對於剛剛從Windows系統進入Linux學習的初學者來講,馬上進入枯燥的命令學習實在太難,可是一旦學會就愛不釋手。由於它的功能實在太強大了。bash
有不少初學者都會遇到這麼一個問題,本身對系統的每一個命令都很熟悉,可是在系統出現故障的時候,就無從下手了,甚至不知道在何時用什麼命令去檢查系統,這是不少Linux新手最無奈的事情了。說到底,就是學習的理論知識沒有很好地與系統實際操做相結合。網絡
不少Linux知識,例如每一個命令的參數含義,在書本上說得很清楚,看起來也很容易理解,可是一旦組合起來使用,卻並不那麼容易,沒有屢次的動手練習,其中的技巧是沒法徹底掌握的。運維
人類大腦不像計算機的硬盤,除非硬盤壞掉或者硬盤被格式化,不然儲存的資料將永遠記憶在硬盤中,並且時刻能夠調用。而在人類記憶的曲線中,必需要不斷地重複練習纔會將一件事情記得比較牢。學習Linux也同樣,若是沒法堅持學習的話,就會學了後面的,忘記了前面的。還有些Linux初學者也學了不少Linux知識,可是因爲長期不用,致使學過的東西在很短的時間內又忘記了,長此以往,失去了學習的信心。ide
可見,要培養本身的實戰技能,只有勤於動手,肯於實踐,這也是學好Linux的根本。函數
遇到問題,首先想到的應該是如何本身去解決這個問題,解決方式有不少,好比看書查資料、網絡搜索引擎搜索和瀏覽技術論壇等,經過這幾種方式,90%的問題都能獲得解決。linux運維
獨立思考並解決問題,不但鍛鍊了本身獨立解決問題的能力,在技術上也能獲得快速提升。若是經過以上方式實在解決不了的話,能夠向人詢問,獲得答案後要思考爲什麼這麼作,而後作筆記記錄解決過程。最忌諱的方式是隻要遇到問題,就去問人,雖然這樣可能會很快解決問題,可是長久下去遇到問題就會依賴別人,技術上也不會進步。學習
shell的本意是「殼」的意思,其實已經很形象地說明了shell在Linux系統中的做用。shell就是圍繞在Linux內核以外的一個「殼」程序,用戶在操做系統上完成的全部任務都是經過shell與Linux系統內核的交互來實現的。咱們應該熟悉DOS系統中command.com程序,shell的功能與此相似,可是shell的功能更增強大,更加好用。this
各類操做系統都有本身的shell。以DOS爲例,它的shell就是command.com程序。DOS下還出現了不少第三方命令解釋程序,例如4DOS、NDOS等,這些命令解釋程序徹底能夠取代標準的command.com程序。一樣,Linux下除了默認的Bourne again shell(bash),還有不少其餘的shell,例如C shell(csh)、Korn shell(ksh)、Bourne shell(sh)和Tenex C shell(tcsh)等。每一個版本的shell功能基本相同,但各有千秋,如今的Linux系統發行版通常都以bash做爲默認的shell。
shell自己是一個C語言編寫的程序,是用戶和操做系統內核之間通訊的橋樑。shell既是一種命令解釋程序,又是一種功能強大的解釋型程序設計語言。做爲命令解釋程序,shell解釋用戶輸入的命令,而後提交到內核處理,最後把結果返回給用戶。
爲了加快命令的運行,同時更有效地定製shell程序,shell中定義了一些內置的命令,通常咱們把shell自身解釋執行的命令稱爲內置命令,例以下面咱們將要講到的cd、pwd、exit和echo等命令,都是屬於bash的內置命令。當用戶登陸系統後,shell以及內置命令就被系統載入到內存,而且一直運行,直到用戶退出系統爲止。除了內置命令,Linux系統上還有不少可執行文件。可執行文件相似於Windows下的.exe文件,這些可執行文件也能夠做爲shell命令來執行。其實Linux上不少命令都不是shell的內置命令,例如ls就是一個可執行文件,存放在/bin/ls中。這些命令與shell內置命令不一樣,只有當它們被調用時,才由系統裝入內存執行。
當用戶登陸系統後,若是是登陸字符界面,將出現shell命令提示符。「#」表示登陸的用戶是系統超級用戶,「*」表示登陸到系統的是普通用戶。shell執行命令解釋的具體過程爲:用戶在命令行輸入命令提交後,shell程序首先檢測是否爲內置命令,若是是,就經過shell內部的解釋器將命令解釋爲系統調用,而後提交給內核執行;若是不是shell內置的命令,那麼shell會按照用戶給出的路徑或者根據系統環境變量的配置信息在硬盤尋找對應的命令,而後將其調入內存,最後再將其解釋爲系統調用,提交給內核執行。
最後shell仍是強大的解釋型程序設計語言,它定義了各類選項和變量,幾乎支持高級程序語言的全部程序結構,例如變量、函數、表達式和循環等。利用shell能夠編寫shell腳本程序,相似於Windows/DOS下的批處理文件,可是shell功能更加完善,更增強大。
Linux下的各類shell的主要區別在於命令行的語法。對於一些普通的命令,各個shell版本的語法基本相同,只有在編寫一個shell腳本或者使用一些shell高級特性的時候,各個版本shell的差別纔會顯示出來。
shell語法分析是指shell的對命令的掃描處理過程,也就是把命令或者用戶輸入的內容分解成要處理的各個部分的操做。在Linux系統下,shell語法分析包含不少的內容,例如重定向、文件名擴展和管道等。
本節咱們以bash爲例,介紹如下shell命令的語法分析。
3.1.shell的命令格式
用戶登陸系統後,shell命令行啓動。shell遵循必定的語法格式將用戶輸入的命令進行分析解釋並傳遞給系統內核。shell命令的通常格式爲:
command [options] [arguments]
根據習慣,咱們通常把具備以上格式的字符串稱爲命令行。命令行是用戶與shell之間對話的基本單位。
? command:表示命令的名稱。
? options:表示命令的選項。
? arguments:表示命令的參數。
在命令行中,選項是包含一個或多個字母的代碼,主要用於改變命令的執行方式。通常在選項前面有一個「-」符號,用於區別參數。例如:
[root@WEBServer ~]#ls -a
ls命令加上-a選項後,列出當前目錄下的全部文件(包含隱藏文件)。若是ls不加「-a」選項,則僅僅顯示當前目錄下的文件名和目錄(不顯示隱藏文件)。
通常命令都有不少選項,能夠單獨列出它們,也能夠在「-」後面把須要的選項都列出來,例如,
ls –a –l
也能夠寫成:
ls –al
不少命令均可以接受參數。參數就是在選項後面緊跟的一個或多個字符串,這些字符串指定了命令的操做對象,如文件或者目錄。例如,要顯示/etc目錄下的全部文件及信息,可用如下命令:
[root@WEBServer ~]#ls –al /etc
特殊狀況下,有些命令能夠不帶參數,例如ls命令,而有些必須帶參數。當參數不夠時,shell就會給出錯誤提示。例如,mv命令至少須要兩個參數。
[root@WEBServer ~]#mv mylinux1.txt mylinux.txt
在shell的一個命令行中,還能夠輸入多個命令,用分號將各個命令分開,例如:
[root@WEBServer ~]#ls –al;cp mylinux1.txt mylinux2.txt
相反也能夠在多行中輸入一個命令,用「\」將一個命令持續到下一行:
[root@WEBServer ~]#cp –i \ >mylinux1.txt \ > mylinux2.txt
3.二、shell的通配符
通配符主要是爲了方便用戶對文件或者目錄的描述,例如用戶僅僅須要以「.sh」結尾的文件時,使用通配符就能很方便地實現。各個版本的shell都有通配符,這些通配符是一些特殊的字符,用戶能夠在命令行的參數中使用這些字符,進行文件名或者路徑名的匹配。shell將把與命令行中指定的匹配規則符合的全部文件名或者路徑名做爲命令的參數,而後執行這個命令。
bash中經常使用的通配符有「*」、「?」、「[]」。
(1)「*」——匹配任意一個或多個字符
例如:
[root@WEBServer ~]#ls *.txt
這個命令是列出當前目錄中全部以「.txt」結尾的文件(除去以「.」開頭的文件)。
[root@WEBServer ~]#cp doc/* /opt
表示將doc目錄下的全部文件(除去以「.」開頭的文件)拷貝到/opt目錄下。
[root@WEBServer ~]#ls –al /etc/*/*.conf
列出/etc目錄的子目錄下全部以「.conf」結尾的文件。在/etc目錄下的以「.conf」結尾文件將不會列出。
(2)「?」——匹配任意單一字符
例如:
[root@WEBServer ~]#ls ab?.txt
將列出當前目錄下以ab開頭,隨後一個字母是任意字符,接着以「.txt」結尾的文件。
[root@WEBServer ~]#ls ab??.txt
將列出當前目錄下以ab開頭,隨後的兩個字母是任意字符,接着以「.txt」結尾的文件。
(3)「[]」——匹配任何包含在方括號內的單字符
例如:
[root@WEBServer ~]#ls /dev/sda[12345] /dev/sda1 /dev/sda2 /dev/sda3 /dev/sda4 /dev/sda5
上面列出了在/dev目錄下以sda開頭,第4個字符是一、二、三、4或5的全部文件。
[root@WEBServer ~]#ls /dev/sda[1-5]
在方括號中「1-5」給出了匹配的範圍,與上面一條命令徹底等效。
(4)通配符的組合使用
在Linux下,通配符也能夠組合使用,例如:
[root@WEBServer ~]#ls [0-9]?.conf
列出當前目錄下以數字開頭,隨後一個是任意字符,接着以「.conf」結尾的全部文件。
[root@WEBServer ~]#ls [xyz]*.txt
列出當前目錄下以x、y或z開頭,最後以「.txt」結尾的文件。
3.三、shell的重定向
Linux下系統打開3個文件,即標準輸入、標準輸出和標準錯誤輸出。用戶的shell將鍵盤設爲默認的標準輸入,默認的標準輸出和標準錯誤輸出爲屏幕。也就是用戶從鍵盤輸入命令,而後將結果和錯誤信息輸出到屏幕。
所謂的重定向,就是不使用系統默認的標準輸入輸出,而是從新指定,所以重定向分爲輸入重定向、輸出重定向和錯誤輸出重定向。要實現重定向就須要瞭解重定向操做符,shell就是根據重定向操做符來決定重定向操做的。
一、輸入重定向
輸入重定向用於改變命令的輸入源,利用輸入重定向,就能夠將一個文件的內容做爲命令的輸入,而不從鍵盤輸入。
用於輸入重定向的操做符有「<」和「<<」。例如:
[root@WEBServer ~]#wc </etc/shadow 40 40 1169
用wc命令統計輸入給它的文件/etc/inittab的行數、單詞數和字符數。
還有一種輸入重定向「<<」,這種重定向告訴shell,當前命令的標準輸入爲來自命令行中一對分隔號之間的內容。例如:
[root@WEBServer ~]#wc << aa > # Default runlevel. The runlevels used by RHS are: > # 0 - halt (Do NOT set initdefault to this) > # 1 - Single user mode > # 2 - Multiuser, without NFS (The same as 3, if you do not have networking) > # 3 - Full multiuser mode > # 4 - unused > # 5 - X11 > # 6 - reboot (Do NOT set initdefault to this) > aa 8 65 303
上面的命令將一對分隔號aa之間的內容做爲wc命令的輸入。分隔號能夠是任意字符。shell將在第一個分隔號後開始讀取內容,直到出現另外一個分隔號讀取結束,而後將內容送給wc命令處理。
二、輸出重定向
輸出重定向是將命令的輸出結果不在屏幕輸出,而是輸出到一個指定文件中。
在Linux下輸出重定向用得不少,例如,某個命令的輸出很長,一個屏幕沒法顯示完畢,咱們能夠將命令的輸出指定到一個文件,而後用more命令查看這個文件,從而獲得命令輸出的完整信息。
用於輸出重定向的操做符有「>」和「>>」。
例如:
[root@WEBServer ~]#ps –ef >ps.txt
將ps –ef輸出的系統運行進程信息所有輸入到了ps.txt文件,而不輸出到屏幕,能夠用more命令查看ps.txt文件中系統運行的進程信息。
[root@WEBServer ~]#more file1 file2 file3 >file
more命令是查看文件的內容,上面的命令是將file一、file2和file3的內容所有輸出到file文件中,相似於文件內容的合併。
若是在「>」後面指定的文件不存在的話,shell就會自動重建一個;若是文件存在的話,那麼這個文件原有的內容將被覆蓋;若是不想覆蓋存在的文件,可使用「>>」操做符。例如:
[root@WEBServer ~]#ls –al /etc/* >>/root/install.log
將/etc目錄及其子目錄下的全部文件信息追加到/root/install.log文件的後面。/root/install.log文件原來的內容仍然存在。
三、錯誤重定向
錯誤重定向和標準輸出重定向同樣,可使用操做符「2>」和「2>>」實現對錯誤輸出的重定向。例如:
[root@WEBServer ~]#tar zxvf text.tar.gz 2> error.txt
tar是打包命令,能夠在屏幕上看到tar的解壓過程。若是「text.tar.gz」是個損壞的壓縮包,就會把錯誤信息輸出到error.txt文件。
3.四、shell的管道
管道能夠把不少命令鏈接起來,能夠把第1個命令的輸入看成第2個命令的輸出,第2個命令的輸出看成第3個命令的輸入,依此類推。所以,管道的做用就是把一個命令的輸出看成下一個命令的輸入,而不通過任何中間文件。
經過管道符「|」能夠創建一個管道鏈接,例如:
[root@WEBServer ~]# ls -al /etc/* |more
表示將/etc目錄以及子目錄下的全部文件分屏顯示。
[root@WEBServer ~]#ps -ef|grep httpd|wc –l
這個命令是查看系統中正在運行的httpd進程,並計算httpd的進程數。
3.五、shell中的引用
在bash中有不少特殊字符,這些字符自己就具備特殊含義。若是在shell的參數中使用它們,就會出現問題。Linux中使用了「引用」技術來忽略這些字符的特殊含義,引用技術就是通知shell將這些特殊字符看成普通字符處理。shell中用於引用的字符有轉義字符「\」、單引號「'」、雙引號「" "」。
一、轉義字符「\」
若是將「\」放到特殊字符前面,shell就忽略這些特殊字符的原有含義,看成普通字符對待,例如:
[root@WEBServer ~]#ls abc?* C:\backup [root@WEBServer ~]#mv abc\?\* abc [root@WEBServer ~]#mv C\:\\backup backup
上面是將abc?*重命令爲abc,將C:\backup重命名爲backup。由於文件名中含有特殊字符,全部都使用了轉義字符「\」。
二、單引號「'」
將字符串放到一對單引號之間,那麼字符串中全部字符的特殊含義將被忽略,例如:
[root@WEBServer ~]#mv C\:\\backup backup [root@WEBServer ~]#mv 'C:\backup' backup
上面兩條命令徹底等效。
三、雙引號「" "」
雙引號的引用與單引號基本相同,包含在雙引號內的大部分特殊字符能夠看成普通字符處理,可是仍有一些特殊字符即便用雙引號括起來,也仍然保留本身的特殊含義,好比「$」、「\」和「`」。
[root@WEBServer ~]#str="The \$SHELL Current shell is $SHELL" [root@WEBServer ~]#str1="\$$SHELL" [root@WEBServer ~]#echo $str The $SHELL Current shell is /bin/bash [root@WEBServer ~]#echo $str1 $/bin/bash
從上面輸出能夠看出,「$」和「\」在雙引號內仍然保留了特殊含義。
[root@WEBServer ~]# str="This hostname is `hostname`" [root@WEBServer ~]# echo $str This hostname is WEBServer
上面的輸出中,字符「`」在雙引號中也保留了本身特殊含義。
看到了吧,shell很厲害吧,linux運維工做更多的是與shell打交道,因此學會shell,是學好linux運維的根本。
說了這麼多,那麼問題來了,怎麼能快速學好shell,可以編寫高質量的shell腳本提升運維效率呢,我將多年來企業一線工做經驗進行了總結和提煉,寫成了專欄《神奇高效的Linux命令行》點擊前往,15篇文章打通shell任通二脈,讓經驗和案例說話: