Linux學習筆記

本筆記按照鳥哥的Linux私房菜學習,另,有關Linux下的環境變量PATH方法設定請看該博客:在Linux裏設置環境變量的方法(export PATH)php

1、BASH Shell學習

一、什麼是 Shell?

這應該是個蠻有趣的話題:『什麼是 Shell ?』相信只要摸過計算機,對於操做系統 ( 不管是 Linux 、 Unix 或者是 Windows ) 有點概念的朋友們大多聽過這個名詞,由於只要有『操做系統』那麼就離不開 Shell 這個東西。
這就是基本的一個輸出聲音的須要的步驟!那麼也就是說,你必需要『輸入』一個指令以後, 『硬件』纔會透過你下達的指令來工做!嘿嘿!那麼硬件如何知道你下達的指令呢?那就是 kernel (核心)的控制工做了!瞭解了嗎?沒錯!也就是說,咱們必需要透過『 Shell 』將咱們輸入的指令與 Kernel 溝通,好讓 Kernel 能夠控制硬件來正確無誤的工做! 基本上,咱們能夠透過底下這兩張圖來講明一下:html

clipboard.png

clipboard.png

基本上,替咱們工做的是『硬件』,而控制硬件的是『核心』,再來,咱們使用者乃是利用『Shell』控制一些 kernel 提供的 『工具 (Utility)』來操控硬件替咱們正確的工做。再進一步來講,因爲 kernel 聽不懂人類的語言,而人類也沒有辦法直接記得 kernel 的語言,因此二者的溝通就得藉由 shell 來支援了!(其實早期的 DOS 的文字接口也是使用 shell 來溝通呀!那個 shell 的名稱就叫作 command.com ,還記得嗎? ^_^)linux

以字面上的意思來講, kernel 是『核心』的意思,而 Shell 是『殼』的意思,呵呵!也就是說, shell 是最外頭的咚咚!而 kernel 乃是最內層的的咚咚啦!核心是操做系統的最底層的東西! 這個核內心頭包括了各類的支持硬件的工具!固然囉,若是你的硬件太新,而你的 kernel 並無支持的話,那麼很抱歉,你的 Shell 能力再怎麼強,也沒有辦法使硬件工做的! 這樣能夠了解了嗎?呵呵!沒錯!使計算機主機工做的正是核心的任務,可是操做核心來替使用者工做的,倒是 shell 喔!所以,有時候你的 shell 搞了老半天,硬件卻不能工做的時候,請注意, 您的『核心』是否正確呢?阿!扯遠了!這是 kernel 章節纔要說的東西。web

2.Shell scripts 的強大功能:

在 DOS 年代還記得將一堆指令寫在一塊兒的所謂的『批處理文件』吧?在 Linux 底下的 shell scripts 則發揮的更爲強大的功能,能夠將您平常生活當中常須要下達的連續指令寫成一個檔案, 該檔案而且能夠透過對談交互式的方式來進行主機的偵測工做!也能夠藉由 shell 提供的環境變量及相關指令來進行設計,哇!整個設計下來幾乎就是一個小型的程序語言了!該 scripts 的功能真的是超乎個人想象以外!之前在 DOS 底下須要程序語言才能寫的東西,在 Linux 底下使用簡單的 shell scripts 就能夠幫你達成了!真的厲害!!這部分咱們在後續章節再來談!shell

變量的取用與設定:echo, 變量設定規則, unset
說的口沫橫飛的,也不知道『變量』與『變量表明的內容』有啥關係? 固然啦,那咱們就將『變量』的『內容』拿出來給您瞧瞧就行了。利用 echo 這個指令來取用變量, 可是,變量在被取用時,前面必需要加上 $ 才行,舉例來講,要知道 PATH 的內容,該如何是好?數組

[root@linux ~]# echo $variable
[root@linux ~]# echo $PATH
/bin:/sbin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:/usr/X11R6/bin
[root@linux ~]# echo ${PATH}

變量的取用就如同上面的範例,利用 ehco 就可以讀出,只是須要在變量名稱前面加上 $ , 或者是以 ${variable} 的方式來取用均可以!固然啦,那個 echo 的功能但是不少的, 咱們這裏單純是拿 echo 來讀出變量的內容而已,更多的 echo 使用,請自行給他 man echo 吧! ^_^bash

範例一:設定一變量 name ,且內容爲 VBird 。
[root@linux ~]# 12name=VBird
-bash: 12name=VBird: command not found  <==屏幕會顯示錯誤!由於不能以數字開頭!
[root@linux ~]# name = VBird  <==仍是錯誤!由於有空白!
[root@linux ~]# name=VBird    <==OK 的啦!

範例二:承上題,若變量內容爲 VBird's name 呢?
[root@linux ~]# name=VBird's name  
# 由於單引號能夠將 Enter 這個特殊字符取消,因此,您能夠繼續在下一行輸入內容~
# 不過,這與咱們要達到的功能不一樣,因此,算是失敗的啦!
[root@linux ~]# name="VBird's name"  <==OK 的啦!
[root@linux ~]# name=VBird\'s\ name
# 利用反斜槓 (\) 跳脫特殊字符,例如單引號與空格鍵,這也是 OK 的啦!

範例三:我要在 PATH 這個變量當中『累加』:/home/dmtsai/bin 這個目錄
[root@linux ~]# PATH=$PATH:/home/dmtsai/bin
[root@linux ~]# PATH="$PATH":/home/dmtsai/bin
# 上面這兩種格式在 PATH 裏頭的設定都是 OK 的!可是底下的例子就不見得囉!

範例四:呈範例三,我要將 name 的內容多出 "yes" 呢?
[root@linux ~]# name=$nameyes  
# 知道了吧?若是沒有雙引號,那麼變量成了啥?name 的內容是 $nameyes 這個變量!
# 呵呵!咱們可沒有設定過 nameyes 這個變量吶!因此,應該是底下這樣纔對!
[root@linux ~]# name="$name"yes
[root@linux ~]# name=${name}yes

範例五:如何讓我剛剛設定的 name=VBird 能夠用在下個 shell 的程序?
[root@linux ~]# name=VBird
[root@linux ~]# bash        <==進入到所謂的子程序
[root@linux ~]# echo $name  <==嘿嘿!並無剛剛設定的內容喔!
[root@linux ~]# exit        <==離開剛剛的子程序
[root@linux ~]# export name
[root@linux ~]# bash        <==進入到所謂的子程序
[root@linux ~]# echo $name  <==出現了設定值了!
[root@linux ~]# exit        <==離開剛剛的子程序
# 什麼是『子程序』呢?就是說,在我目前這個 shell 的狀況下,
# 去啓用另外一個新的 shell ,新的那個 shell 就是子程序啦!在通常的狀態下,
# 父程序的自定義變量是沒法在子程序內使用的。可是透過 export 將變量變成
# 環境變量後,就可以在子程序底下應用了!很不賴吧!至於程序的相關概念,
# 咱們會在『程序與資源管理』章節當中提到的喔!

範例六:如何進入到您目前核心的模塊目錄?
[root@linux ~]# cd /lib/modules/`uname -r`/kernel
# 每一個操做系統核心版本都不相同,以 FC4 爲例,他的預設核心版本是 
# 2.6.11-1.1369_FC4 因此,他的模塊目錄在 /lib/modules/2.6.11-1.1369_FC4/kernel 。
# 由於每一個 distributions 的這個值都不相同,可是咱們卻能夠利用 uname -r 這個指令
# 先取得版本信息,因此囉,就能夠透過上面指令當中的內含指令 `uname -r` 
# 先取得版本輸出到 cd .. 那個指令當中,就可以順利的進入目前核心的驅動程序所放置
# 的目錄囉!很方便吧!

範例七:取消剛剛設定的 name 這個變量內容
[root@linux ~]# unset name

3.set

其餘全部的變量說明: set
而除了這些環境變量以外,還有沒有什麼重要的變量呢?固然有啊! 咱們在 bash 的環境下,其實還有一些挺重要的變量,這些變量是『在這個 shell 環境下有效』的, 若是是在『子程序』,這些變量值就不會相同了。 那麼如何觀察目前 shell 環境下的全部變量呢?很簡單啊,就用 set 便可!set 這個指令除了會將環境變量列出來以外,其餘咱們的自定義變量,與全部的變量,都會被列出來喔!信息多好多。 底下僅列出幾個重要的內容。併發

\d :表明日期,格式爲 Weekday Month Date,例如 "Mon Aug 1"
\H :完整的主機名。舉例來講,鳥哥的練習機 linux.dmtsai.tw ,那麼這個主機名就是 linux.dmtsai.tw
\h :僅取主機名的第一個名字。以上述來說,就是 linux 而已, .dmtsai.tw 被省略。
\t :顯示時間,爲 24 小時格式,如: HH:MM:SS
\T :顯示時間,12 小時的時間格式!
\A :顯示時間,24 小時格式, HH:MM
\u :目前使用者的帳號名稱;
\v :BASH 的版本信息;
\w :完整的工做目錄名稱。家目錄會以 ~ 取代;
\W :利用 basename 取得工做目錄名稱,因此僅會列出最後一個目錄名。
\# :下達的第幾個指令。
\$ :提示字符,若是是 root 時,提示字符爲 # ,不然就是 $ 囉~

OK!因此,由預設的 PS1 內容爲: '[u@h W]&dollar; ' 就能夠了解爲什麼咱們的提示字符會是: [root@linux ~]# 了吧!好了,那麼假設我想要有相似底下的提示字符:less

[root@linux /home/dmtsai 16:50 #12]#

,那個 # 表明第 12 次下達的指令。 那麼應該如何設定 PS1 呢?能夠這樣啊:curl

[root@linux home]# PS1='[\u@\h \w \A #\#]\$ '
[root@linux /home 17:02 #85]# 
# 看到了嗎?提示字符變了!變的頗有趣吧!其中,那個 #85 比較有趣,
# 若是您按下 [Enter] 後,該數字就會增長喔!爲啥?上面有說明ㄇㄟ!

$:(關於本 shell 的 PID)

其實這個咚咚表明的是『目前這個 Shell 的線程代號』,亦便是所謂的 PID (Process ID)。 更多的程序觀念,咱們會在第四章的時候說起。想要知道咱們的 shell 的 PID ,就能夠: echo $$ 便可!

?:(關於上個執行指令的回傳碼)

蝦密?問號也是一個特殊的變數?沒錯!在 bash 裏面這個變量可重要的很! 這個變數是:『上個執行的指令所回傳的值』, 上面這句話的重點是『上一個指令』與『回傳值』兩個地方。當咱們執行某些指令時, 這些指令都會回傳一個執行後的代碼。通常來講,若是成功的執行該指令, 則會回傳一個 0 值,若是執行過程發生錯誤,就會回傳『錯誤代碼』纔對!通常就是以非爲 0 的數值來取代。 咱們以底下的例子來看看:

[root@linux ~]# echo $SHELL
/bin/bash
[root@linux ~]# echo $?
0
# 由於上個指令執行過程當中,並無錯誤,爲成功的執行完畢,因此回傳 0 。
[root@linux ~]# 12name=VBird
-bash: 12name=VBird: command not found
[root@linux ~]# echo $?
127
# 發生錯誤啦!因此 echo $? 時,就會出現錯誤的代碼!
# 咱們能夠利用這個代碼來搜尋錯誤的緣由喔!
[root@linux ~]# echo $?
0
# 咦!怎麼又變成正確了?這是由於 "?" 只與『上一個執行指令』有關,
# 因此,咱們上一個指令是執行『 echo $? 』,固然沒有錯誤,因此是 0 沒錯!

自定義變量轉成環境變量: export
如您想要讓該變量內容繼續的在子程序中使用,那麼就請執行:

export 變量

這個東西用在『引用他人的檔案或者其餘程序』時,至關的重要的! 尤爲像鳥哥經常兩三個檔案互相引用來引用去的,若是忘記設定 export 的話,那麼不一樣的檔案中的相同變量值,將須要一再地重複設定才行!因此,我只要在頭一個檔案使用 export 的話,那麼後續的檔案引用時,將會把該變量內容讀進來!好用的很,若是僅下達 export 而沒有接變量時,那麼此時將會把全部的『環境變量』秀出來喔!例如:

變量鍵盤讀取、數組與宣告: read, array, declare

[root@linux ~]# export
declare -x ENV="/root/.bashrc"
declare -x HISTSIZE="1000"
declare -x HOME="/root"
declare -x HOSTNAME="linux.dmtsai.tw"
declare -x INPUTRC="/etc/inputrc"
declare -x LANG="en_US.UTF-8"
declare -x MAIL="/var/spool/mail/root"
declare -x SHELL="/bin/bash"
# 不少都直接省略了!否則....重複性過高,浪費版面~ ^_^

額外的變量設定功能
剛剛咱們提到了兩種變量取用的方法,分別是這樣:

[root@linux ~]# echo $HOME
[root@linux ~]# echo ${HOME}

那麼,在那個 ${variable} 的使用方法中,其實,咱們還能夠將變量進行一些修訂的工做喔! 只要加上一些字符標誌,後面再接着使用比對字符串,就可以修改變量的內容了! 咱們取底下的例子來講明:在底下的例子中,假設個人變量名稱爲 vbird ,且內容爲 /home/vbird/testing/testing.x.sh。

二.經常使用命令

一、alias 別名

咱們能夠爲命令設置別名,已達到好記易輸入的效果,如清屏命令是clear,咱們可使其簡化爲clr, 查看目錄命令 ’ls -al | more‘能夠設置爲 lm,是否是很方便?

// 設置別名
alias clr='clear'
alias lm='ls -al | more'

// 取消別名
unalias clr

查看設置的別名

// 查看設置的別名
alias

clipboard.png

二、history

history 獲取輸入的歷史命令

// 查看全部的命令
history

// 查看最近輸入的命令前N條
history 5

clipboard.png

更多使用方法請看鳥哥私房菜文檔

3、通配符與特殊符號

在 bash 裏頭還支持一些通配符喔 (wild card) !多了這些通配符, 咱們利用 bash 處理數據就更方便了!底下咱們列出一些經常使用的通配符喔:

通配符
clipboard.png

組合鍵
clipboard.png

用法:

[root@linux ~]# ls test*      <==那個 * 表明後面不論接幾個字符都予以接受
[root@linux ~]# ls test?      <==那個 ? 表明後面『必定』要接『一個』字符
[root@linux ~]# ls test???    <==那個 ??? 表明『必定要接三個』字符!
[root@linux ~]# cp test[1-5] /tmp
# 將 test1, test2, test3, test4, test5 若存在的話,就拷貝到 /tmp 
[root@linux ~]# cp test[!1-5] /tmp
# 只要不是 test1, test2, test3, test4, test5 以外的其餘 test? ,
# 若存在的話,就拷貝到 /tmp 
[root@linux ~]# cd /lib/modules/`uname -r`/kernel/drivers
# 被 ` ` 括起來的內容『會先執行』

4、數據流重導向

數據流重導向 (redirect) 由字面上的意思來看,好像就是將『數據給他傳導到其餘地方去』的樣子? 呵呵!是啊是啊!沒錯~數據流重導向就是將某個指令執行後應該要出如今屏幕上的數據, 給他傳輸到其餘的地方,例如檔案或者是裝置 (例如打印機之類的!)!這玩意兒在 Linux 的文本模式底下可重要的! 尤爲是若是咱們想要將某些數據儲存下來時,就更有用了!

一、什麼是數據流重導向

好傢伙!什麼是數據流重導向啊?這得要由指令的執行結果談起! 通常來講,若是你要執行一個指令,一般他會是這樣的:
咱們執行一個指令的時候,這個指令可能會由檔案讀入資料,通過處理以後,再將數據輸出到屏幕上。 在圖三當中, standard output 與 standard error 分別表明標準輸出與標準錯誤輸出, 這兩個玩意兒默認都是輸出到屏幕上面來的啊!舉個簡單例子來講, 咱們下達『 cat /etc/crontab /etc/vbirdsay 』這個指令時,cat 會由 /etc/crontab 與 /etc/vbirdsay 讀入資料, 而後再將數據輸出到屏幕上,不過,由於系統原本就不存在 /etc/vbirdsay 這個檔案, 因此就會顯示錯誤訊息,這個錯誤訊息也會輸出到屏幕上來喔!

clipboard.png

在這樣的過程中,咱們能夠將 standard error (簡稱 stderr) 與 standard output (簡稱 stdout) 給他傳送到其餘不一樣的地方,而不是屏幕上頭!傳送的目標處,一般是檔案或者是裝置! 而傳送的指令則是以下所示:

標準輸入(stdin) :代碼爲 0 ,使用 < 或 << ;
標準輸出(stdout):代碼爲 1 ,使用 > 或 >> ;
標準錯誤輸出(stderr):代碼爲 2 ,使用 2> 或 2>> ;

舉例來講,若是我想要將我目前根目錄下全部的目錄都記錄下來的話,也就是說,將 ls -l / 這個指令的輸出結果儲存下來,就能夠:

[root@linux ~]# ls -l /  >  ~/rootfile
# 原本 ls -l / 會將根目錄的數據列出到屏幕上;
# 如今我使用了 > ~/rootfile 後,則原本應該在屏幕上出現的數據
# 就會被『從新導向』到 ~/rootfile 檔案內了!就能夠將該數據儲存!

此時,本來應該在屏幕上面出現的數據統統不見去~由於那些資料都被寫入到 ~/rootfile 去了! 固然,那個檔案的檔名隨便你取啦~若是你下達:『 cat ~/rootfile 』就能夠看到本來應該在屏幕上面的數據囉。 那麼若是我再次下達:『 ls -l /home > ~/rootfile 』後,那麼那個 ~/rootfile 檔案的內容變成什麼? 呵呵!變成『僅有 ls -l /home 的數據』而已!咦!本來的 ls -l / 數據就不見了嗎?是的! 由於該檔案的創建方式是:

  1. 該檔案 (本例中是 ~/rootfile) 若不存在,系統會自動的將他創建起來,可是,
  2. 當這個檔案存在的時候,那麼系統就會先將這個檔案內容清空,而後再將數據寫入!
  3. 也就是若以 > 輸出到一個既存盤案中,呵呵,那個檔案就會被覆蓋掉囉!

那若是我想要將數據累加,不想要將舊的數據刪除,那該如何是好? 呵呵!就利用 >> 就好啦!例如上面的例子中,就變成『ls -l / >> ~/rootfile』 如此一來,當 ~/rootfile 不存在時,系統會主動創建這個檔案,若該檔案已存在, 則數據會在該檔案的最下方累加進去!基本上,指令的下達方式:

>
              1>
command       2>    裝置或檔案
              2>>
              <

固然啦,一串指令的最左邊必定是指令,而在 >,2>,< 右邊的,必須是檔案或裝置才行! 此外,那個 > 會等於 1> ,由於 standard output 代碼是 1 ,能夠省略啦! 再者, 1 與 > 之間並無空格喔!是緊接在一塊兒的!注意注意!咱們底下來玩幾個東西好了:

範例一:將目前目錄下的檔案信息所有儲存到 list.txt 檔案中
[root@linux ~]# ls -al > list.txt

範例二:將根目錄下的數據也儲存到 list.txt 檔案中
[root@linux ~]# ls -al / >> list.txt

好了,對於『 > , >> 』這兩個東西有必定的概念以後,咱們來深刻的談一談『數據流重導向』的觀念吧! 如前所述,基本上, Linux 執行的結果中,能夠約略的分紅『正確輸出』與『錯誤輸出』兩種數據。 例如,當你以通常身份執行 find 這個指令時,例如執行『 find / -name testing 』時,因爲你是通常身份,又有些文件夾是不容許通常身份者進入的, 因此囉,當你使用 find 時,就會有錯誤訊息發生了!但同時若是有 testing 這個檔案在你能夠進入的文件夾當中,那麼屏幕也會輸出到給你看!所以, 就具備正確的與錯誤的輸出兩種囉!(分別稱爲 Stdout 與 Stderror)例以下面爲執行結果: 裏面的『 find: /home/root: Permission denied 』就告訴你該文件夾你沒有權限進入, 這就是錯誤的輸出了,那麼『 /home/dmtsai/tseting 』就是正確的輸出了!

[dmtsai@linux ~]$ find /home -name testing
find: /home/test1: Permission denied   <== Starndard error
find: /home/root: Permission denied    <== Starndard error
find: /home/masda: Permission denied   <== Starndard error
/home/dmtsai/testing                   <== Starndard output

好了,那麼假如咱們想要將數據輸出到 list 這個檔案中呢?執行『 find / -name testing > list 』 會有什麼結果?呵呵,你會發現 list 裏面存了剛剛那個『正確』的輸出數據, 至於屏幕上仍是會有錯誤的訊息出現呢!傷腦筋!若是想要將正確的與錯誤的數據分別存入不一樣的檔案中須要怎麼作?! 呵呵!其實在數據的重導向方面,正確的寫法應該是『 1> 』與『 2> 』纔對!可是若是隻有 > 則預設是以 1> 來進行數據的!那個 1> 是輸出正確數據, 2> 則是錯誤數據輸出項目。也就是說:

1> :是將正確的數據輸出到指定的地方去
2> :是將錯誤的數據輸出到指定的地方去

好了,那麼上面的例子中,咱們如何將數據輸出到不一樣的地方去呢?能夠這麼寫:

[dmtsai@linux ~]$ find /home -name testing > list_right 2> list_error

這樣一來,剛剛執行的結果中,有 Permission 的那幾行錯誤信息都會跑到 list_error 這個檔案中,至於正確的輸出數據則會存到 list_right 這個檔案中囉!這樣能夠了解了嗎? 若是有點混亂的話,去休息一下再來看看吧!!

再來,若是我只要正確的數據,錯誤的信息我不要了呢?呵呵,這個時候 /dev/null 這個垃圾桶就很重要了!/dev/null 是什麼呢? 基本上,那就有點像是一個『黑洞』的垃圾桶功能!當你輸入的任何東西導向到這個虛擬的垃圾桶裝置時, 『他就會憑空消失不見了~~』,這個東西有用的很!例如上面的例子中,咱們能夠這麼作,來將錯誤的信息丟掉!

[dmtsai@linux ~]$ find /home -name testing > list_right 2> /dev/null

很神奇呦! error message 就會『不見了!』呵呵!真高興!另外, 若是我要將數據都寫到同一個檔案中呢?這個時候寫法須要用到特殊寫法,請注意底下的寫法呦!

[dmtsai@linux ~]$ find /home -name testing > list 2> list  <==錯誤寫法
[dmtsai@linux ~]$ find /home -name testing > list 2>&1     <==正確寫法

請特別留意這一點呢!同時寫入同一個檔案須要使用 2>&1 纔對呦!

OK!瞭解了 >, 2>, >> 與 /dev/null 以後,那麼那個 < 又是什麼呀!?呵呵!以最簡單的說法來講, 那就是『將本來須要由鍵盤輸入的數據,經由檔案來讀入』的意思。 舉例來講,咱們可使用 cat 在鍵盤上面輸入一些數據,而後寫入一個檔案內,例如:

[root@linux ~]# cat > catfile
testing
cat file test
<==這裏按下 [ctrl]+d 結束輸入來離開!

此時就會有 catfile 這個檔案產生,並且該檔案的內容就是剛剛輸入的內容喔。 那麼,我是否可使用其餘檔案來取代鍵盤輸入呢?能夠啊!這樣作!

[root@linux ~]# cat > catfile < somefile

我能夠先編輯 somefile ,而後再以上述的指令來將數據輸出到 catfile 去呢!這樣能夠理解了嗎? 可以理解 < 以後,再來則是怪可怕一把的 << 這個連續兩個小於的符號了~ 他表明的是『結束的輸入字符』的意思!舉例來說:『我要用 cat 直接將輸入的訊息輸出到 catfile 中, 且當輸入 eof 時,該次輸入就結束』,那我能夠這樣作:

[root@linux ~]# cat > catfile <<eof
> This is a test testing
> OK now stop
> eof  <==輸入這個玩意兒,嘿!馬上就結束了!

看到了嗎?利用 << 右側的控制字符,咱們能夠終止一次輸入, 而沒必要輸入 [crtl]+d 來結束哩!這對程序寫做頗有幫助喔!好了,那麼爲什麼要使用命令輸出重導向呢? 這個問題必定會困擾你一下下的,若是你歷來都沒有寫過 script 的話!好了,咱們來講一說吧!

1.當屏幕輸出的信息很重要,並且咱們須要將他存下來的時候;
2.背景執行中的程序,不但願他干擾屏幕正常的輸出結果時;
3.一些系統的例行命令(例如寫在 /etc/crontab 中的檔案)的執行結果,但願他能夠存下來時;
4.一些執行命令,咱們已經知道他可能的錯誤訊息,因此想以『 2> /dev/null 』將他丟掉時;
5.錯誤訊息與正確訊息須要分別輸出時。

固然還有不少不少的功能的,最簡單的就是網友們經常問到的:『 爲什麼個人 root 都會收到系統 crontab 寄來的錯誤訊息呢』這個咚咚是常見的錯誤, 而若是咱們已經知道這個錯誤訊息是能夠忽略的時候,嗯!『 2> errorfile 』這個功能就很重要了吧! 瞭解了嗎??

小結: > 表示覆蓋 >>表示累加

5、命令執行的判斷依據: ; , &&, ||

在某些時候,咱們但願能夠一次執行多個指令,例如關機時,但願我能夠先執行兩次 sync ,而後才 shutdown 計算機,那麼能夠怎麼做呢?這樣作呀:

[root@linux ~]# sync; sync; shutdown -h now

在指令與指令中間利用分號 (;) 來隔開,這樣一來,分號前的指令執行完後, 就會馬上接着執行後面的指令了。

// 當前面的指令執行結果爲正確 (例如:僅有 standard output 時),就能夠接着執行後續的指令, 不然就予以略過
[root@linux ~]# ls /vbird && touch /vbird/test

// 若是我想要當某個檔案不存在時,就去創建那個檔案, 不然就略過呢?很簡單啊~能夠這樣作:
[root@linux ~]# ls /tmp/vbirding || touch /tmp/vbirding

因爲指令是一個接着一個去執行的,所以,若是真要使用判斷, 那麼這個 && 與 || 的順序就不能搞錯~通常來講,判斷式最多會有三個,也就是:

command1 && command2 || command3

6、管線命令 (pipe)

就如同前面所說的, bash 命令執行的時候有輸出的數據會出現! 那麼若是這羣數據必須要通過幾道手續以後才能獲得咱們所想要的格式,應該如何來設定? 這就牽涉到管線命令的問題了 (pipe) ,管線命令使用的是『 | 』這個界定符號! 另外,管線命令與『連續下達命令』是不同的呦! 這點底下咱們會再說明。底下咱們先舉一個例子來講明一下簡單的管線命令。

假設咱們想要知道 /etc/ 底下有多少檔案,那麼能夠利用 ls /etc 來查閱,不過, 由於 /etc 底下的檔案太多,致使一口氣就將屏幕塞滿了~不知道前面輸出的內容是啥?此時,咱們能夠透過 less 指令的協助,利用:

[root@linux ~]# ls -al /etc | less

7、Shell scripts

一、什麼是Shell scripts

什麼是 shell script (程序化腳本) 呢?就字面上的意義,咱們將他分爲兩部份。 在『 shell 』部分,咱們在 十一章的 BASH 當中已經提過了,那是一個文字介面底下讓咱們與系統溝通的一個工具介面。那麼『 script 』是啥? 字面上的意義, script 是『腳本、劇本』的意思。整句話是說, shell script 是針對 shell 所寫的『劇本!』。

Shell script 是利用 shell 的功能所寫的一個『程序 (program)』,這個程序是使用純文字檔,將一些 shell 的語法與命令(含外部命令)寫在裏面, 搭配正規表示法、管線命令與數據流重導向等功能,以達到咱們所想要的處理目的。

二、爲何學習Shell scripts

  1. 自動化管理的重要依據:
  2. 追蹤與管理系統的重要工做:
  3. 簡單入侵偵測功能:
  4. 連續命令單一化:
  5. 簡易的數據處理:
  6. 跨平臺支持與學習歷程較短:

三、第一個script的編寫及運行

script其實就是多個命令的批處理,要下達命令就要注意如下事項:

1.命令的運行是從上而下、從左而右的分析與運行;
2.命令的下達就如同第五章內提到的: 命令、選項與參數間的多個空白都會被忽略掉;
3.空白行也將被忽略掉,而且 [tab] 按鍵所推開的空白一樣視爲空白鍵;
4.若是讀取到一個 Enter 符號 (CR) ,就嘗試開始運行該行 (或該串) 命令;
5.至於若是一行的內容太多,則可使用『 [Enter] 』來延伸至下一行;
6.『 # 』可作爲註解!任何加在 # 後面的數據將所有被視爲註解文字而被忽略!

運行script:

直接命令下達: shell.sh 文件必需要具有可讀與可運行 (rx) 的權限,而後:
絕對路徑:使用 /home/dmtsai/shell.sh 來下達命令;
相對路徑:假設工做目錄在 /home/dmtsai/ ,則使用 ./shell.sh 來運行
變量『PATH』功能:將 shell.sh 放在 PATH 指定的目錄內,例如: ~/bin/

以 bash 程序來運行:透過『 bash shell.sh 』或『 sh shell.sh 』來運行

四、撰寫第一支 script

[root@www ~]# mkdir scripts; cd scripts
[root@www scripts]# vi sh01.sh
#!/bin/bash
# Program:
#       This program shows "Hello World!" in your screen.
# History:
# 2005/08/23    VBird    First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
echo -e "Hello World! \a \n"
exit 0

clipboard.png
注:請將全部撰寫的 script 放置到你家目錄的 ~/scripts 這個目錄內, 將來比較好管理啦!

腳本說明:

  1. 第一行 #!/bin/bash 在宣告這個 script 使用的 shell 名稱:
    由於咱們使用的是 bash ,因此,必需要以『 #!/bin/bash 』來宣告這個文件內的語法使用 bash 的語法!那麼當這個程序被運行時,他就可以加載 bash 的相關環境配置檔 (通常來講就是 non-login shell 的 ~/.bashrc), 而且運行 bash 來使咱們底下的命令可以運行!這很重要的!(在不少情況中,若是沒有配置好這一行, 那麼該程序極可能會沒法運行,由於系統可能沒法判斷該程序須要使用什麼 shell 來運行啊!)
  2. 程序內容的說明:
    整個 script 當中,除了第一行的『 #! 』是用來宣告 shell 的以外,其餘的 # 都是『註解』用途! 因此上面的程序當中,第二行如下就是用來講明整個程序的基本數據。通常來講, 建議你必定要養成說明該 script 的:1. 內容與功能; 2. 版本資訊; 3. 做者與聯絡方式; 4. 建檔日期;5. 歷史紀錄 等等。這將有助於將來程序的改寫與 debug 呢!
  3. 主要環境變量的宣告:
    建議務必要將一些重要的環境變量配置好,鳥哥我的認爲, PATH 與 LANG (若是有使用到輸出相關的資訊時) 是當中最重要的! 如此一來,則可以讓咱們這支程序在進行時,能夠直接下達一些外部命令,而沒必要寫絕對路徑呢!比較好啦!
  4. 主要程序部分
  5. 運行成果告知 (定義回傳值)
    是否記得咱們在第十一章裏面要討論一個命令的運行成功與否,可使用 $? 這個變量來觀察~ 那麼咱們也能夠利用 exit 這個命令來讓程序中斷,而且回傳一個數值給系統。 在咱們這個例子當中,鳥哥使用 exit 0 ,這表明離開 script 而且回傳一個 0 給系統, 因此我運行完這個 script 後,若接著下達 echo $? 則可獲得 0 的值喔! 更聰明的讀者應該也知道了,呵呵!利用這個 exit n (n 是數字) 的功能,咱們還能夠自訂錯誤信息, 讓這支程序變得更加的 smart 呢!

運行結果:

clipboard.png

或者你也能夠利用:『chmod a+x sh01.sh; ./sh01.sh』來運行這個 script 的呢!

五、撰寫 shell script 的良好習慣建立

建議你必定要養成良好的 script 撰寫習慣,在每一個 script 的檔頭處記錄好:

  • script 的功能;
  • script 的版本資訊;
  • script 的做者與聯絡方式;
  • script 的版權宣告方式;
  • script 的 History (歷史紀錄);
  • script 內較特殊的命令,使用『絕對路徑』的方式來下達;
  • script 運行時須要的環境變量預先宣告與配置。

併發測試
使用curl模擬併發請求網頁

test.sh

#!/bin/bash

#betin time
begin=$(date +%s)

#批量處理
count=100
for(( i = 0; i < $count; i++ ))
do
{
  /usr/bin/curl http://172.18.82.21/xampps/web/login_test/index.php
}&
done

#結束時間
end=$(date +%s)
spend=$(expr $end - $begin)
echo "花費時間爲$spend秒"

執行腳本

// 執行腳本
> bash test.sh
相關文章
相關標籤/搜索