shell 編程


shell 編程

Shell 是一個命令行解釋器,它為用戶提供了一個向 Linux 內核發送請求以便運行程序的界面系統級程序,用戶可以用 Shell 來啟動、掛起、停止甚至是編寫一些程序。

shell 腳本的執行方式

  • 腳本以#!/bin/bash 開頭

  • 腳本需要有可執行權限

第一個 Shell 腳本

#!/bin/bash
echo "hello,world~"

腳本的常用執行方式

方式 1 (輸入腳本的絕對路徑或相對路徑)

說明:首先要賦予 helloworld.sh 腳本的 +x 權限, 再執行腳本

./hello.sh 或 /root/shcode/hello.sh
方式 2 ( sh + 腳本)

說明:不用賦予腳本+x 權限,直接執行即可。

sh hello.sh

Shell 的變量

  • Linux Shell 中的變量分為,系統變量和用戶自定義變量。
  • 系統變量:$HOME$PWD$SHELL$USER 等等
  • 顯示當前 shell 中所有變量:set

shell 變量的定義

基本語法

定義變量

變量名=值

撤銷變量

unset 變量

聲明靜態變量

readonly 變量
細節說明
  • 變量名稱可以由字母、數字和下划線組成,但是不能以數字開頭
  • 等號兩側不能有空格
  • 靜態變量不能 unset
  • 變量名稱一般習慣為大寫, 這是一個規范
將命令的返回值賦給變量

A=date反引號,運行里面的命令,並把結果返回給變量 A

A=$(date) 等價於反引號

設置環境變量

基本語法

shell 變量輸出為環境變量/全局變量

export 變量名=變量值

讓修改后的配置信息立即生效

source 配置文件

查詢環境變量的值

echo $變量名

快速入門

  1. /etc/profile 文件中定義 TOMCAT_HOME 環境變量
  2. 查看環境變量 TOMCAT_HOME 的值
  3. 在另外一個 shell 程序中使用 TOMCAT_HOME

注意:在輸出 TOMCAT_HOME 環境變量前,需要讓其生效

source /etc/profile

shell 腳本的多行注釋

:<<!
內容
!

位置參數變量

當執行一個 shell 腳本時,如果希望獲取到命令行的參數信息,就可以使用到位置參數變量
比如 : ./myshell.sh 100 200 , 這個就是一個執行 shell 的命令行,可以在 myshell 腳本中獲取到參數信息

基本語法

$n:n 為數字,$0 代表命令本身,$1-$9 代表第一到第九個參數,十以上的參數,十以上的參數需要用大括號包含,如${10}

$*:這個變量代表命令行中所有的參數,$* 把所有的參數看成一個整體

$@:這個變量也代表命令行中所有的參數,不過$@把每個參數區分對待

$#:這個變量代表命令行中所有參數的個數

實例演示

編寫一個 shell 腳本 position.sh ,在腳本中獲取到命令行的各個參數信息

#! /bin/bash
echo "0=$0 1=$1"
echo "參數=$*"
echo "$@"
echo "參數的個數=$#"

輸入:sh position.sh 100 200

預定義變量

就是 shell 設計者事先已經定義好的變量,可以直接在 shell 腳本中使用

基本語法

$$:當前進程的進程號PID

$! :后台運行的最后一個進程的進程號(PID)

$?:最后一次執行的命令的返回狀態。如果這個變量的值為 0,證明上一個命令正確執行;如果這個變量的值為非 0(具體是哪個數,由命令自己來決定),則證明上一個命令執行不正確了。

#!/bin/bash
echo "當前執行的進程 id=$$"
#以后台的方式運行一個腳本,並獲取他的進程號
/root/shcode/myshell.sh &
echo "最后一個后台方式運行的進程 id=$!"
echo "執行的結果是=$?"

運算符

基本語法

$((運算式))
或
$[運算式]
或 
expr m + n

細節說明

  • 注意 expr 運算符間要有空格, 如果希望將 expr 的結果賦給某個變量,使用 ``
  • expr *, /, % 乘,除,取余

應用實例

案例 1:計算(2+3)X4 的值

#! /bin/bash
#使用第一種方式
RES1=$(((2+3)*4))
echo "res1=$RES1"
#使用第二種方式, 推薦使用
RES2=$[(2+3)*4]
echo "res2=$RES2"
#使用第三種方式 expr
TEMP=`expr 2 + 3`
RES4=`expr $TEMP \* 4`
echo "temp=$TEMP"
echo "res4=$RES4"

條件判斷

判斷語句

基本語法
[ condition ]
細節說明
  • 注意 condition 前后要有空格
  • 非空返回 true,可使用$?驗證(0 為 true,>1 為 false)
應用實例
[ hspEdu ] 返回 true
[ ] 返回 false
[ condition ] && echo OK || echo notok 條件滿足,執行后面的語句
常用判斷條件
  • 字符串比較

=

  • 兩個整數的比較

-lt 小於
-le 小於等於 little equal
-eq 等於
-gt 大於
-ge 大於等於
-ne 不等於

流程控制

if 判斷

基本語法
if [ 條件判斷式 ] 
then
代碼
fi

多分支

if [ 條件判斷式 ]
then
代碼
elif [條件判斷式]
then
代碼
fi
細節說明
  • [ 條件判斷式 ],中括號和條件判斷式之間必須有空格
應用實例

編寫一個 shell 程序,如果輸入的參數,大於等於 60,則輸出 "及格了",如果小於 60,則輸出 "不及格"

#! /bin/bash
if [ $1 -ge 60 ]
then
	echo "及格"
elif [ $1 -lt 60 ]
then
	echo "不及格"
fi

case 語句

基本語法
case $變量名 in
"值 1")
如果變量的值等於值 1,則執行程序 1
;;
"值 2")
如果變量的值等於值 2,則執行程序 2
;;
…省略其他分支…
*)
如果變量的值都不是以上的值,則執行此程序
;;
esac
應用實例

當命令行參數是 1 時,輸出 "周一", 是 2 時,就輸出"周二", 其它情況輸出 "other"

#! /bin/bash
case $1 in
"1")
;;
echo "周一"
"2")
echo "周二"
;;
*)
echo "other..."
;;
esac

for 循環

基本語法
for 變量 in 值 1 值 2 值 3…
do
程序/代碼
done
for (( 初始值;循環控制條件;變量變化 ))
do
程序 /代碼
done
應用實例
  1. 打印命令行輸入的參數 [這里可以看出$* 和 $@ 的區別]
#! /bin/bash
#使用$*
for i in "$*"
do
   echo "num is $i"
done
#使用$@
for i in "$@"
do
   echo "num is $i"
done
  1. 從命令行輸入一個數 n,統計從 1+..+ n 的值是多少?
#! /bin/bash
SUM=0
for(( i=1; i<=$1; i++))
do
   SUM=$[$SUM+$i]
done
echo "SUM=$SUM"

while 循環

基本語法
while [ 條件判斷式 ]
do
程序/代碼
done
細節說明
  • while[有空格,條件判斷式和 [也有空格
應用實例

從命令行輸入一個數 n,統計從 1+..+ n 的值是多少?

#!/bin/bash
SUM=0
i=0
while [ $i -le $1 ]
do
SUM=$[$SUM+$i]
#i 自增
i=$[$i+1]
done
echo "執行結果=$SUM"

read 讀取控制台輸入

基本語法

read(選項)(參數)

選項說明

-p:指定讀取值時的提示符

-t:指定讀取值時等待的時間(秒),如果沒有在指定的時間內輸入,就不再等待

參數說明

  • 變量:指定讀取值的變量名

應用實例

讀取控制台輸入一個 NUM2 值,在 10 秒內輸入

read -t 10 -p "請輸入一個數 NUM2=" NUM2
echo "你輸入的 NUM2=$NUM2"

函數

shell 編程和其它編程語言一樣,有系統函數,也可以自定義函數。

系統函數

basename

返回完整路徑最后 / 的部分,常用於獲取文件名

basename [pathname] [suffix]
basename [string] [suffix]

basename 命令會刪掉所有的前綴包括最后一個(‘/’)字符,然后將字符串顯示出來。

選項說明

  • suffix 為后綴,如果 suffix 被指定了,basename 會將 pathname 或 string 中的 suffix 去掉。
dirname

返回完整路徑最后 / 的前面的部分,常用於返回路徑部分

dirname 文件絕對路徑

從給定的包含絕對路徑的文件名中

應用實例

請返回 /home/aaa/test.txt/home/aaa

dirname /home/aaa/test.txt

自定義函數

基本語法
[ function ] funname[()]
{
Action;
[return int;]
}

調用直接寫函數名:funname [值]

應用實例

計算輸入兩個參數的和(動態的獲取), getSum

#!/bin/bash
#定義函數 getSum
function getSum() {
SUM=$[$n1+$n2]
echo "和是=$SUM"
}
#輸入兩個值
read -p "請輸入一個數 n1=" n1
read -p "請輸入一個數 n2=" n2
#調用自定義函數
getSum $n1 $n2

Shell 編程綜合案例

每天凌晨 2:30 備份 數據庫 hspedu 到 /data/backup/db

備份開始和備份結束能夠給出相應的提示信息

備份后的文件要求以備份時間為文件名,並打包成 .tar.gz 的形式,比如:2021-08-19_130201.tar.gz

在備份的同時,檢查是否有 10 天前備份的數據庫文件,如果有就將其刪除。

編寫 mysql_db_backup.sh

#備份目錄
BACKUP=/data/backup/db
#當前時間
DATETIME=$(date +%Y-%m-%d_%H%M%S)
echo $DATETIME
#數據庫的地址
HOST=localhost
#數據庫用戶名
DB_USER=root
#數據庫密碼
DB_PW=hspedu100
#備份的數據庫名
DATABASE=hspedu
#創建備份目錄, 如果不存在,就創建
[ ! -d "${BACKUP}/${DATETIME}" ] && mkdir -p "${BACKUP}/${DATETIME}"
#備份數據庫
mysqldump -u${DB_USER} -p${DB_PW} --host=${HOST} -q -R --databases ${DATABASE} | gzip >
${BACKUP}/${DATETIME}/$DATETIME.sql.gz
#將文件處理成 tar.gz
cd ${BACKUP}
tar -zcvf $DATETIME.tar.gz ${DATETIME}
#刪除對應的備份目錄
rm -rf ${BACKUP}/${DATETIME}
#刪除 10 天前的備份文件
find ${BACKUP} -atime +10 -name "*.tar.gz" -exec rm -rf {} \;
echo "備份數據庫${DATABASE} 成功~"

設置定時任務,每天凌晨2:30執行

crontab -l
30 2 * * * /usr/sbin/mysql_db_backup.sh


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM