1、bash 與 shell
管理整個計算機硬件的其實是操作系統的內核(Kernel),這個內核是需要被保護的,所以我們一般用戶就只能通過shell來跟內核通信,讓內核達到我們想要達到的工作。
1.1、硬件,內核與shell
我們必須通過 shell 將我們輸入的命令與內核通信,好讓內核可以控制硬件來正確無誤的工作。
操作系統其實是一組軟件,由于這組軟件在控制整個硬件與管理系統的活動監測。如果這組軟件能被用戶隨意操作,若用戶應用不當,將會使得整個系統奔潰。因為操縱系統管理的就是整個硬件功能,所以當然不能夠被隨便一些沒有管理能力的終端用戶隨意使用。
但我們總是需要讓用戶操作系統的,所以就有了在操作系統上面發展的應用程序。用戶可以通過應用程序來指揮內核,讓內核達到我們所需要的硬件任務。
如圖所示,其實應用程序在最外層,就如同雞蛋的外殼一樣,因此這個也就被稱為shell。
也就是說,只要能夠操作應用程序的接口都能夠稱為shell。狹義的shell指的是命令行方面的軟件,包括bash等。廣義的shell則包括圖形界面的軟件。
1.2、為何要學習命令界面的shell
命令行界面的shell:各個distribution 都一樣;
遠程管理:命令行界面就是比較快;
Linux的任督二脈:shell是也;
1.3、系統的合法shell與/etc/shells功能
由于shell依據發布者的不同就有許多版本,例如 Bourne SHell (sh)、C SHell、K SHell、TCSH等。
Linux默認使用的這一版本就是 Bourne Again SHell(bash),這個shell是 Bourne SHell 的增強版,也是基于GNU框架下發展出來的。
cat ?/etc/shells ? ?#檢查系統有多少個可以使用的shell
為什么我們系統上合法的shell要寫入/etc/shells這個文件?這是因為系統某些服務在運行過程中,會去檢查用戶能夠使用的shells,而這些shell的查詢就是借助/etc/shells這個文件。
我這個用戶什么時候可以取得shell權限呢?默認又會取得哪一種shell呢?
cat ?/etc/passwd
每一行的最后一個數據,就是你可以取得的默認的shell。
1.4、bash shell 的功能
bash是GNU計劃中重要的工具軟件之一,目前也是Linux distributions 的標準shell。bash主要兼容于sh,并且依據一些用戶的需求而加強shell 版本。
bash的主要優點:
命令記憶能力(history);
命令與文件補全功能(【tab】按鍵的好處);
命令別名設置功能(alias); ? ?# alias ?ll='ls -l'
作業控制、前臺、后臺控制(job control, foreground,background);
使用前臺、后臺的控制可以讓作業進行得更為順利。至于作業控制(jobs)的用途更廣,可以讓我們隨時將工作丟到后臺中執行,而不怕不小心使用 ctrl + c ?來中斷該進程。此外也可以在單一登錄的環境中達到多任務的目的呢!
程序腳本(shell ?script);# 還記得DOS下的批處理文件嗎?Linux下的shell script 則發揮更為強大的功能。
通配符(Wildcard);
1.5、bash shell 的內置命令:type
判定一個命令是來自于外部命令(非bash所提供的命令)或是內置在bash當中的呢?利用type這個命令來查看即可。
type 主要在找出“執行文件”而不是一般文件名,所以type也可以用來作為類似which命令的用途。
1.6、命令的執行
如果命令串太長的話,如何使用兩行來輸出?
cp ?/var/spool/mail/root ?/etc/crontab ?\
> ?/etc/fstab ?/root
上面的命令是將三個文件復制到/root這個目錄下來,不過因為命令太長,我們就利用 “ \[Enter] " ,用轉義符 " \ "來將 " [Enter]"轉義,讓 [Enter] 按鍵不再具有“開始執行”的功能。
特別要注意 轉義字符 ?" \ ",這非常重要。
2、shell 的變量功能
2.1、什么是變量
y=ax+b,其中左邊的y就是變量,右邊的(ax+b)就是變量內容。左邊是未知數,右邊是已知數。
變量就是以一組文字或符號等,來替代一些設置或者是一串保留的數據。
講的更簡單一點,我們可以用一個簡單的“字眼”來替代另一個比較復雜或者是容易變動的數據。這樣最大的好處就是方便。
變量的可變性與方便性;
影響bash環境操作的變量;
腳本程序設計的好幫手;
2.2變量的顯示與設置:echo、unset
你可以利用 ?echo ?這個命令來顯示變量,但是變量在被顯示的時候,前面必須要加上字符 "$" 才行。
echo ?$PATH
echo ?$HOME
myname=Zhang
echo ?$myname
在bash中,當一個變量名稱尚未被設置時,默認的內容是”空“的。
變量的設置規則
1,變量與變量內容以一個等號”=“來連接,如myname=zhang;
2,等號兩邊不能直接接空格符,否則錯誤;
3,變量名稱只能是英文字母和數字,但是開頭字符不能是數字;
4,變量內容若有空格可使用 ?雙引號”“ ?或者單引號‘’ 將變量內容結合起來;
雙引號 " " 內的特殊符號(如$等),可以保有原本的特性。
單引號 ' ' 內的特殊字符則僅為一般字符(純文本)。
5,可用轉義字符 "\"將特殊符號(如 [Enter]、$、\、空格符、!等)變成一般字符;
6,在一串命令中,還需要通過其他命令提供的信息,可以使用 反單引號 ` `(~符號鍵,在1旁邊,tab上邊);
7,若該變量為了增加變量內容時,則可用 $變量名稱 ?或 ?${變量} 累加內容;
8,若該變量需要在其他子進程執行,則需要以 export 來使變量變成環境變量;
9,通常大寫字符為系統默認變量,自行設置變量可以使用小寫字符,方便判斷;
0,取消標量的方法為使用 ?unset 變量名,如 unset myname;
什么是子進程?就是說在我目前這個shell的情況下,去打開另一個新的shell,新的那個shell就是子進程。在一般狀態下,父進程定義的變量是無法在子進程內使用的,要通過 export 將變量變成環境變量后才可以。
在一串命令中,在 反引號 `` 內的命令將被優先執行,而其執行結果將作為外部的輸入信息。
特別注意 單引號,雙引號,反引號?所代表的意思。
2.3、環境變量的功能
環境變量可以幫我們達到很多功能,包括主文件夾的變換、提示符的顯示、執行文件查找的路徑等。
用env(environment)查看環境變量與常見環境變量說明:
HOME ?代表用戶主目錄;
SHELL ?告知我們目前這個環境使用的shell是哪個程序;
HISTSIZE ?這個與歷史命令有關;
PATH ?就是執行文件查找的路勁;
LANG ?系統語系數據;
RANDOM ?這是隨機數變量;
用set查看所有變量(含環境變量和自定義變量)
PS1這個是我們的命令提示符,PS2是第二行的提示符;
PS1:(提示字符的配置)
這是 PS1 (數字的 1 不是英文字母),這個東西就是我們的『命令提示字符』喔! 當我們每次按下 [Enter] 按鍵去運行某個命令后,最后要再次出現提示字符時, 就會主動去讀取這個變量值了。上頭 PS1 內顯示的是一些特殊符號,這些特殊符號可以顯示不同的信息, 每個 distributions 的 bash 默認的 PS1 變量內容可能有些許的差異,不要緊,『習慣你自己的習慣』就好了。 你可以用 man bash (注3)去查詢一下 PS1 的相關說明,以理解底下的一些符號意義。
\d :可顯示出『星期 月 日』的日期格式,如:"Mon Feb 2"
\H :完整的主機名。舉例來說,鳥哥的練習機為『www.vbird.tsai』
\h :僅取主機名在第一個小數點之前的名字,如鳥哥主機則為『www』后面省略
\t :顯示時間,為 24 小時格式的『HH:MM:SS』
\T :顯示時間,為 12 小時格式的『HH:MM:SS』
\A :顯示時間,為 24 小時格式的『HH:MM』
\@ :顯示時間,為 12 小時格式的『am/pm』樣式
\u :目前使用者的賬號名稱,如『root』;
\v :BASH 的版本信息,如鳥哥的測試主板本為 3.2.25(1),僅取『3.2』顯示
\w :完整的工作目錄名稱,由根目錄寫起的目錄名稱。但家目錄會以 ~ 取代;
\W :利用 basename 函數取得工作目錄名稱,所以僅會列出最后一個目錄名。
\# :下達的第幾個命令。
\$ :提示字符,如果是 root 時,提示字符為 # ,否則就是 $ 啰~
好了,讓我們來看看 CentOS 默認的 PS1 內容吧:『[\u@\h \W]\$ 』,現在你知道那些反斜杠后的數據意義了吧? 要注意喔!那個反斜杠后的數據為 PS1 的特殊功能,與 bash 的變量配置沒關系啦!不要搞混了喔! 那你現在知道為何你的命令提示字符是:『 [root@www ~]# 』了吧?
$:(關于本 shell 的 PID)
錢字號本身也是個變量喔!這個咚咚代表的是『目前這個 Shell 的線程代號』,亦即是所謂的 PID (Process ID)。 更多的程序觀念,我們會在第四篇的時候提及。想要知道我們的 shell 的 PID ,就可以用:『 echo $$ 』即可!出現的數字就是你的 PID 號碼。
什么?問號也是一個特殊的變量?沒錯!在 bash 里面這個變量可重要的很! 這個變量是:『上一個運行的命令所回傳的值』, 上面這句話的重點是『上一個命令』與『回傳值』兩個地方。當我們運行某些命令時, 這些命令都會回傳一個運行后的代碼。一般來說,如果成功的運行該命令, 則會回傳一個 0 值,如果運行過程發生錯誤,就會回傳『錯誤代碼』才對!
OSTYPE, HOSTTYPE, MACHTYPE:(主機硬件與核心的等級)
由于不同等級的 CPU 命令集不太相同,因此你的軟件可能會針對某些 CPU 進行優化,以求取較佳的軟件性能。 所以軟件就有 i386, i686 及 x86_64 之分。
要留意的是,較高階的硬件通常會向下兼容舊有的軟件,但較高階的軟件可能無法在舊機器上面安裝!
export: 自定義變量轉成環境變量
因為子進程僅會繼承父進程的環境變量,子進程不會繼承父進程的自定義變量,所以需要使用 export 命令。
export ?變量名稱;
2.4、影響顯示結果的語系變量(locale)
locale ?;
設置LANG的時候,其他的語系變量就會被這個變量所替代。
2.5、變量的有效范圍
某些書籍會談到 全局變量(global variable)和 局部變量(local variable),基本上可以這么理解,
環境變量=全局變量;
自定義變量=局部變量;
2.6、變量鍵盤讀取、數組與聲明:read,array,declare
read
要讀取來自鍵盤輸入的變量,就是用read這個命令。
declare / typeset
declare 或 typeset 是一樣的功能,就是在『聲明變量的類型』
變量類型默認為 字符串,所以若不指定變量類型,則 1+2 為一個字符串而不是計算式;
bash 環境中的數值運算,默認最多僅能到達整數類型,所以 1/3 結果為 0;
數組(array)變量類型:
某些時候,我們必須使用數組來宣告一些變量。
數組的變量類型比較有趣的地方在于『讀取』,一般來說,建議直接以 ${數組} 的方式來讀取,比較正確無誤的啦!
3、命令別名與歷史命令
3.1、命令別名設置:alias,unalias
命令別名是一個很有趣的東西,特別是你的慣用命令特別長的時候。或者給命令增設默認選項的時候。
alias ?ll='ls ?-l'
source ~/.bashrc
查看系統別名情況
unalias ?ll ? ? #取消ll命令別名
3.2、歷史命令:history
查看使用過的歷史命令
history
那么history命令只可以讓我們查詢命令而已嗎?當然不止。我們可以利用相關的功能來幫我們執行歷史命令。
基本上history命令用途很大,但是需要小心安全的問題,尤其是root的歷史紀錄文件,這是Cracker的最愛。因為不小心 root 會將很多的重要數據在執行的過程中記錄在 ~/.bash_history當中,如果這個文件被解析的話,后果不堪設想。
無論如何,使用history配置 !曾經使用的命令執行是很有效率的。
4、Bash Shell的操作環境
是否記得我們登錄主機的時候屏幕上面會有一些說明文字,并且登錄的時候還可以給用戶提供一些信息或者歡迎文字。此外我們習慣的環境變量,命令別名等是否可以登錄就主動幫我們設置好?
4.1、路徑與命令查找順序
命令的運行順序基本上可以這樣看:
1,以絕對/相對路徑執行命令;
2,由alias找到該命令來執行;
3,由bash內置的(builtin)命令來執行;
4,通過$PATH這個變量的順序找到的第一個命令來執行
4.2、bash的登錄與歡迎信息:/etc/issue,/etc/motd
還記得在終端接口登錄時候的歡迎信息嗎?它在 /etc/issue 里面。可對此進行自定義。
cat ?/etc/issue
如果你想要讓用戶登錄后取得一些信息,例如你想要讓大家都知道的信息,那么可以將信息加入 /etc/motd 里去。所有用戶都會顯示這個信息。
vi ? /etc/motd
4.3、bash的環境配置文件
操作系統有一些環境配置文件的存在,讓bash在啟動時直接讀取這些配置文件,以規劃好bash的操作環境。而這些配置文件又可以分為全體系統的配置文件以及用戶個人偏好配置文件。要注意的是,我們前幾個小時談到的命令別名、自定義的變量在你注銷bash后就會失效,所以你想要保留你的設置,就得要將這些設置寫入配置文件才行。
login shell 和 non-login shell
取得bash時需要完整的登錄流程,就稱為login shell。
取得bash接口的方法不需要重復登錄的舉動,就稱為 non-login shell。
記住幾個組合按鍵:
4.4、通配符與特殊符號
通配符(wildcard)是一個非常有用的功能。
bash中常見的特殊符號。理論上,你的文件名盡量不要使用到上述的字符。
5、數據流重定向
數據流重定向就是將某個命令執行后應該要出現在屏幕上的數據傳輸到其他的地方,l例如文件或者是設備。這玩意兒在Linux的文本模式下面可重要的,尤其是如果我們想要將某些數據保存下來時,就更有用了。
5.1、什么是數據流重定向
Standard output (標準輸出)和 Standard error (標準錯誤)都是默認輸出到屏幕上面來的。
簡單來說,標準輸出指的是命令執行所回傳的正確信息,而標準錯誤輸出可理解為命令執行失敗后,所回傳的錯誤信息。
標準輸入(stdin):代碼為0,使用 < 或者 <<;
標準輸出(stdout):代碼為1,使用 > 或者 >>;
標準錯誤(stderr):代買為2,使用 2> 或者 2>>;
">" 表示以覆蓋方式寫入,">>"表示以追加方式寫入。
將標準輸出和錯誤輸出寫入不同文件:
find ?/home -name .bashrc > right.txt 2> error.txt
如果要將正確與錯誤寫入相同文件:
find /home -name .bashrc > /dev/null 2>&1
/dev/null 垃圾桶黑洞設備與特殊寫法,這個/dev/null 可以吃掉任何導向這個設備的信息。
Standard input(標準輸入):將原本由鍵盤輸入的數據改由文件的內容來替代。
cat ?> ?catfile ?< ?~/abc.txt
5.2、命令執行的判斷依據: “;” ? “&&” ? “||”
在某些情況下,我們想一次性輸入多個命令去執行,有兩個選擇。
1、cmd; ?cmd ? ?#不考慮命令相關性的連續命令執行
如:sync; shutdown -h now
在命令與命令中利用分號(;)來隔開,這樣一來,分號前的命令執行完后就會立刻接著執行后面的命令了。Linux下命令是由左往右走執行的。
2、$?(命令回傳碼)與 && 或 ||
若前一個命令執行的結果為正確,在Linux下面會回傳一個 $?=0 的值。
5.3、雙重定向
想要將數據流處理過程中將某段信息存下來,就可以利用 tee命令。
tee 命令會同時將數據流送與 文件 和 屏幕(screen)
6、管道命令(pipe)
管道命令使用 " | " 這個界定符號。
其實管道命令" | " 僅能處理經由前面一個命令傳來的正確信息,也就是 Standard output的信息,對于 Standard error并沒有直接處理的能力。
在每個管道后面接的第一個數據必定是”命令“,而且這個命令必須要能夠接收 standard input 的數據才行,這樣的命令才可以是”管道命令“。
6.1、選取命令:cut,grep
什么是選取命令,說穿了,就是講一段數據經過分析后,取出我們所想要的,或者是經由分析關鍵字,去得我們所想要的那一行。
cut 命令
這個命令可以將一段信息的某一段”切“出來,處理的信息是以”行“為單位。
cut 主要的用途在于將同一行里面的數據進行分解,最常使用在分析一些數據或文字數據的時候。
grep 命令
grep 是分析一行信息,若當中有我們所需要的信息,就將該行拿出來。
grep 可以解析一行文字,去得關鍵字,若該行有存在
6.2、排序命令:sort,wc,uniq
sort 是很有趣的命令,它可以幫助我們進行排序,而且可以依據不同的數據類型來排序。
uniq,排序完成后,想將重復的數據僅列出一個顯示。
wc,知道文件里面有多少行,多少字,多少多少字符。
重點回顧:
由于內核在內存中是受保護的塊,因此我們必須要通過”Shell“將我們輸入的命令與Kernel通信,好讓Kernel可以控制硬件來正確無誤地工作。
學習Shell的主要原因有:命令行界面的shell在各大distribution都一樣;遠程管理時命令行界面速度較快;shell是管理Linux系統非常重要的一環,因為Linux內很多控制都是以shell編寫的。
系統合法的shell均寫在/etc/shell文件中。
用戶默認登陸取得的shell記錄于/etc/passwd的最后一個字段。
bash的功能主要有命令編輯功能、命令與文件補全功能、命令別名設置功能、作業控制、前臺、后臺控制、程序化腳本、通配符。
type可以用來找到執行命令為何種類型,也可用于與which相同的功能。
變量就是以一組文字或符號等來替換一些設置或者是一串保留的數據。
變量主要有環境變量和自定義變量,或稱為全局變量和局部變量。
使用 env(environment)與export可查看環境變量,其中export可以將自定義變量轉換成環境變量。
set 可以查看目前bash環境下的所有變量。
$?也為變量,是前一個命令執行完畢后的回傳碼。在Linux回傳碼為0代表執行成功。
locale可用于查看語系數據。
可用read讓用戶由鍵盤輸入變量的值。
ulimit 可用以限制用戶使用系統的資源情況。
bash的配置文件主要分為 loginshell 與 non-login shell。 login shell 主要讀取 /etc/profile 與 ~/.bash_profile,non-login shell 則僅讀取 ~/.bashrc。
通配符主要有 * ?? ?[ ]等。
數據流重定向通過 >、2>、< 之類的符號將輸出的信息轉到其他文件夾或設備去。
連續命令的執行可通過:&&,||等符號來處理。
管道命令的重點是它僅會處理 standard output,對于 standard error output 會予以忽略。管道命令必須要能偶接收來自前一個命令的數據成為 standard input繼續處理才行。