1. 程式人生 > 其它 >Shell指令碼入門與實戰

Shell指令碼入門與實戰

一.基本概念

Shell 是一個用 C 語言編寫的程式,它是使用者使用 Linux 的橋樑。Shell 既是一種命令語言,又是一種程式設計語言。
Shell 是指一種應用程式,這個應用程式提供了一個介面,使用者通過這個介面訪問作業系統核心的服務。
在電腦科學中,Shell俗稱殼(用來區別於核),是指“為使用者提供操作介面”的軟體(command interpreter,命令解析器)。
Linux shell屬於一種圖形化shell介面,並且shell指令碼指的是執行在shell上的指令碼。

二.基礎入門

1.基礎語法格式與標準

自定義shell指令碼通常被放於/usr/local/sbin目錄下,這樣方便標準統一,shell指令碼通常以sh結尾,比如test.sh

#! /bin/bash

## 這是第一個shell
date
echo 'Hello world!'
ls

其中,第一行#! /bin/bash必須要有,#! 是一個約定的標記,它告訴系統這個指令碼需要什麼直譯器來執行,即使用哪一種 Shell(這裡用的是bash)。
echo用於向視窗輸出文字,文字用單引號括起來,執行結果如下:

[root@VM-12-14-centos sbin]# sh test.sh 
Wed Aug  4 11:00:46 CST 2021
Hello,word!
test.sh
  1. #!/bin/bash 指定指令碼要使用的 Shell 型別為 Bash 。
  2. #! 被稱為 Sha-bang ,或者 Shebang , Linux 會分析它之後的指令,並載入該指令作為解析器。
  3. ls 就是指令碼檔案的內容了,表明我們執行 hello.sh 指令碼時會列舉出當前目錄的檔案列表並且會向控制檯列印 hello world

shell指令碼的執行方式常用的有兩種:

  1. 如果為非Root使用者,可以給指令碼新增執行許可權(因為vim編輯預設不帶執行許可權)
  • chmod +x test.sh #給此指令碼test.sh新增執行許可權
  • ./test.sh #執行當前目錄下的指令碼
  1. sh test.sh 直接執行

也可以使用sh -x test.sh 顯示執行過程,方便排查指令碼錯誤

shell中常用的date命令
date "+%Y-%m-%d %H:%M:%S"

2021-08-01 12:25:10
date -d "+1 day" "%Y-%m-%d" 加一天
date -d "-1 year" "%Y-%m-%d" 減一年

(1)基本運算子與引數賦值

  1. $[ ] : 加減乘除,不必新增空格
  2. $(( )) :加減乘除等,不必新增空格
#! /bin/bash
a=1
b=2
sum=$[$a+$b]
echo "12345+$sum"
echo "------------"
echo "第一個數:"
read  x
echo ”第二個數:
read y
sum=$[$x+$y]
echo "這是兩個數的和:$sum"

執行結果如下:

[root@VM-12-14-centos sbin]# sh test.sh 
2021-08-04 11:44:42
Hello,word!
test.sh
12345+3
------------
第一個數:
999
”第二個數:
999
這是兩個數的和:1998

read x/a/b/c/d 還可以替換為read -p “字串” x/a/b/c/d

read -p "當前結果滿意嗎:y/N" x

read -p相當於echo的效果上進行輸入

(2)條件判斷語句

基本條件判定符號如下:

  1. 條件在(( ))雙括號中使用,可用 引數名 + >= ,<=,>,<,=
  2. 條件在[ ]方括號中使用,使用 -lt (小於),-gt (大於),-le (小於等於),-ge (大於等於),-eq (等於),-ne (不等於)。
  3. [] : 中括號旁邊和運算子兩邊必須新增空格 (可以使用,不推薦)
  4. [[ ]]:中括號旁邊和運算子兩邊必須新增空格 (字串驗證時,推薦使用)
  5. (()) : 中括號旁邊和運算子兩邊必須新增空格 (數字驗證時,推薦使用)
  6. [[]] 和 (()) 分別是[ ]的針對數學比較表示式和字串表示式的加強版。
  7. 使用[[ … ]]條件判斷結構,而不是[ … ],能夠防止指令碼中的許多邏輯錯誤。比如,&&、||、<和> 操作符能夠正常存在於[[ ]]條件判斷結構中,但是如果出現在[ ]結構中的話,會報錯。比如可以直接使用if [[ $a != 1 && $a != 2 ]], 如果不適用雙括號, 則為if [ $a -ne 1] && [ $a != 2 ]或者if [ $a -ne 1 -a $a != 2 ]。
  8. [[ ]]中增加模式匹配特效;
  9. (( ))不需要再將表示式裡面的大小於符號轉義,除了可以使用標準的數學運算子外,還增加了以下符號

【1】if

#! /bin/bash
read -p "請輸入你的成績:" a
if ((a>=60));then
	echo "你的成績及格了,恭喜你!"
fi

【2】if else

#! /bin/bash
read -p "請輸入你的成績:" a
if ((a>=60));then
	echo "你的成績及格了,恭喜你!"
else
   echo "你的成績沒及格,下次加油!"
fi

【3】if elif else

#!/bin/bash
read -p "請輸入你的成績:" a
if ((a>=60)) && ((a<=90));then
   echo "你的成績及格了,恭喜你!"
elif ((a>90));then
   echo "你的成績非常優秀!"
else
   echo "你的成績沒及格,下次加油!"
fi


或者

執行結果圖如下

【4】case語句

#!/bin/bash
read -p "請輸入你想判斷的整數:" x
a=$[$x%2]
case $a in
1)
        echo "這是一個奇數!"
        ;;
0)
        echo "這是一個偶數!"
        ;;
esac

Shell case語句為多選擇語句。可以用case語句匹配一個值與一個模式,如果匹配成功,執行相匹配的命令。
case需要一個esac(就是case反過來)作為結束標記,每個case分支用右圓括號,用兩個分號表示break,其中“;;”不是跳出迴圈,是不在去匹配下面的模式

  1. break :跳出總迴圈
  2. continue:跳出當前迴圈,繼續下一次迴圈

case指令碼常用於編寫系統服務的啟動指令碼。

【5】while

#條件迴圈
while condition
do
    command
done

#無限迴圈
while :
do
    command
done

【6】until迴圈

until 迴圈執行一系列命令直至條件為 true 時停止。
until 迴圈與 while 迴圈在處理方式上剛好相反。

until condition
do
    command
done

【7】for迴圈

for 變數名 in 迴圈的條件; do
command
done

#!/bin/bash
for i in `seq 1 5`;do
        echo $i
done

seq 1 5 代表1到5的一個序列

(3)輸出語句

【1】echo

僅建議用於字串的輸出
echo " " 或者echo ' '

【2】printf

printf 不會像 echo 自動新增換行符,我們可以手動新增 \n
無大括號,直接以空格分隔

  • 格式:printf format-string [arguments...] 其中(format-string: 格式控制字串、arguments: 引數列表)
  • 案例:printf "%-10s %-8s %-4.2f\n" 郭靖 男 66.1234

%s %c %d %f 都是格式替代符:

  1. d:Decimal 十進位制整數 對應位置引數必須是十進位制整數,否則報錯!
  2. s:String 字串 對應位置引數必須是字串或者字元型 否則報錯
  3. c:Char 字元 對應位置引數必須是字串或者字元型 否則報錯
  4. f:Float 浮點 對應位置引數必須是數字型 否則報錯
  5. %-10s : 指一個寬度為10個字元(-表示左對齊,沒有則表示右對齊),任何字元都會被顯示在10個字元寬的字元內,如果不足則自動以空格填充,超過也會將內容全部顯示出來。
  6. %-4.2f :指格式化為小數,寬度為4個字元,其中.2指保留2位小數。

轉義符:

  1. \a :警告字元,通常為ASCII的BEL字元
  2. \b :後退
  3. \c :抑制(不顯示)輸出結果中任何結尾的換行字元(只在%b格式指示符控制下的引數字串中有效),而且,任何留在引數裡的字元、任何接下來的引數以及任何留在格式字串中的字元,都被忽略
  4. \f :換頁(formfeed)
  5. \n :換行
  6. \r :回車(Carriage return)
  7. \t :水平製表符
  8. \v :垂直製表符
  9. \ :一個字面上的反斜槓字元
  10. \ddd :表示1到3位數八進位制值的字元。僅在格式字串中有效
  11. \0ddd :表示1到3位的八進位制值字元

(4)shell指令碼中的函式

函式建議寫在開頭,函式永遠要在呼叫之前,
使用$1來代表第一個引數,便於按順序傳參
可以在指令碼內呼叫方法,也可以在指令碼外呼叫方法

#!/bin/bash
function add(){
        sum=$[$1 + $2]
        return $sum
}

add 1 2
echo "當前和為:$? !"

和為3


#!/bin/bash
function add(){
        sum=$[$1 + $2]
        return $sum
}

add $1 $2
echo "當前和為:$? !"
sh hanshu.sh 3 6

當前和為:9 !

(5)常用檔案操作

shell 指令碼中if還經常判斷關於檔案屬性,比如判斷是普通檔案還是目錄,判斷檔案是否有讀寫執行許可權等。常用的也就幾個選項:

  • -e :判斷檔案或目錄是否存在
  • -d :判斷是不是目錄,並是否存在
  • -f :判斷是否是普通檔案,並存在
  • -r :判斷文件是否有讀許可權
  • -w :判斷是否有寫許可權
  • -x :判斷是否可執行
    使用if判斷時,具體格式為: if [ -e filename ] ; then

三.實戰入門

1.入門練手

(1)1-100的和

#!/bin/bash
a=1
sum=0
b=1
while (($a<=100))
do
        sum=$[$a+$sum]
        a=$[$b+$a]
done

echo $sum 

(2)輸入一個數,求從1-n的和

#bin/bash
sum=0
read -p "請輸入一個數字:" a
while ((a<1))
do
        read -p "輸入的數字格式不正確,請重新輸入一個數字:" a
done

for i in `seq 1 $a`;do
        sum=$[$i+$sum]
done
echo $sum

(3)拷貝一個目錄到另一個目錄下

shell指令碼對檔案目錄的判定

shell 指令碼中if還經常判斷關於檔案屬性,比如判斷是普通檔案還是目錄,判斷檔案是否有讀寫執行許可權等。常用的也就幾個選項:

-e :判斷檔案或目錄是否存在

-d :判斷是不是目錄,並是否存在

-f :判斷是否是普通檔案,並存在

-r :判斷文件是否有讀許可權

-w :判斷是否有寫許可權

-x :判斷是否可執行

使用if判斷時,具體格式為: if [ -e filename ] ; then

#!/bin/bash
cd /home/xt
list=`ls`
for i in ${list[0]}
do
        echo "$i"
        if [ -d $i ];then
           echo "123456"
           cp -r $i /home/test1/
        fi
done
或者********************************
#! /bin/bash
for f in `ls /root/`; do
	if [ -d $f ] ; then
		cp -r $f /tmp/
	fi
done

2.檔案資訊處理

awk處理檔案

#!/bin/bash
awk -F "," '{print NF,$1,$2,$3,$4,$5,$6,$7}' a.txt

awk -F "," '{print NF,$0}' a.txt


直接讀取檔案,輸出第123457列的資料
$0直接輸出所有的資料,

3.實用指令碼

(1)開啟/關閉Tomcat

sh tomcat.sh start/stop
開啟tomcat,並進入tomcat的日誌
關閉tomcat,並判斷是否要殺死殭屍程序,刪除webapps下的war包

#!/bin/bash
tomcat_home=/home/xt/test-tomcat
STARTTOMCAT=$tomcat_home/bin/startup.sh
SHUTDOWN=$tomcat_home/bin/shutdown.sh
WEB=$tomcat_home/webapps
MYLOG=/applog/ossDown-downBatch
TOMCATLOG=$tomcat_home/logs
case $1 in
start)
        echo "啟動Tomcat!"
        $STARTTOMCAT
        cd $TOMCATLOG
        tail -f catalina.out -n 500
        ;;
stop)
        echo "關閉Tomcat!"
        $SHUTDOWN
        pid=`ps -ef |grep test-tomcat |grep -v "grep"|awk '{print $2}'`
        if [ "$pid" = "" ];then
                echo "當前tomcat執行緒已停止"
        else
                echo "關閉的程序號為: $pid"
                kill -9 $pid
        fi
        cd $WEB
        rm -rf *
        ;;

esac