當(dāng)前位置:首頁 > IT技術(shù) > 系統(tǒng)服務(wù) > 正文

一文教你如何學(xué)會(huì)寫Shell腳本
2022-02-14 14:19:13

一文教你如何學(xué)會(huì)寫Shell腳本_java

做 Java 的肯定都接觸過 Linux 系統(tǒng),那么很多時(shí)候我們在開發(fā)的過程中都是把我們項(xiàng)目打成一個(gè)jar包,或者是war包的形式,然后通過 XFTP 上傳到我們服務(wù)器的指定目錄,然后運(yùn)行一端啟動(dòng)腳本,讓我們項(xiàng)目變得可以訪問 就像???./sh service.sh start???然后啟動(dòng)我們寫好的???sh???的shell腳本。接下來我們就來學(xué)習(xí)一下關(guān)于 Shell 腳本是如何寫出來的。

Shell 腳本

Shell 腳本是什么?Shell是一個(gè)命令解釋器,它的作用是解釋執(zhí)行用戶輸入的命令及程序等,也就是說,我們用戶每輸入一條命令,Shell 就會(huì)相對(duì)應(yīng)的執(zhí)行一條命令。當(dāng)命令或程序語句不在命令行下執(zhí)行,而是通過一個(gè)程序文件來執(zhí)行時(shí),該程序文件就被稱為Shell腳本。

在我們的 Shell 腳本中,會(huì)有各種各樣的內(nèi)容,賦值,計(jì)算,循環(huán)等一系列的操作,接下來我們就來看看這個(gè) Shell 腳本怎么寫吧

1.查看自己當(dāng)前系統(tǒng)默認(rèn)的 Shell

??echo $SHELL??

輸出:/bin/bash

2.查看系統(tǒng)支持的Shell

??cat /etc/shells??

輸出:

/bin/sh /bin/bash /usr/bin/sh /usr/bin/bash

也就是說,我們的云服務(wù)器是支持我們在這里給他安排 Shell 腳本的

Shell 腳本怎么寫出來的

我們這時(shí)候先來安排一下???sh????的文件,創(chuàng)建一個(gè)文件夾,然后在其中創(chuàng)建一個(gè)???sh???的文件。

??mkdir /usr/local/shelltest??

??touch test.sh??

創(chuàng)建完成我們編輯一下內(nèi)容

??vim test.sh??

#!/bin/bash
echo "Hello World Shell"

然后我們出來運(yùn)行一下我們的 Shell 的第一個(gè)腳本

??bash test.sh??

出來的結(jié)果是???Hello World Shell??

一個(gè)及其簡單的腳本出現(xiàn)了,接下我們就分析一波我們寫了點(diǎn)啥?

??#!/bin/bash??

#! 是一個(gè)約定的標(biāo)記,它告訴系統(tǒng)這個(gè)腳本需要什么解釋器來執(zhí)行,即使用哪一種 Shell

我們在之前也使用了???echo $SHELL????來查看了自己系統(tǒng)默認(rèn)的是哪一種???sh???解析器,之前看到的是/bin/bash,所以我們在寫 Shell 腳本的時(shí)候,我們在開頭默認(rèn)的約定中,我們寫了這個(gè)是用 /bin/bash 來進(jìn)行解釋的,

那么我們?nèi)绾蜗裰罢{(diào)用我們的當(dāng)前目錄中的 Shell 腳本一樣去調(diào)用他呢?就像這個(gè)樣子的???./sh service.sh start??

1.授權(quán),

我們先不授權(quán)試一下看看能通過 ./test.sh 進(jìn)行調(diào)用么

bash: ./test.sh: Permission denied 會(huì)提示這個(gè),也就是沒有授權(quán)定義,

授權(quán)命令:chmod +x test.sh

2.執(zhí)行 ./test.sh

然后調(diào)用就能正常輸出了,就是說,在當(dāng)前的目錄下執(zhí)行這個(gè)腳本命令。

Shell 腳本的變量
  1. 定義變量和使用

變量命名實(shí)際上很簡單,我們先來試一下

??name=zhiyikeji??

這時(shí)候我們怎么使用變量呢?實(shí)際上只要在前面加上一個(gè)符號(hào)就可以 $

??echo $name??

[root@iZbp10j01t7sgfqekyefpoZ ~]# echo $name
zhiyikeji
[root@iZbp10j01t7sgfqekyefpoZ ~]# echo ${name}
zhiyikeji

上面的兩種寫法都是可以的,外面的大括號(hào)加和不加區(qū)別不大,可以省略,直接就??$name???就可以使用你定義的變量

使用括號(hào)的意義一般在于區(qū)別某些變量,比如你寫了一串的內(nèi)容,可能寫的是???echo $nameismyfriend???,如果連在一起,是不是有點(diǎn)尷尬,這時(shí)候就可以使用括號(hào)區(qū)別一下,??echo ${name}ismyfriend???不使用括號(hào)的時(shí)候,他就去找nameismyfriend這個(gè)變量了,就無法出來我們要的效果。

  1. 刪除自己定義的變量

??unset name??

這時(shí)候我們就把我們剛才定義的???name=zhiyikeji???這個(gè)變量給去掉了,我們可以調(diào)用一下我們的變量看是什么?

??echo $name??

[root@iZbp10j01t7sgfqekyefpoZ ~]# unset name
[root@iZbp10j01t7sgfqekyefpoZ ~]# echo $name

這是不是就證明我們自己定義的變量已經(jīng)刪除了

  1. 只讀變量

那么我們需要一個(gè)關(guān)鍵字,大家肯定能想到是什么關(guān)鍵字???readonly??

我們先給name賦值,然后使用 readonly 設(shè)置只讀,然后再改變一下試試,

[root@iZbp10j01t7sgfqekyefpoZ ~]# name=zhiyikeji
[root@iZbp10j01t7sgfqekyefpoZ ~]# echo $name
zhiyikeji
[root@iZbp10j01t7sgfqekyefpoZ ~]# readonly name
[root@iZbp10j01t7sgfqekyefpoZ ~]# echo $name
zhiyikeji
[root@iZbp10j01t7sgfqekyefpoZ ~]# name=ceshi
-bash: name: readonly variable
[root@iZbp10j01t7sgfqekyefpoZ ~]#

竟然是真的,如果不設(shè)置只讀,是不是會(huì)重新可以進(jìn)行賦值,我們測試個(gè)年齡,

[root@iZbp10j01t7sgfqekyefpoZ ~]# age=10
[root@iZbp10j01t7sgfqekyefpoZ ~]# echo $age
10
[root@iZbp10j01t7sgfqekyefpoZ ~]# age=20
[root@iZbp10j01t7sgfqekyefpoZ ~]# echo $age
20

所以我們就可以肯定,readonly就是設(shè)置只讀的關(guān)鍵詞,記住了么?

那么設(shè)置只讀的變量可以刪除么?畢竟總有杠精的面試官會(huì)提問這個(gè)棘手的問題,但是,阿粉試過的所有方式好像都是不行的,阿粉就直接重啟了自己的服務(wù)器,這樣臨時(shí)的變量就不存在了!

Shell 腳本的流程控制

說真的,Shell腳本的流程控制數(shù)一般才是yyds,為什么這么說,因?yàn)槟阍趯懘蟛糠值哪_本的時(shí)候,流程控制的地方永遠(yuǎn)是最多的,判斷,選擇,等等一系列的函數(shù),當(dāng)時(shí)熟練使用的時(shí)候,就發(fā)現(xiàn)這東西確實(shí)很有意思。

IF

我們先說最簡單的???if else????這也是我們最經(jīng)常使用的判斷,在寫???Shell???腳本的時(shí)候,就不像我們的 Java 中直接寫

if(...){

}else{
....
}

??Xshell????中的語法就不是這個(gè)樣子的,??Xshell??語法:

if ...
then

...
else
...
fi

末尾的 fi 就是 if 倒過來拼寫,我們可以寫一個(gè)???if???的腳本試一下這個(gè)流程能否理解。

#! /bin/bash

if [ $1 -gt 2 ];


then
echo "值大于2"

else
echo "值小于2"

exit
fi

這里申明一下,


  • ??-ge??標(biāo)識(shí)的是大于等于符號(hào);
  • ??-le??表示的是小于等于符號(hào);
  • ??-gt???表示大于符號(hào);
  • ??-lt???表示小于符號(hào);
  • ??-eq???表示等于符號(hào);
  • ??-ne???表示不等于符號(hào);

我們在上面這段腳本中寫就是內(nèi)容就是,我們給腳本傳入一個(gè)值,然后比對(duì)這個(gè)值和2的大小關(guān)系,然后輸出我們指定的內(nèi)容。

運(yùn)行后就能看到

[root@iZbp10j01t7sgfqekyefpoZ shelltest]# sh test2.sh 1
值小于2
[root@iZbp10j01t7sgfqekyefpoZ shelltest]# sh test2.sh 3
值大于2

??$1????表示我們給 Shell 腳本輸入的第一個(gè)參數(shù),???$0??就是你寫的shell腳本本身的名字,$2 是我們給 Shell 腳本傳的第二個(gè)參數(shù)

大家在部署某些項(xiàng)目的時(shí)候,是不是啟動(dòng)命令就很簡潔,就是???sh service.sh start????類似這種的,那我們來看看一般這種是怎么寫的,這就用到了另外一塊的內(nèi)容,和???if????類似,在 Java 中也有,那就是???Case??.

Case

我們先來看看???Case???的語法,

??case ... esac????實(shí)際上就和 Java 中的 Case 是非常相似的,case 語句匹配一個(gè)值與一個(gè)模式,如果匹配成功,執(zhí)行相匹配的命令.??esac??是一個(gè)結(jié)束的標(biāo)志。

case 值 in
匹配值1)
command1
command2

;;
匹配值2)
command1
command2
;;
esac

光說不練,假把式,我們來搞一下試試寫一個(gè)腳本來搞一下。就用我們剛才說的???sh servic.sh start???來進(jìn)行測試。

case $1 in

start)
#輸出啟動(dòng)命令
echo "start已經(jīng)開始"
;;
stop)
#輸出停止命令
echo "stop命令執(zhí)行"
;;
esac
exit

我們來看看運(yùn)行結(jié)果

[root@iZbp10j01t7sgfqekyefpoZ shelltest]# sh service.sh start
start已經(jīng)開始
[root@iZbp10j01t7sgfqekyefpoZ shelltest]# sh service.sh stop
stop命令執(zhí)行

那么這段 Shell 腳本是什么意思呢?其實(shí)很簡單,匹配我們傳入的第一個(gè)字符,和???start????還有???stop???進(jìn)行比較,如果匹配上之后,輸出命令,最后退出即可。

是不是感覺沒有那么復(fù)雜了呢?

For

說到流程控制,那么肯定不能不說 for , 畢竟 for 循環(huán)在 Java 中那可是重頭戲。

我們先看他的格式

for i in item1 item2 ... itemN
do
command1
command2
...
commandN
done

那么我們有沒有說像是 Java 中那種 for 循環(huán)一樣的方式呢?比如說這個(gè)??for ((i=1; i<=j; i++))??

實(shí)際上也是支持這種的,我們來寫一個(gè)試試。

j=$1
for ((i=1;i<=j;i++))
do
echo $i
done

執(zhí)行一下看看

[root@iZbp10j01t7sgfqekyefpoZ shelltest]# sh fortest.sh 6
1
2
3
4
5
6

既然有 for 那是不是就有 while 呢?是的,沒錯(cuò),確實(shí)是有 while ,也是循環(huán)的意思,但是寫法有略微不一樣的地方

While
while condition
do
command
done

我們來舉個(gè)嘗試打印九九乘法表來看一下

a=1
b=1
while ((a <=9))
do
while ((b<=a))
do
let "c=a*b" #聲明變量c
echo -n "$a*$b=$c "
let b++
done
let a++

let b=1 #因?yàn)槊總€(gè)乘法表都是1開始乘,所以b要重置

echo "" #顯示到屏幕換行

done
[root@iZbp10j01t7sgfqekyefpoZ shelltest]# sh whileTest.sh 
1*1=1
2*1=2 2*2=4
3*1=3 3*2=6 3*3=9
4*1=4 4*2=8 4*3=12 4*4=16
5*1=5 5*2=10 5*3=15 5*4=20 5*5=25
6*1=6 6*2=12 6*3=18 6*4=24 6*5=30 6*6=36
7*1=7 7*2=14 7*3=21 7*4=28 7*5=35 7*6=42 7*7=49
8*1=8 8*2=16 8*3=24 8*4=32 8*5=40 8*6=48 8*7=56 8*8=64
9*1=9 9*2=18 9*3=27 9*4=36 9*5=45 9*6=54 9*7=63 9*8=72 9*9=81

是不是也挺簡單的?

其實(shí) Shell 腳本的編寫一般都是在實(shí)際應(yīng)用中提升,單純的寫測試腳本,也是可以讓自己對(duì)知識(shí)的掌握比較充分,而我們一般都是寫一些比較簡單的腳本,復(fù)雜的不是還有運(yùn)維么?


< END >

告訴大家一個(gè)好消息,Java極客技術(shù)讀者交流群(摸魚為主),時(shí)隔 2 年后再次開放了,感興趣的朋友,可以在公號(hào)回復(fù):999

一文教你如何學(xué)會(huì)寫Shell腳本_shell腳本_02


本文摘自 :https://blog.51cto.com/u

開通會(huì)員,享受整站包年服務(wù)立即開通 >