## 12.4 條件判斷式
只要講到“程序”的話,那么條件判斷式,亦即是“ if then ”這種判別式肯定一定要學習的! 因為很多時候,我們都必須要依據某些數據來判斷程序該如何進行。舉例來說,我們在上頭的 [ans_yn.sh](../Text/index.html#sh06) 討論輸入回應的范例中不是有練習當使用者輸入 Y/N 時,必須要執行不同的訊息輸出嗎?簡單的方式可以利用 && 與 || ,但如果我還想要執行一堆指令呢?那真的得要 if then 來幫忙啰~下面我們就來聊一聊!
### 12.4.1 利用 if .... then
這個 if .... then 是最常見的條件判斷式了~簡單的說,就是當符合某個條件判斷的時候, 就予以進行某項工作就是了。這個 if ... then 的判斷還有多層次的情況!我們分別介紹如下:
* 單層、簡單條件判斷式
如果你只有一個判斷式要進行,那么我們可以簡單的這樣看:
```
if [ 條件判斷式 ]; then
當條件判斷式成立時,可以進行的指令工作內容;
fi <==將 if 反過來寫,就成為 fi 啦!結束 if 之意!
```
至于條件判斷式的判斷方法,與前一小節的介紹相同啊!較特別的是,如果我有多個條件要判別時, 除了 [ans_yn.sh](../Text/index.html#sh06) 那個案例所寫的,也就是“將多個條件寫入一個中括號內的情況”之外, 我還可以有多個中括號來隔開喔!而括號與括號之間,則以 && 或 || 來隔開,他們的意義是:
* && 代表 AND ;
* || 代表 or ;
所以,在使用中括號的判斷式中, && 及 || 就與指令下達的狀態不同了。舉例來說, ans_yn.sh 里面的判斷式可以這樣修改:
> [ "${yn}" == "Y" -o "${yn}" == "y" ]
> 上式可替換為
> [ "${yn}" == "Y" ] || [ "${yn}" == "y" ]
之所以這樣改,很多人是習慣問題!很多人則是喜歡一個中括號僅有一個判別式的原因。好了, 現在我們來將 ans_yn.sh 這個腳本修改成為 if ... then 的樣式來看看:
```
[dmtsai@study bin]$ cp ans_yn.sh ans_yn-2.sh <==用復制來修改的比較快!
[dmtsai@study bin]$ vim ans_yn-2.sh
#!/bin/bash
# Program:
# This program shows the user's choice
# History:
# 2015/07/16 VBird First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
read -p "Please input (Y/N): " yn
if [ "${yn}" == "Y" ] || [ "${yn}" == "y" ]; then
echo "OK, continue"
exit 0
fi
if [ "${yn}" == "N" ] || [ "${yn}" == "n" ]; then
echo "Oh, interrupt!"
exit 0
fi
echo "I don't know what your choice is" && exit 0
```
不過,由這個例子看起來,似乎也沒有什么了不起吧?原本的 ans_yn.sh 還比較簡單呢~ 但是如果以邏輯概念來看,其實上面的范例中,我們使用了兩個條件判斷呢!明明僅有一個 ${yn} 的變量,為何需要進行兩次比對呢? 此時,多重條件判斷就能夠來測試測試啰!
* 多重、復雜條件判斷式
在同一個數據的判斷中,如果該數據需要進行多種不同的判斷時,應該怎么作?舉例來說,上面的 [ans_yn.sh](../Text/index.html#sh06) 腳本中,我們只要進行一次 ${yn} 的判斷就好 (僅進行一次 if ),不想要作多次 if 的判斷。 此時你就得要知道下面的語法了:
```
# 一個條件判斷,分成功進行與失敗進行 (else)
if [ 條件判斷式 ]; then
當條件判斷式成立時,可以進行的指令工作內容;
else
當條件判斷式不成立時,可以進行的指令工作內容;
fi
```
如果考慮更復雜的情況,則可以使用這個語法:
```
# 多個條件判斷 (if ... elif ... elif ... else) 分多種不同情況執行
if [ 條件判斷式一 ]; then
當條件判斷式一成立時,可以進行的指令工作內容;
elif [ 條件判斷式二 ]; then
當條件判斷式二成立時,可以進行的指令工作內容;
else
當條件判斷式一與二均不成立時,可以進行的指令工作內容;
fi
```
你得要注意的是, elif 也是個判斷式,因此出現 elif 后面都要接 then 來處理!但是 else 已經是最后的沒有成立的結果了, 所以 else 后面并沒有 then 喔!好!我們來將 ans_yn-2.sh 改寫成這樣:
```
[dmtsai@study bin]$ cp ans_yn-2.sh ans_yn-3.sh
[dmtsai@study bin]$ vim ans_yn-3.sh
#!/bin/bash
# Program:
# This program shows the user's choice
# History:
# 2015/07/16 VBird First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
read -p "Please input (Y/N): " yn
if [ "${yn}" == "Y" ] || [ "${yn}" == "y" ]; then
echo "OK, continue"
elif [ "${yn}" == "N" ] || [ "${yn}" == "n" ]; then
echo "Oh, interrupt!"
else
echo "I don't know what your choice is"
fi
```
是否程序變得很簡單,而且依序判斷,可以避免掉重復判斷的狀況,這樣真的很容易設計程序的啦! ^_^! 好了,讓我們再來進行另外一個案例的設計。一般來說,如果你不希望使用者由鍵盤輸入額外的數據時, 可以使用[上一節提到的參數功能 ($1)](../Text/index.html#dis3)!讓使用者在下達指令時就將參數帶進去! 現在我們想讓使用者輸入“ hello ”這個關鍵字時,利用參數的方法可以這樣依序設計:
1. 判斷 $1 是否為 hello,如果是的話,就顯示 "Hello, how are you ?";
2. 如果沒有加任何參數,就提示使用者必須要使用的參數下達法;
3. 而如果加入的參數不是 hello ,就提醒使用者僅能使用 hello 為參數。
整個程序的撰寫可以是這樣的:
```
[dmtsai@study bin]$ vim hello-2.sh
#!/bin/bash
# Program:
# Check $1 is equal to "hello"
# History:
# 2015/07/16 VBird First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
if [ "${1}" == "hello" ]; then
echo "Hello, how are you ?"
elif [ "${1}" == "" ]; then
echo "You MUST input parameters, ex> {${0} someword}"
else
echo "The only parameter is 'hello', ex> {${0} hello}"
fi
```
然后你可以執行這支程序,分別在 $1 的位置輸入 hello, 沒有輸入與隨意輸入, 就可以看到不同的輸出啰~是否還覺得挺簡單的啊! ^_^。事實上, 學到這里,也真的很厲害了~好了,下面我們繼續來玩一些比較大一點的計劃啰~
我們在第十章已經學會了 [grep](../Text/index.html#grep) 這個好用的玩意兒,那么多學一個叫做 netstat 的指令,這個指令可以查詢到目前主機有打開的網絡服務端口 (service ports), 相關的功能我們會在[服務器架設篇](http://linux.vbird.org/linux_server)繼續介紹,這里你只要知道,我可以利用“ netstat -tuln ”來取得目前主機有啟動的服務, 而且取得的信息有點像這樣:
```
[dmtsai@study ~]$ netstat -tuln
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN
tcp6 0 0 :::22 :::* LISTEN
tcp6 0 0 ::1:25 :::* LISTEN
udp 0 0 0.0.0.0:123 0.0.0.0:*
udp 0 0 0.0.0.0:5353 0.0.0.0:*
udp 0 0 0.0.0.0:44326 0.0.0.0:*
udp 0 0 127.0.0.1:323 0.0.0.0:*
udp6 0 0 :::123 :::*
udp6 0 0 ::1:323 :::*
#封包格式 本地IP:端口 遠端IP:端口 是否監聽
```
上面的重點是“Local Address (本地主機的IP與端口對應)”那個字段,他代表的是本機所啟動的網絡服務! IP的部分說明的是該服務位于那個接口上,若為 127.0.0.1 則是僅針對本機開放,若是 0.0.0.0 或 ::: 則代表對整個 Internet 開放 (更多信息請參考服務器架設篇的介紹)。 每個端口 (port) 都有其特定的網絡服務,幾個常見的 port 與相關網絡服務的關系是:
* 80: WWW
* 22: ssh
* 21: ftp
* 25: mail
* 111: RPC(遠端程序調用)
* 631: CUPS(打印服務功能)
假設我的主機有興趣要偵測的是比較常見的 port 21, 22, 25及 80 時,那我如何通過 netstat 去偵測我的主機是否有打開這四個主要的網絡服務端口呢?由于每個服務的關鍵字都是接在冒號“ : ”后面, 所以可以借由擷取類似“ :80 ”來偵測的!那我就可以簡單的這樣去寫這個程序喔:
```
[dmtsai@study bin]$ vim netstat.sh
#!/bin/bash
# Program:
# Using netstat and grep to detect WWW,SSH,FTP and Mail services.
# History:
# 2015/07/16 VBird First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
# 1\. 先作一些告知的動作而已~
echo "Now, I will detect your Linux server's services!"
echo -e "The www, ftp, ssh, and mail(smtp) will be detect! \n"
# 2\. 開始進行一些測試的工作,并且也輸出一些信息啰!
testfile=/dev/shm/netstat_checking.txt
netstat -tuln > ${testfile} # 先轉存數據到內存當中!不用一直執行 netstat
testing=$(grep ":80 " ${testfile}) # 偵測看 port 80 在否?
if [ "${testing}" != "" ]; then
echo "WWW is running in your system."
fi
testing=$(grep ":22 " ${testfile}) # 偵測看 port 22 在否?
if [ "${testing}" != "" ]; then
echo "SSH is running in your system."
fi
testing=$(grep ":21 " ${testfile}) # 偵測看 port 21 在否?
if [ "${testing}" != "" ]; then
echo "FTP is running in your system."
fi
testing=$(grep ":25 " ${testfile}) # 偵測看 port 25 在否?
if [ "${testing}" != "" ]; then
echo "Mail is running in your system."
fi
```
實際執行這支程序你就可以看到你的主機有沒有啟動這些服務啦!是否很有趣呢? 條件判斷式還可以搞的更復雜!舉例來說,在臺灣當兵是國民應盡的義務,不過,在當兵的時候總是很想要退伍的! 那你能不能寫個腳本程序來跑,讓使用者輸入他的退伍日期,讓你去幫他計算還有幾天才退伍?
由于日期是要用相減的方式來處置,所以我們可以通過使用 date 顯示日期與時間,將他轉為由 1970-01-01 累積而來的秒數, 通過秒數相減來取得剩余的秒數后,再換算為日數即可。整個腳本的制作流程有點像這樣:
1. 先讓使用者輸入他們的退伍日期;
2. 再由現在日期比對退伍日期;
3. 由兩個日期的比較來顯示“還需要幾天”才能夠退伍的字樣。
似乎挺難的樣子?其實也不會啦,利用“ date --date="YYYYMMDD" +%s ”轉成秒數后,接下來的動作就容易的多了!如果你已經寫完了程序,對照下面的寫法試看看:
```
[dmtsai@study bin]$ vim cal_retired.sh
#!/bin/bash
# Program:
# You input your demobilization date, I calculate how many days before you demobilize.
# History:
# 2015/07/16 VBird First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
# 1\. 告知使用者這支程序的用途,并且告知應該如何輸入日期格式?
echo "This program will try to calculate :"
echo "How many days before your demobilization date..."
read -p "Please input your demobilization date (YYYYMMDD ex>20150716): " date2
# 2\. 測試一下,這個輸入的內容是否正確?利用正則表達式啰~
date_d=$(echo ${date2} |grep '[0-9]\{8\}') # 看看是否有八個數字
if [ "${date_d}" == "" ]; then
echo "You input the wrong date format...."
exit 1
fi
# 3\. 開始計算日期啰~
declare -i date_dem=$(date --date="${date2}" +%s) # 退伍日期秒數
declare -i date_now=$(date +%s) # 現在日期秒數
declare -i date_total_s=$((${date_dem}-${date_now})) # 剩余秒數統計
declare -i date_d=$((${date_total_s}/60/60/24)) # 轉為日數
if [ "${date_total_s}" -lt "0" ]; then # 判斷是否已退伍
echo "You had been demobilization before: " $((-1*${date_d})) " ago"
else
declare -i date_h=$(($((${date_total_s}-${date_d}*60*60*24))/60/60))
echo "You will demobilize after ${date_d} days and ${date_h} hours."
fi
```
瞧一瞧,這支程序可以幫你計算退伍日期呢~如果是已經退伍的朋友, 還可以知道已經退伍多久了~哈哈!很可愛吧~腳本中的 date_d 變量宣告那個 /60/60/24 是來自于一天的總秒數 (24小時*60分*60秒) 。瞧~全部的動作都沒有超出我們所學的范圍吧~ ^_^ 還能夠避免使用者輸入錯誤的數字,所以多了一個正則表達式的判斷式呢~ 這個例子比較難,有興趣想要一探究竟的朋友,可以作一下[課后練習題](../Text/index.html#ex) 關于計算生日的那一題喔!~加油!
### 12.4.2 利用 case ..... esac 判斷
上個小節提到的“ if .... then .... fi ”對于變量的判斷是以“比對”的方式來分辨的, 如果符合狀態就進行某些行為,并且通過較多層次 (就是 elif ...) 的方式來進行多個變量的程序碼撰寫,譬如 [hello-2.sh](../Text/index.html#check_1) 那個小程序,就是用這樣的方式來撰寫的啰。 好,那么萬一我有多個既定的變量內容,例如 hello-2.sh 當中,我所需要的變量就是 "hello" 及空字串兩個, 那么我只要針對這兩個變量來設置狀況就好了,對吧?那么可以使用什么方式來設計呢?呵呵~就用 case ... in .... esac 吧~,他的語法如下:
```
case $變量名稱 in <==關鍵字為 case ,還有變量前有錢字號
"第一個變量內容") <==每個變量內容建議用雙引號括起來,關鍵字則為小括號 )
程序段
;; <==每個類別結尾使用兩個連續的分號來處理!
"第二個變量內容")
程序段
;;
*) <==最后一個變量內容都會用 * 來代表所有其他值
不包含第一個變量內容與第二個變量內容的其他程序執行段
exit 1
;;
esac <==最終的 case 結尾!“反過來寫”思考一下!
```
要注意的是,這個語法以 case (實際案例之意) 為開頭,結尾自然就是將 case 的英文反過來寫!就成為 esac 啰! 不會很難背啦!另外,每一個變量內容的程序段最后都需要兩個分號 (;;) 來代表該程序段落的結束,這挺重要的喔! 至于為何需要有 * 這個變量內容在最后呢?這是因為,如果使用者不是輸入變量內容一或二時, 我們可以告知使用者相關的信息啊!廢話少說,我們拿 hello-2.sh 的案例來修改一下,他應該會變成這樣喔:
```
[dmtsai@study bin]$ vim hello-3.sh
#!/bin/bash
# Program:
# Show "Hello" from $1.... by using case .... esac
# History:
# 2015/07/16 VBird First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
case ${1} in
"hello")
echo "Hello, how are you ?"
;;
"")
echo "You MUST input parameters, ex> {${0} someword}"
;;
*) # 其實就相當于萬用字符,0~無窮多個任意字符之意!
echo "Usage ${0} {hello}"
;;
esac
```
在上面這個 hello-3.sh 的案例當中,如果你輸入“ sh hello-3.sh test ”來執行, 那么屏幕上就會出現“Usage hello-3.sh {hello}”的字樣,告知執行者僅能夠使用 hello 喔~ 這樣的方式對于需要某些固定字串來執行的變量內容就顯的更加的方便呢! 這種方式你真的要熟悉喔!這是因為早期系統的很多服務的啟動 scripts 都是使用這種寫法的 (CentOS 6.x 以前)。 雖然 CentOS 7 已經使用 systemd,不過仍有數個服務是放在 /etc/init.d/ 目錄下喔!例如有個名為 netconsole 的服務在該目錄下, 那么你想要重新啟動該服務,是可以這樣做的 (請注意,要成功執行,還是得要具有 root 身份才行!一般帳號能執行,但不會成功!):
> /etc/init.d/netconsole restart
重點是那個 restart 啦!如果你使用“ less /etc/init.d/netconsole ”去查閱一下,就會看到他使用的是 case 語法, 并且會規定某些既定的變量內容,你可以直接下達 /etc/init.d/netconsole , 該 script 就會告知你有哪些后續接的變量可以使用啰~方便吧! ^_^
一般來說,使用“ case $變量 in ”這個語法中,當中的那個“ $變量 ”大致有兩種取得的方式:
* 直接下達式:例如上面提到的,利用“ script.sh variable ” 的方式來直接給予 $1 這個變量的內容,這也是在 /etc/init.d 目錄下大多數程序的設計方式。
* 互動式:通過 read 這個指令來讓使用者輸入變量的內容。
這么說或許你的感受性還不高,好,我們直接寫個程序來玩玩:讓使用者能夠輸入 one, two, three , 并且將使用者的變量顯示到屏幕上,如果不是 one, two, three 時,就告知使用者僅有這三種選擇。
```
[dmtsai@study bin]$ vim show123.sh
#!/bin/bash
# Program:
# This script only accepts the flowing parameter: one, two or three.
# History:
# 2015/07/17 VBird First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
echo "This program will print your selection !"
# read -p "Input your choice: " choice # 暫時取消,可以替換!
# case ${choice} in # 暫時取消,可以替換!
case ${1} in # 現在使用,可以用上面兩行替換!
"one")
echo "Your choice is ONE"
;;
"two")
echo "Your choice is TWO"
;;
"three")
echo "Your choice is THREE"
;;
*)
echo "Usage ${0} {one|two|three}"
;;
esac
```
此時,你可以使用“ sh show123.sh two ”的方式來下達指令,就可以收到相對應的回應了。 上面使用的是直接下達的方式,而如果使用的是互動式時,那么將上面第 10, 11 行的 "#" 拿掉, 并將 12 行加上注解 (#),就可以讓使用者輸入參數啰~這樣是否很有趣啊?
### 12.4.3 利用 function 功能
什么是“函數 (function)”功能啊?簡單的說,其實, 函數可以在 shell script 當中做出一個類似自訂執行指令的東西,最大的功能是, 可以簡化我們很多的程序碼~舉例來說,上面的 show123.sh 當中,每個輸入結果 one, two, three 其實輸出的內容都一樣啊~那么我就可以使用 function 來簡化了! function 的語法是這樣的:
```
function fname() {
程序段
}
```
那個 fname 就是我們的自訂的執行指令名稱~而程序段就是我們要他執行的內容了。 要注意的是,因為 shell script 的執行方式是由上而下,由左而右, 因此在 shell script 當中的 function 的設置一定要在程序的最前面, 這樣才能夠在執行時被找到可用的程序段喔 (這一點與傳統程序語言差異相當大!初次接觸的朋友要小心!)! 好~我們將 show123.sh 改寫一下,自訂一個名為 printit 的函數來使用喔:
```
[dmtsai@study bin]$ vim show123-2.sh
#!/bin/bash
# Program:
# Use function to repeat information.
# History:
# 2015/07/17 VBird First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
function printit(){
echo -n "Your choice is " # 加上 -n 可以不斷行繼續在同一行顯示
}
echo "This program will print your selection !"
case ${1} in
"one")
**printit**; echo ${1} | tr 'a-z' 'A-Z' # 將參數做大小寫轉換!
;;
"two")
**printit**; echo ${1} | tr 'a-z' 'A-Z'
;;
"three")
**printit**; echo ${1} | tr 'a-z' 'A-Z'
;;
*)
echo "Usage ${0} {one|two|three}"
;;
esac
```
以上面的例子來說,鳥哥做了一個函數名稱為 printit ,所以,當我在后續的程序段里面, 只要執行 printit 的話,就表示我的 shell script 要去執行“ function printit .... ” 里面的那幾個程序段落啰!當然啰,上面這個例子舉得太簡單了,所以你不會覺得 function 有什么好厲害的, 不過,如果某些程序碼一再地在 script 當中重復時,這個 function 可就重要的多啰~ 不但可以簡化程序碼,而且可以做成類似“模塊”的玩意兒,真的很棒啦!

**Tips** 建議讀者可以使用類似 vim 的編輯器到 /etc/init.d/ 目錄下去查閱一下你所看到的文件, 并且自行追蹤一下每個文件的執行情況,相信會更有心得!
另外, function 也是擁有內置變量的~他的內置變量與 shell script 很類似, 函數名稱代表示 $0 ,而后續接的變量也是以 $1, $2... 來取代的~ 這里很容易搞錯喔~因為“ function fname() { 程序段 } ”內的 $0, $1... 等等與 shell script 的 $0 是不同的。以上面 show123-2.sh 來說,假如我下達:“ sh show123-2.sh one ” 這表示在 shell script 內的 $1 為 "one" 這個字串。但是在 printit() 內的 $1 則與這個 one 無關。 我們將上面的例子再次的改寫一下,讓你更清楚!
```
[dmtsai@study bin]$ vim show123-3.sh
#!/bin/bash
# Program:
# Use function to repeat information.
# History:
# 2015/07/17 VBird First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
function printit(){
echo "Your choice is ${1}" # 這個 $1 必須要參考下面指令的下達
}
echo "This program will print your selection !"
case ${1} in
"one")
**printit 1** # 請注意, printit 指令后面還有接參數!
;;
"two")
**printit 2**
;;
"three")
**printit 3**
;;
*)
echo "Usage ${0} {one|two|three}"
;;
esac
```
在上面的例子當中,如果你輸入“ sh show123-3.sh one ”就會出現“ Your choice is 1 ”的字樣~ 為什么是 1 呢?因為在程序段落當中,我們是寫了“ printit 1 ”那個 1 就會成為 function 當中的 $1 喔~ 這樣是否理解呢? function 本身其實比較困難一點,如果你還想要進行其他的撰寫的話。 不過,我們僅是想要更加了解 shell script 而已,所以,這里看看即可~了解原理就好啰~ ^_^
- 鳥哥的Linux私房菜:基礎學習篇 第四版
- 目錄及概述
- 第零章、計算機概論
- 0.1 電腦:輔助人腦的好工具
- 0.2 個人電腦架構與相關設備元件
- 0.3 數據表示方式
- 0.4 軟件程序運行
- 0.5 重點回顧
- 0.6 本章習題
- 0.7 參考資料與延伸閱讀
- 第一章、Linux是什么與如何學習
- 1.1 Linux是什么
- 1.2 Torvalds的Linux發展
- 1.3 Linux當前應用的角色
- 1.4 Linux 該如何學習
- 1.5 重點回顧
- 1.6 本章習題
- 1.7 參考資料與延伸閱讀
- 第二章、主機規劃與磁盤分區
- 2.1 Linux與硬件的搭配
- 2.2 磁盤分區
- 2.3 安裝Linux前的規劃
- 2.4 重點回顧
- 2.5 本章習題
- 2.6 參考資料與延伸閱讀
- 第三章、安裝 CentOS7.x
- 3.1 本練習機的規劃--尤其是分區參數
- 3.2 開始安裝CentOS 7
- 3.3 多重開機安裝流程與管理(Option)
- 3.4 重點回顧
- 3.5 本章習題
- 3.6 參考資料與延伸閱讀
- 第四章、首次登陸與線上求助
- 4.1 首次登陸系統
- 4.2 文字模式下指令的下達
- 4.3 Linux系統的線上求助man page與info page
- 4.4 超簡單文書編輯器: nano
- 4.5 正確的關機方法
- 4.6 重點回顧
- 4.7 本章習題
- 4.8 參考資料與延伸閱讀
- 第五章、Linux 的文件權限與目錄配置
- 5.1 使用者與群組
- 5.2 Linux 文件權限概念
- 5.3 Linux目錄配置
- 5.4 重點回顧
- 5.5 本章練習
- 5.6 參考資料與延伸閱讀
- 第六章、Linux 文件與目錄管理
- 6.1 目錄與路徑
- 6.2 文件與目錄管理
- 6.3 文件內容查閱
- 6.4 文件與目錄的默認權限與隱藏權限
- 6.5 指令與文件的搜尋
- 6.6 極重要的復習!權限與指令間的關系
- 6.7 重點回顧
- 6.8 本章習題:
- 6.9 參考資料與延伸閱讀
- 第七章、Linux 磁盤與文件系統管理
- 7.1 認識 Linux 文件系統
- 7.2 文件系統的簡單操作
- 7.3 磁盤的分區、格式化、檢驗與掛載
- 7.4 設置開機掛載
- 7.5 內存交換空間(swap)之創建
- 7.6 文件系統的特殊觀察與操作
- 7.7 重點回顧
- 7.8 本章習題 - 第一題一定要做
- 7.9 參考資料與延伸閱讀
- 第八章、文件與文件系統的壓縮,打包與備份
- 8.1 壓縮文件的用途與技術
- 8.2 Linux 系統常見的壓縮指令
- 8.3 打包指令: tar
- 8.4 XFS 文件系統的備份與還原
- 8.5 光盤寫入工具
- 8.6 其他常見的壓縮與備份工具
- 8.7 重點回顧
- 8.8 本章習題
- 8.9 參考資料與延伸閱讀
- 第九章、vim 程序編輯器
- 9.1 vi 與 vim
- 9.2 vi 的使用
- 9.3 vim 的額外功能
- 9.4 其他 vim 使用注意事項
- 9.5 重點回顧
- 9.6 本章練習
- 9.7 參考資料與延伸閱讀
- 第十章、認識與學習BASH
- 10.1 認識 BASH 這個 Shell
- 10.2 Shell 的變量功能
- 10.3 命令別名與歷史命令
- 10.4 Bash Shell 的操作環境:
- 10.5 數據流重導向
- 10.6 管線命令 (pipe)
- 10.7 重點回顧
- 10.8 本章習題
- 10.9 參考資料與延伸閱讀
- 第十一章、正則表達式與文件格式化處理
- 11.1 開始之前:什么是正則表達式
- 11.2 基礎正則表達式
- 11.3 延伸正則表達式
- 11.4 文件的格式化與相關處理
- 11.5 重點回顧
- 11.6 本章習題
- 11.7 參考資料與延伸閱讀
- 第十二章、學習 Shell Scripts
- 12.1 什么是 Shell scripts
- 12.2 簡單的 shell script 練習
- 12.3 善用判斷式
- 12.4 條件判斷式
- 12.5 循環 (loop)
- 12.6 shell script 的追蹤與 debug
- 12.7 重點回顧
- 12.8 本章習題
- 第十三章、Linux 帳號管理與 ACL 權限設置
- 13.1 Linux 的帳號與群組
- 13.2 帳號管理
- 13.3 主機的細部權限規劃:ACL 的使用
- 13.4 使用者身份切換
- 13.5 使用者的特殊 shell 與 PAM 模塊
- 13.6 Linux 主機上的使用者訊息傳遞
- 13.7 CentOS 7 環境下大量創建帳號的方法
- 13.8 重點回顧
- 13.9 本章習題
- 13.10 參考資料與延伸閱讀
- 第十四章、磁盤配額(Quota)與進階文件系統管理
- 14.1 磁盤配額 (Quota) 的應用與實作
- 14.2 軟件磁盤陣列 (Software RAID)
- 14.3 邏輯卷軸管理員 (Logical Volume Manager)
- 14.4 重點回顧
- 14.5 本章習題
- 14.6 參考資料與延伸閱讀
- 第十五章、例行性工作調度(crontab)
- 15.1 什么是例行性工作調度
- 15.2 僅執行一次的工作調度
- 15.3 循環執行的例行性工作調度
- 15.4 可喚醒停機期間的工作任務
- 15.5 重點回顧
- 15.6 本章習題
- 第十六章、程序管理與 SELinux 初探
- 16.1 什么是程序 (process)
- 16.2 工作管理 (job control)
- 16.3 程序管理
- 16.4 特殊文件與程序
- 16.5 SELinux 初探
- 16.6 重點回顧
- 16.7 本章習題
- 16.8 參考資料與延伸閱讀
- 第十七章、認識系統服務 (daemons)
- 17.1 什么是 daemon 與服務 (service)
- 17.2 通過 systemctl 管理服務
- 17.3 systemctl 針對 service 類型的配置文件
- 17.4 systemctl 針對 timer 的配置文件
- 17.5 CentOS 7.x 默認啟動的服務簡易說明
- 17.6 重點回顧
- 17.7 本章習題
- 17.8 參考資料與延伸閱讀
- 第十八章、認識與分析登錄文件
- 18.1 什么是登錄文件
- 18.2 rsyslog.service :記錄登錄文件的服務
- 18.3 登錄文件的輪替(logrotate)
- 18.4 systemd-journald.service 簡介
- 18.5 分析登錄文件
- 18.6 重點回顧
- 18.7 本章習題
- 18.8 參考資料與延伸閱讀
- 第十九章、開機流程、模塊管理與 Loader
- 19.1 Linux 的開機流程分析
- 19.2 核心與核心模塊
- 19.3 Boot Loader: Grub2
- 19.4 開機過程的問題解決
- 19.5 重點回顧
- 19.6 本章習題
- 19.7 參考資料與延伸閱讀
- 第二十章、基礎系統設置與備份策略
- 20.1 系統基本設置
- 20.2 服務器硬件數據的收集
- 20.3 備份要點
- 20.4 備份的種類、頻率與工具的選擇
- 20.5 鳥哥的備份策略
- 20.6 災難復原的考慮
- 20.7 重點回顧
- 20.8 本章習題
- 20.9 參考資料與延伸閱讀
- 第二十一章、軟件安裝:源代碼與 Tarball
- 20.1 開放源碼的軟件安裝與升級簡介
- 21.2 使用傳統程序語言進行編譯的簡單范例
- 21.3 用 make 進行宏編譯
- 21.4 Tarball 的管理與建議
- 21.5 函數庫管理
- 21.6 檢驗軟件正確性
- 21.7 重點回顧
- 21.8 本章習題
- 21.9 參考資料與延伸閱讀
- 第二十二章、軟件安裝 RPM, SRPM 與 YUM
- 22.1 軟件管理員簡介
- 22.2 RPM 軟件管理程序: rpm
- 22.3 YUM 線上升級機制
- 22.4 SRPM 的使用 : rpmbuild (Optional)
- 22.5 重點回顧
- 22.6 本章習題
- 22.7 參考資料與延伸閱讀
- 第二十三章、X Window 設置介紹
- 23.1 什么是 X Window System
- 23.2 X Server 配置文件解析與設置
- 23.3 顯卡驅動程序安裝范例
- 23.4 重點回顧
- 23.5 本章習題
- 23.6 參考資料與延伸閱讀
- 第二十四章、Linux 核心編譯與管理
- 24.1 編譯前的任務:認識核心與取得核心源代碼
- 24.2 核心編譯的前處理與核心功能選擇
- 24.3 核心的編譯與安裝
- 24.4 額外(單一)核心模塊編譯
- 24.5 以最新核心版本編譯 CentOS 7.x 的核心
- 24.6 重點回顧
- 24.7 本章習題
- 24.8 參考資料與延伸閱讀