標籤:style io 使用 ar strong for 資料 div art
利用 if .... then
if [ 條件判斷式 ]; then當條件判斷式成立時,可以進行的命令工作內容;fi <==將 if 反過來寫,就成為 fi !結束 if 之意! |
[ "$yn" == "Y" -o "$yn" == "y" ]
上式可替換為
[ "$yn" == "Y" ] || [ "$yn" == "y" ]
[[email protected] scripts]# cp sh06.sh sh06-2.sh <==用改的比較快![[email protected] scripts]# vi sh06-2.sh#!/bin/bash# Program:# This program shows the user‘s choice# History:# 2005/08/25 VBird First releasePATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/binexport PATHread -p "Please input (Y/N): " ynif [ "$yn" == "Y" ] || [ "$yn" == "y" ]; thenecho "OK, continue"exit 0fiif [ "$yn" == "N" ] || [ "$yn" == "n" ]; thenecho "Oh, interrupt!"exit 0fiecho "I don‘t know what your choice is" && exit 0 |
# 一個條件判斷,分成功進行與失敗進行 (else)if [ 條件判斷式 ]; then當條件判斷式成立時,可以進行的命令工作內容;else當條件判斷式不成立時,可以進行的命令工作內容;fi |
# 多個條件判斷 (if ... elif ... elif ... else) 分多種不同情況運行if [ 條件判斷式一 ]; then當條件判斷式一成立時,可以進行的命令工作內容;elif [ 條件判斷式二 ]; then當條件判斷式二成立時,可以進行的命令工作內容;else當條件判斷式一與二均不成立時,可以進行的命令工作內容;fi |
[[email protected] scripts]# cp sh06-2.sh sh06-3.sh[[email protected] scripts]# vi sh06-3.sh#!/bin/bash# Program:# This program shows the user‘s choice# History:# 2005/08/25 VBird First releasePATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/binexport PATHread -p "Please input (Y/N): " ynif [ "$yn" == "Y" ] || [ "$yn" == "y" ]; thenecho "OK, continue"elif [ "$yn" == "N" ] || [ "$yn" == "n" ]; thenecho "Oh, interrupt!"elseecho "I don‘t know what your choice is"fi |
一般來說,如果你不希望使用者由鍵盤輸入額外的資料時, 讓使用者在下達命令時就將參數帶進去! 現在我們想讓使用者輸入『 hello 』這個關鍵字時,利用參數的方法可以這樣依序設計:
- 判斷 $1 是否為 hello,如果是的話,就顯示 "Hello, how are you ?";
- 如果沒有加任何參數,就提示使用者必須要使用的參數下達法;
- 而如果加入的參數不是 hello ,就提醒使用者僅能使用 hello 為參數。
整個程式的撰寫可以是這樣的:
[[email protected] scripts]# vi sh09.sh#!/bin/bash# Program:#Check $1 is equal to "hello"# History:# 2005/08/28VBirdFirst releasePATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/binexport PATHif [ "$1" == "hello" ]; thenecho "Hello, how are you ?"elif [ "$1" == "" ]; thenecho "You MUST input parameters, ex> {$0 someword}"elseecho "The only parameter is ‘hello‘, ex> {$0 hello}"fi |
netstat命令可以查詢到目前主機有開啟的網路服務連接埠 (service ports)
[[email protected] ~]# netstat -tulnActive Internet connections (only servers)Proto Recv-Q Send-Q Local Address Foreign Address Statetcp 0 0 0.0.0.0:111 0.0.0.0:* LISTENtcp 0 0 127.0.0.1:631 0.0.0.0:* LISTENtcp 0 0 127.0.0.1:25 0.0.0.0:* LISTENtcp 0 0 :::22 :::* LISTENudp 0 0 0.0.0.0:111 0.0.0.0:*udp 0 0 0.0.0.0:631 0.0.0.0:*#封包格式 本地IP:連接埠 遠程IP:連接埠 是否監聽 |
上面的重點是『Local Address (本地主機的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 』來偵測的!那我就可以簡單的這樣去寫這個程式喔:
[[email protected] scripts]# vi sh10.sh#!/bin/bash# Program:# Using netstat and grep to detect WWW,SSH,FTP and Mail services.# History:# 2005/08/28VBirdFirst releasePATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/binexport PATH# 1. 先作一些告知的動作而已~echo "Now, I will detect your Linux server‘s services!"echo -e "The www, ftp, ssh, and mail will be detect! \n"# 2. 開始進行一些測試的工作,並且也輸出一些資訊羅!testing=$(netstat -tuln | grep ":80 ") # 偵測看 port 80 在否?if [ "$testing" != "" ]; thenecho "WWW is running in your system."fitesting=$(netstat -tuln | grep ":22 ") # 偵測看 port 22 在否?if [ "$testing" != "" ]; thenecho "SSH is running in your system."fitesting=$(netstat -tuln | grep ":21 ") # 偵測看 port 21 在否?if [ "$testing" != "" ]; thenecho "FTP is running in your system."fitesting=$(netstat -tuln | grep ":25 ") # 偵測看 port 25 在否?if [ "$testing" != "" ]; thenecho "Mail is running in your system."fi |
由於日期是要用相減的方式來處置,所以我們可以透過使用 date 顯示日期與時間,將他轉為由 1970-01-01 累積而來的秒數, 透過秒數相減來取得剩餘的秒數後,再換算為日數即可。整個指令碼的製作流程有點像這樣:
- 先讓使用者輸入他們的退伍日期;
- 再由現在日期比對退伍日期;
- 由兩個日期的比較來顯示『還需要幾天』才能夠退伍的字樣。
利用『 date --date="YYYYMMDD" +%s 』轉成秒數後,接下來的動作就容易的多了!如果你已經寫完了程式,對照底下的寫法試看看:
[[email protected] scripts]# vi sh11.sh#!/bin/bash# Program:#You input your demobilization date, I calculate how many days#before you demobilize.# History:# 2005/08/29VBirdFirst releasePATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/binexport 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>20090401): " date2# 2. 測試一下,這個輸入的內容是否正確?利用正規標記法date_d=$(echo $date2 |grep ‘[0-9]\{8\}‘) # 看看是否有八個數字if [ "$date_d" == "" ]; thenecho "You input the wrong date format...."exit 1fi# 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"elsedeclare -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 |
利用 case ..... esac 判斷
case $變數名稱 in <==關鍵字為 case ,還有變數前有錢字型大小 "第一個變數內容") <==每個變數內容建議用雙引號括起來,關鍵字則為小括弧 )程式段;; <==每個類別結尾使用兩個連續的分號來處理! "第二個變數內容")程式段;; *) <==最後一個變數內容都會用 * 來代表所有其他值不包含第一個變數內容與第二個變數內容的其他程式運行段exit 1;;esac <==最終的 case 結尾!『反過來寫』! |
[[email protected] scripts]# vi sh09-2.sh#!/bin/bash# Program:# Show "Hello" from $1.... by using case .... esac# History:# 2005/08/29VBirdFirst releasePATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/binexport PATHcase $1 in "hello")echo "Hello, how are you ?";; "")echo "You MUST input parameters, ex> {$0 someword}";; *) # 其實就相當於萬用位元組,0~無窮多個任意位元組之意!echo "Usage $0 {hello}";;esac |
/etc/init.d/syslog restart
一般來說,使用『 case $變數 in 』這個文法中,當中的那個『 $變數 』大致有兩種取得的方式:
- 直接下達式:例如上面提到的,利用『 script.sh variable 』 的方式來直接給予 $1 這個變數的內容,這也是在 /etc/init.d 目錄下大多數程式的設計方式。
- 互動式:透過 read 這個命令來讓使用者輸入變數的內容。
讓使用者能夠輸入 one, two, three ,並且將使用者的變數顯示到螢幕上,如果不是 one, two, three 時,就告知使用者僅有這三種選擇。
[[email protected] scripts]# vi sh12.sh#!/bin/bash# Program:#This script only accepts the flowing parameter: one, two or three.# History:# 2005/08/29VBirdFirst releasePATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/binexport PATHecho "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 |
利用 function 功能
因為 shell script 的運行方式是由上而下,由左而右, 因此在 shell script 當中的 function 的配置一定要在程式的最前面, 這樣才能夠在運行時被找到!
[[email protected] scripts]# vi sh12-2.sh#!/bin/bash# Program:#Use function to repeat information.# History:# 2005/08/29VBirdFirst releasePATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/binexport PATHfunction 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 |
function 也是擁有內建變數的,函數名稱代表示 $0 ,而後續接的變數也是以 $1, $2...
[[email protected] scripts]# vi sh12-3.sh#!/bin/bash# Program:#Use function to repeat information.# History:# 2005/08/29VBirdFirst releasePATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/binexport PATHfunction 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 |
第十三章、學習 Shell Scripts 條件判斷式