介紹
shell 指令碼是實現 Linux 系統自動化的重要工具,提高效率,避免重複勞動,例如如下場景
1、系統安裝完後的優化、IP地址設定
2、系統安裝完後服務的搭建
3、系統資源、服務的監控等
學習 shell 指令碼最好有以下基礎
1、Linux 中常用的命令
2、常見的服務和搭建、排除、優化,nginx、nfs等等
3、vim/vi 文字編輯器,grep sed awk
內容
1、變數
2、判斷語句:if、case
3、迴圈語句:for、while等
4、函式
5、流程控制語句:continue、break、exit
等等
什麼是 shell 指令碼
最簡單的 shell 指令碼就是命令的堆砌
嚴格的 shell 指令碼會包含有命令、判斷語句、迴圈語句、流程控制語句、變數、註釋資訊等等。
例子
現在要編寫一個指令碼清除日誌,日誌為 /access.log
root@test:/home/test# echo 123 > /access.log
root@test:/home/test# cat /access.log
123
root@test:/home/test# vim clean_log.sh
cd /
>/access.log
echo "日誌清除完成"
root@test:/home/test# sh clean_log.sh
日誌清除完成
root@kunjuee:/home/test# cat /access.log
上面的腳步是不規範的
#!/bin/bash
DIR=/
ROOT_UID=0
#只有root使用者才能清除日誌
if ["$UID" -ne "$ROOT_UID"]
then
echo "只有root使用者才能清除日誌"
exit 1
fi
cd $DIR || {
echo "切換目錄失敗"
exit 2
}
>access.log && echo "清除日誌成功"
介紹
#!/bin/bash
第一行一般來說用於指定命令直譯器, sh script-name
指令碼執行方式:
1. sh scripts-name 或 /bin/bash scripts-name 腳步檔案可以沒有可執行許可權
2. /path/scripts-name 命令全路徑,或者相對路徑,必須要有可執行許可權
3. source /path/scripts-name 或 ./path/scripts-name 能夠讓指令碼中的變數與函式在指令碼執行完成後依然生效。
# 檢視預設的命令直譯器
root@test:~$ echo $SHELL
/bin/bash
在shell指令碼中只要以 # 開頭,表示註釋
一般來說指令碼名稱會以.sh結尾,但這不是必須的
shell 指令碼是按行執行的,並且預設情況下可以沒有縮排,但是為了程式碼的易讀性,所以人為的新增縮排
變數
在 shell 中有三種變數:環境變數,自定義全域性變數、自定義區域性變數
變數名可以由字母(大小寫)、數字、下劃線等組成,不能以數字開頭
環境變數,例如$SHELL,$UID 等,一般可以在 /etc/profile 或 /etc/bashrc等檔案中看到
全域性變數:export 變數名=value
能夠對子 shell 生效
區域性變數:變數名=value
定義完後只能當前shell生效
測試
$ aaa=123
$ export bbb=456
$ echo aaa
123
$ echo bbb
456
# 檢視當前shell程式號
$ echo $$
12866
# 開啟一個子shell
$ bash
$ echo $$
16990
$ echo $aaa
$ echo $bbb
456
$ exit
除了上面的變數外還有一些特殊功能的變數,$0 $? $n $#
$0:指令碼名稱
$?:上一條命令的執行結果
$n:n就是第幾個引數,指令碼傳參功能
$#:引數的個數
除了以上功能,還有條件測試表示式、檔案測試表示式、字串測試表示式等等,man bash 來進行檢視
判斷語句 if
if 語句分為單分支語句、雙分支語句、多分支語句,並且 if 語句是可以互相巢狀的。
單分支語句格式:
if <條件表示式> then 指令1 ... fi
雙分支語句格式:
if <條件表示式> then 指令1 ... else 指令2 ... fi
多分支語句格式:
if <條件表示式> then 指令1 ... elif <條件表示式> then 指令2 ... elif <條件表示式> then ... else 指令3 ... fi
<條件表示式>,這裡的條件表示式可以是命令,test [] [[]] (())
測試
現在編寫一個指令碼,判斷某個服務是否執行,如果已經執行則提示服務已經執行並退出,如果沒有執行則執行,如果沒有安裝服務,則先進行安裝再執行,在安裝前將yum源設定為阿里雲的yum源
# grep 是聚合草足,wc -l 是統計數量
$ jps -l | grep file | wc -l
# 檢視服務是否已經啟動
$ systemctl is-active mysql
# 檢視上一條命令是否執行成功
$ echo $?
#
$ ss -lntup
#!/bin/bash
if[$# -eq 1]
then
#判斷服務是否安裝
#rmp -qa | grep $1 | wc -l
aa=`rpm -qa $1|wc -l`
if[$aa -lt 1]
then
#下載阿里雲映象源
curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo
if [ $? -eq 0]
then
#安裝服務
yum install -y $1
systemctl start $1
systemctl enable $1
bb=`systemctl is-active $1`
if [ $bb == 'active']
then
echo "${1}服務安裝並啟動成功"
else
echo "${1}服務安裝失敗,請檢查"
fi
else
echo "安裝yum源失敗,請檢查網路"
exit 1
fi
else
cc=`systemctl is-active $1`
if [ $cc == "active" ]
then
echo "${1}服務已經開啟"
else
systemctl start $1
if [$? -eq 0 ]
then
echo "${1}服務已經啟動成功"
else
echo "${1}服務啟動失敗,檢查配置是否正常"
fi
systemctl enable $1
fi
fi
else
echo "請輸入要執行的服務,格式為:if.sh 服務名稱"
fi
for 迴圈
for 迴圈與 while 迴圈最大的區別在於迴圈的次數,一般來說 for 迴圈用於有限次數的迴圈,while 迴圈一般來說用於守護程式。
格式
for 變數名 in 變數取值表
do
指令
...
done
例子:
現在有幾個 KVM 虛擬機器,配置檔案是以 xml 結尾的檔案,檔案中記錄著虛擬機器的各種資訊。現在需要獲取虛擬機器的名稱與磁碟的對應關係,並且以空格分隔。
# 列印 xml 的第九行,| 將前面的結果丟給後面的命令,awk進行列輸出,-F 指定分隔符,
$ sed -n 9p centos7-11.xml | awk -F "[<>]" '{print $3}'
#!/bin/bash
file_name=`ls /root/centos7-*.xml`
for n in $file_name
do
kvm_name=`sed -n 9p $n | awk -F "[<>]" '{print $3}' `
disk_name=`sed -n 41p $n | awk -F "'" '{print $2}'`
echo "${n}:${kvm_name} ${disk_name}"
while 迴圈語句
格式
while 條件表示式(true)一直執行
do
指令
done
例子:
猜隨機數,系統隨機生成一個1~60之間的數字,使用者來猜這個數字,對使用者輸入的數字進行判斷,如果不等於則提示大或小,正確後提示正確,並提示嘗試次數。
# 生成隨機數 0~32768 之間
$ echo $RANDOM
$ expr 1 + 1
2
$ echo $?
0
$ expr aa + 1
expr:非整數引數
$ echo $?
2
#!/bin/bash
try=0
num=$((RANDOM%61))
one(){
# read 是互動式的
read -p "please input a num 0 ~ 60:" a
# 判斷輸入的是否為數字
expr $a + 1 & > /dev/null
if [ $? -ne 0 ]
then
echo "請輸入正確的內容"
one
fi
}
two(){
((try++))
if [ $a -eq $num ]
then
echo "猜對了,數字為:${num}.嘗試次數為${try}"
exit 0
elif [ $a -gt $num ]
then
echo "大了,請重試"
one
else
echo "小了,請重試"
one
fi
}
three(){
one
while true
do
two
done
}
three
本作品採用《CC 協議》,轉載必須註明作者和本文連結