shell腳本簡單教程

shell腳本教程

1 什么是shell腳本

Shell 是一個(gè)用 C 語言編寫的程序,它是用戶使用 Linux 的橋梁。Shell 既是一種命令語言,又是一種程序設(shè)計(jì)語言。Shell 腳本(shell script),是一種為 shell 編寫的腳本程序。

1.1 開發(fā)環(huán)境

Shell 編程跟 JavaScript、php 編程一樣,只要有一個(gè)能編寫代碼的文本編輯器和一個(gè)能解釋執(zhí)行的腳本解釋器就可以了。
Linux 的 Shell 種類眾多,常見的有:

  • Bourne Shell(/usr/bin/sh或/bin/sh)
  • Bourne Again Shell(/bin/bash)
  • C Shell(/usr/bin/csh)
  • K Shell(/usr/bin/ksh)
  • Shell for Root(/sbin/sh)
  • ……
1.2 初步體驗(yàn)

程序開發(fā)一般都是以一個(gè)hello world 開始,這里我們也不免俗,新建一個(gè)test.sh的文件,寫入內(nèi)容如下:

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

#! 是一個(gè)約定的標(biāo)記,它告訴系統(tǒng)這個(gè)腳本需要什么解釋器來執(zhí)行,即使用哪一種 Shell。echo 命令用于向窗口輸出文本。
在linux上運(yùn)行shell腳本,需要先將腳本文件更改為可執(zhí)行。然后執(zhí)行。

chmod +x ./test.sh  #使腳本具有執(zhí)行權(quán)限
./test.sh  #執(zhí)行腳本
1.3 語言學(xué)習(xí)的流程

語言學(xué)習(xí)的流程我這邊總結(jié)了比較通用的步驟,這里一定存在一定的狹隘的看法,僅供參考。步驟如下:

1,變量的定義、語法、使用
2,運(yùn)算符
3,流程控制(條件語句、循環(huán)語句)
4,函數(shù)的定義和使用
5,...
2 shell腳本基礎(chǔ)語法
2.1 變量
# 什么是變量?
變量的概念基本上和初中代數(shù)的方程變量是一致的,只是在計(jì)算機(jī)程序中,變量不僅可以是數(shù)字,還可以是任意數(shù)據(jù)類型.
shell腳本中的變量一般只有兩種:數(shù)字和字符串。
# 變量的定義
變量的定義有兩種方式,直接賦值或者語句賦值。
a,直接賦值
my_name="zhangsan"  # 定義了一個(gè)值為zcw的變量,變量的名為my_name
my_age=30   # 定義了值為30的變量,變量名為my_age
需要注意:
1、命名只能使用英文字母,數(shù)字和下劃線,首個(gè)字符不能以數(shù)字開頭
2、中間不能有空格,可以使用下劃線(_)
3、不能使用bash里的關(guān)鍵字
4、變量賦值語句等號(hào)兩側(cè)不能有空格,這點(diǎn)和其他開發(fā)語言不一樣

b,語句賦值
dir_list=`ls`  # dir_list的值即為當(dāng)前文件下全部文件和文件夾名稱
需要注意:
1、ls為linux命令列出當(dāng)前文件下全部文件和文件夾
2、這種linux命令需要使用(`)包括
# 變量的使用
shell腳本變量的使用和其他語言不同,如java、php、python、c、c++等都是直接引用變量名即可,shell腳本中是需要在變量名前加上($)符號(hào)的。
my_name="zhangsan"
echo $my_name
echo ${my_name}   
推薦使用第二種方式,加花括號(hào)是為了幫助解釋器識(shí)別變量的邊界,比如下面這種情況
echo "my name is $my_namei am ok!"
# 字符串
字符串的可以用單引號(hào),也可以用雙引號(hào),也可以不用引號(hào)。一般不推薦不用引號(hào)。
這里主要說下單引號(hào)和雙引號(hào)的區(qū)別。
a,單引號(hào)
1、單引號(hào)里的任何字符都會(huì)原樣輸出,單引號(hào)字符串中的變量是無效的
2、單引號(hào)必須成對出現(xiàn)
b,雙引號(hào)
1、雙引號(hào)可用有變量
2、雙引號(hào)可用出現(xiàn)轉(zhuǎn)義字符

示例
your_name="runoob"
# 使用雙引號(hào)拼接
greeting="hello, "$your_name" !"
greeting_1="hello, ${your_name} !"
echo $greeting  $greeting_1
# 使用單引號(hào)拼接
greeting_2='hello, '$your_name' !'
greeting_3='hello, ${your_name} !'
echo $greeting_2  $greeting_3
hello, runoob ! hello, runoob !
hello, runoob ! hello, ${your_name} !

字符串兩個(gè)方法:
1、獲取字符串長度
string="abcd"
echo ${#string} #輸出 4
2、提取字符串
string="runoob is a great site"
echo ${string:1:4} # 輸出 unoo
# 數(shù)組
bash支持一維數(shù)組、類似于 C 語言,數(shù)組元素的下標(biāo)由 0 開始編號(hào)。
array_name=(value0 value1 value2 value3) #這是一個(gè)定義的數(shù)組

讀取數(shù)組
${array_name[n]}  # n這里為實(shí)際的數(shù)字,范圍為0——數(shù)組長度-1
2.2 運(yùn)算符

shell運(yùn)算符主要包括:

  • 算數(shù)運(yùn)算符
  • 關(guān)系運(yùn)算符
  • 布爾運(yùn)算符
  • 字符串運(yùn)算符
  • 文件測試運(yùn)算符
    這里我簡單講解下算數(shù)運(yùn)算、關(guān)系運(yùn)算和邏輯運(yùn)算。
    據(jù)名知意,算數(shù)就是計(jì)算,關(guān)系是進(jìn)行比較的,邏輯就是與或非。
# 算數(shù)運(yùn)算
原生bash不支持簡單的數(shù)學(xué)運(yùn)算,但是可以通過其他命令來實(shí)現(xiàn),例如 awk 和 expr,expr 最常用。如:
val=`expr 2 + 2`   # 前面講過(`)是執(zhí)行的linux命令
echo "兩數(shù)之和為 : $val"
# 關(guān)系運(yùn)算
關(guān)系運(yùn)算符只支持?jǐn)?shù)字,不支持字符串,除非字符串的值是數(shù)字。
注:
1、需要使用[]包括
2、也可使用test 替換掉[]
2.3 流程控制

主要是控制程序的執(zhí)行,程序運(yùn)行一般都是按照順序執(zhí)行的,不過也有特殊的,如其他語言中的異步、回調(diào)等,不過在shell中一般只考慮順序執(zhí)行即可。順序執(zhí)行時(shí)我們可用通過條件語句來控制程序等運(yùn)行。
條件語句這里主要介紹下三種常見的:if語句、for循環(huán)、case...esac

# if語句
a=10
b=20
if [ $a == $b ]
then
   echo "a 等于 b"
elif [ $a -gt $b ]
then
   echo "a 大于 b"
elif [ $a -lt $b ]
then
   echo "a 小于 b"
else
   echo "沒有符合的條件"
fi
# for語句
for loop in 1 2 3 4 5
do
    echo "The value is: $loop"
done

for file in `ls`
do
    echo file
done
# case...esac語句
echo '輸入 1 到 4 之間的數(shù)字:'
echo '你輸入的數(shù)字為:'
read aNum
case $aNum in
    1)  echo '你選擇了 1'
    ;;
    2)  echo '你選擇了 2'
    ;;
    3)  echo '你選擇了 3'
    ;;
    4)  echo '你選擇了 4'
    ;;
    *)  echo '你沒有輸入 1 到 4 之間的數(shù)字'
    ;;
esac
2.4 函數(shù)

一次定義多處使用。

funWithReturn(){
    echo "這個(gè)函數(shù)會(huì)對輸入的兩個(gè)數(shù)字進(jìn)行相加運(yùn)算..."
    echo "輸入第一個(gè)數(shù)字: "
    read aNum
    echo "輸入第二個(gè)數(shù)字: "
    read anotherNum
    echo "兩個(gè)數(shù)字分別為 $aNum 和 $anotherNum !"
    return $(($aNum+$anotherNum))
}
funWithReturn
echo "輸入的兩個(gè)數(shù)字之和為 $? !"
3 ()、(())、[]、[[]]、{}的作用和區(qū)別
$()和 ` `  
在 bash shell 中,$( ) 與` ` (反引號(hào)) 都可用做命令替換用。
例如   
version=$(uname -r)和version=`uname -r`都可以是version得到內(nèi)核的版本號(hào)
各自的優(yōu)缺點(diǎn):
1、`  ` 基本上可用在全部的 unix shell 中使用,若寫成 shell script ,其移植性比較高,但反單引號(hào)容易打錯(cuò)或看錯(cuò)。
2、$()并不是所有shell都支持。
${ } 
${ }用于變量替換。一般情況下,$var 與${var} 并沒有什么不一樣,但是用 ${ } 會(huì)比較精確的界定變量名稱的范圍。
$[] $(()) 
$[]和$(())是一樣的,都是進(jìn)行數(shù)學(xué)運(yùn)算的。支持+ - * / %(“加、減、乘、除、取?!保5亲⒁?,bash只能作整數(shù)運(yùn)算,對于浮點(diǎn)數(shù)是當(dāng)作字符串處理的。
[ ] 
為test命令的另一種形式,但要注意:
1.必須在左括號(hào)的右側(cè)和右括號(hào)的左側(cè)各加一個(gè)空格,否則會(huì)報(bào)錯(cuò)。
2.test命令使用標(biāo)準(zhǔn)的數(shù)學(xué)比較符號(hào)來表示字符串的比較,而用文本符號(hào)來表示數(shù)值的比較。
3.大于符號(hào)或小于符號(hào)必須要轉(zhuǎn)義,否則會(huì)被理解成重定向。
(( ))及[[ ]] 
分別是[ ]的針對數(shù)學(xué)比較表達(dá)式和字符串表達(dá)式的加強(qiáng)版。

[[ ]]中增加模式匹配特效。
(( ))不需要再將表達(dá)式里面的大小于符號(hào)轉(zhuǎn)義。
4 實(shí)際案例
# 案例1,關(guān)閉javaweb程序
#!/bin/bash  
name=$(lsof -i:80|tail -1|awk '"$1"!=""{print $2}')  
if [ -z $name ]  
then  
    echo "No process can be used to killed!"  
    exit 0  
fi  
id=$(lsof -i:8080|tail -1|awk '"$1"!=""{print $2}')  
kill -9 $id  
  
echo "Process name=$name($id) kill!"  
exit 0
# 案例2,云平臺(tái)一鍵配置
#!/bin/bash
# 此腳本用于一鍵web環(huán)境及項(xiàng)目配置
# ver1.0

www="/home/wwwroot/default"
commands=(all ip lnmp web)

lnmpSetFun(){
    echo "修改lnmp配置信息"
    # php修改
    sed -i 's|proc_open,||' /usr/local/php/etc/php.ini && is_php=1 || is_php=0
    if test $is_php -eq 0
    then
        echo "lnmp尚未安裝,lnmp配置失??!"
        exit
    fi
    sed -i 's|proc_get_status,||' /usr/local/php/etc/php.ini
    sed -i '/PHP_ADMIN_VALUE/d' /usr/local/nginx/conf/fastcgi.conf
    service php-fpm restart
    # nginx修改
    sed -i '/$query_string/d' /usr/local/nginx/conf/nginx.conf
    sed -i '/include enable/a\        location / {try_files $uri $uri/ /index.php?$query_string;}' /usr/local/nginx/conf/nginx.conf
    sed -i '/root/d' /usr/local/nginx/conf/nginx.conf
    sed -i '/index index/a\        root '"$www"'/public;' /usr/local/nginx/conf/nginx.conf
    service nginx restart
    echo "lnmp配置完成!"
}

webSetFun(){
    chmod -R 777 $www/storage && is_web=1 || is_web=0
    if test $is_web -eq 0
    then
        echo "注意!網(wǎng)站未放入或網(wǎng)站路徑!網(wǎng)站配置失??!"
        exit
    fi
    chmod -R 777 $www/public
    cp /home/wwwroot/default/back.php $www/.env
    echo "網(wǎng)站配置完成!"
}

webIpFun(){
    read -p "請輸入本機(jī)IP: " ip
    api_ip="http://${ip}"
    if [ -z $ip ]
    then
        echo "尚未輸入IP,IP配置失?。?
        exit
    else
        sed -i '/baseUrl/d' $www/public/js/config.js
        sed -i '/commandUrl/d' $www/public/js/config.js
        sed -i '/^PLATFROM_CONFIG.title/i\PLATFROM_CONFIG.baseUrl = \"'"$api_ip"'\"' $www/public/js/config.js
        sed -i '/^PLATFROM_CONFIG.title/i\PLATFROM_CONFIG.commandUrl = \"'"$ip"'\"' $www/public/js/config.js
        sed -i '/APP_URL/d' $www/.env
        sed -i '/SERVER_URL/d' $www/.env
        sed -i '/^ADMIN_HTTPS/i\APP_URL='"$api_ip"'' $www/.env
        sed -i '/^ADMIN_HTTPS/i\SERVER_URL='"$api_ip"':8080/energy_command/' $www/.env
        echo "IP配置完成!"
    fi
}

case $1 in
    ${commands[0]})
        lnmpSetFun
        webSetFun
        webIpFun
        ;;
    ${commands[1]})
        webIpFun
        ;;
    ${commands[2]})
        lnmpSetFun
        ;;
    ${commands[3]})
        webSetFun
        ;;
    *)
        echo "輸入指令不正確!"
        echo "正確格式為 \"./webset.sh cmd\""
        echo "其中cmd包含有all、ip、lnmp、web"
        echo "all為一鍵配置全部,按照說明書正常步驟執(zhí)行完即可操作"
        echo "ip單配置后臺(tái)及前臺(tái)ip地址"
        echo "lnmp單配置lnmp服務(wù)"
        echo "web單配置web服務(wù)"
        ;;
esac
echo "配置完成,瀏覽器輸入\"http://本機(jī)ip\"訪問項(xiàng)目"

# 案例3,云平臺(tái)項(xiàng)目部署
#!/bin/bash
# 此腳本用于一鍵部署web項(xiàng)目
# ver1.0

wwwPlat="/home/wwwroot/default"
wwwServer="/home/wwwroot/server"
platMoveFun(){
    if [ -e $wwwPlat ]
    then
        echo "~~~~"
    else
        `mkdir -p ${wwwPlat}`
    fi
    `tar -xzvf ./energy_cloud_platform.tar.gz -C ${wwwPlat}`
}

serverMoveFun(){
    if [ -e $wwwServer ]
    then
        `rm -rf ${wwwServer}/*`
    else
        `mkdir -p ${wwwServer}`
    fi
    `\cp ./energy_cloud/* ${wwwServer}`
}

echo "###一鍵部署web文件###"
serverMoveFun
platMoveFun
echo "部署完成!"
5 結(jié)語

我這里只是帶著簡單過了下shell腳本的一些常用語法,實(shí)際學(xué)習(xí)還需要進(jìn)一步去看文檔。
shell語言其實(shí)只是簡單的基本操作語言,要讓其發(fā)揮作用還需要深入學(xué)習(xí)下linux命令,課程中大家應(yīng)該也看到了,其實(shí)很多地方都需要用到linux的命令獲取到數(shù)據(jù)給我們的變量中讓我們在進(jìn)一步處理。
我對于shell的理解是,其實(shí)它就是對linux命令提供了更方便的操作和處理方式。
這里我在列下自己目前常用的linux命令。http://m.itdecent.cn/p/7f68c0945f2f

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容