Linux shell 指令碼基礎介紹

HuDu發表於2021-07-11

介紹

shell 指令碼是實現 Linux 系統自動化的重要工具,提高效率,避免重複勞動,例如如下場景
1、系統安裝完後的優化、IP地址設定
2、系統安裝完後服務的搭建
3、系統資源、服務的監控等

學習 shell 指令碼最好有以下基礎
1、Linux 中常用的命令
2、常見的服務和搭建、排除、優化,nginx、nfs等等
3、vim/vi 文字編輯器,grep sed awk

內容

1、變數
2、判斷語句:ifcase
3、迴圈語句:forwhile4、函式
5、流程控制語句:continuebreak、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
例子:
猜隨機數,系統隨機生成一個160之間的數字,使用者來猜這個數字,對使用者輸入的數字進行判斷,如果不等於則提示大或小,正確後提示正確,並提示嘗試次數。
# 生成隨機數 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 協議》,轉載必須註明作者和本文連結

相關文章