第一個(gè) Shell 程序
1. Shell 腳本的構(gòu)成及規(guī)范
Shell 腳本有一些約定俗成的規(guī)范,大家都遵循這些規(guī)則,編寫出來的腳本更能被大家接受,Shell 腳本其實(shí)不能稱為一門編程語言,它更像是一個(gè)工具,用來雜糅不同的程序及命令供我們調(diào)用來完成自己的預(yù)期操作。
1.1 命名規(guī)范
- Shell 腳本在命名方面沒有嚴(yán)格的要求,但是我們命名需要遵循見名知意,即可通過 Shell 腳本的名稱知道其功能;
- 文件名約定俗成以
.sh
結(jié)尾,方便識(shí)別其為 Shell 腳本文件; - 文件統(tǒng)一命名風(fēng)格,寫 Shell 一般用小寫字母加下劃線,例如
install_mysql.sh
, 我們看到該名稱就能知道其為一個(gè)安裝 mysql 的腳本文件。
1.2 Shell 腳本結(jié)構(gòu)
Shell 腳本在其中的第一行需要有指明解釋器,在上面 CLI Shell 中的那些解釋器,都可以寫,在以./install_mysql.sh
的時(shí)候,此時(shí)就是利用腳本中第一行的解釋器來運(yùn)行腳本,其格式為
#!Shell解釋器
,例如#!/bin/bash
, 但是這種方式存在一定的局限性,我們推薦使用 env 環(huán)境變量中的 bash,推薦使用這種方式#!/usr/bin/env bash
。
1.3 編碼統(tǒng)一
在編寫 Shell 的時(shí)候我們盡可能使用 UTF-8 編碼,可以支持中文及大多數(shù)符號(hào),在其中我們注釋使用英文,例如在不支持中文的服務(wù)器上,腳本更好的支持。
1.4 作者信息
在編寫 Shell 腳本的時(shí)候,我們應(yīng)該盡可能地指定 Shell 的描述信息,以及該腳本的作者,編寫該腳本的日期及聯(lián)系方式,以及腳本的版本,方便后期其他人閱讀及聯(lián)系。
例如在頭部添加如下注釋信息:
#!/bin/env bash
# Description: /mybin/myvim scripts
# Auth: kaliarch
# Email: kaliarch@163.com
# Date: 2020-02-15 13:36
# Version: 1.0
2. Shell 的運(yùn)行方式
運(yùn)行腳本可以歸納為三種方式,注意一般在運(yùn)行腳本的時(shí)候?yàn)槟_本添加 x
可執(zhí)行權(quán)限
2.1 顯式指定解釋器執(zhí)行
[root@shell workspace]# ll
total 4
-rw-r--r-- 1 root root 44 Sep 3 14:16 01-scripts.sh
[root@shell workspace]# cat 01-scripts.sh
#!/bin/env bash
# Description: /mybin/myvim scripts
# Auth: kaliarch
# Email: kaliarch@163.com
# Date: 2020-02-15 13:36
# Version: 1.0
echo "this is my first script"
cd /
[root@shell workspace]# bash 01-scripts.sh
this is my first script
在當(dāng)前 bash 環(huán)境下,當(dāng)前終端登錄的 Shell 為父 Shell,此種方式為在當(dāng)前 Shell 下再啟動(dòng)一個(gè)子進(jìn)程來運(yùn)行 Shell 腳本。
Tips: 此方法直接在終端指定解釋器來執(zhí)行腳本,此時(shí)的解釋器為終端指定的,不使用腳本內(nèi)第一行指定的解釋器執(zhí)行,直接指定解釋器,此時(shí)不需要為腳本添加可執(zhí)行權(quán)限。
2.2 直接指定腳本文件名稱
[root@shell workspace]# ll
total 4
-rw-r--r-- 1 root root 44 Sep 3 14:16 01-scripts.sh
[root@shell workspace]# . ./01-scripts.sh
-bash: ./01-scripts.sh: Permission denied
[root@shell workspace]# chmod +x 01-scripts.sh
[root@shell workspace]# ll
total 4
-rwxr-xr-x 1 root root 44 Sep 3 14:16 01-scripts.sh
[root@shell workspace]# . ./01-scripts.sh
this is my first script
[root@shell workspace]# /workspace/01-scripts.sh
this is my first script
利用直接在終端指定腳本文件名稱方式執(zhí)行,此種方式需要為腳本添加可執(zhí)行權(quán)限,在當(dāng)前 Shell 來執(zhí)行,不啟動(dòng)子 Shell,利用此種方式執(zhí)行腳本的解釋器為腳本內(nèi)的第一行指定的解釋器,例如此例中為#!/bin/bash
,利用.
命令來執(zhí)行腳本,一般用在當(dāng)前目錄沒有在 PATH 中,所以第二個(gè)./
是用來表示當(dāng)前目錄的。
2.3 source 執(zhí)行
[root@xuel-transfer workspace]# bash 01-scripts.sh
this is my first script
[root@xuel-transfer workspace]# ./01-scripts.sh
this is my first script
[root@xuel-transfer workspace]# source 01-scripts.sh
this is my first script
[root@xuel-transfer /]# pwd
/
利用此種方式也可執(zhí)行腳本,此方式在當(dāng)前上下文中執(zhí)行腳本,不會(huì)生成新的子進(jìn)程。腳本執(zhí)行完畢,回到當(dāng)前 Shell,腳本內(nèi)如果有 cd 命令
腳本退出后會(huì)影響當(dāng)前的環(huán)境上下文,此種方式運(yùn)行 Shell,腳本也可以沒有可執(zhí)行權(quán)限。
3. 調(diào)試
在我們執(zhí)行 Shell 腳本的時(shí)候?yàn)榱朔奖闩懦惓?,我們可以利?-x
來開啟調(diào)試,例如
[root@xuel-transfer workspace]# bash -x 01-scripts.sh
+ echo 'this is my first script'
this is my first script
+ cd /
通過上面例子可以看出 + 后面為腳本的內(nèi)容,沒有 + 的為腳本執(zhí)行的輸出
同時(shí)我們?yōu)榱朔奖悴榭茨_本打印正在執(zhí)行的命令,可以還可以利用 -v
參數(shù)。
4. 實(shí)例
4.1 第一個(gè) Shell 需求
在此我們也不寫 Hello Shell
了,舉一個(gè)非常實(shí)用的例子,里面涉及的一些語法在后期的文章中大家都能學(xué)到,可以先按照操作步驟實(shí)現(xiàn)。
經(jīng)過上面的學(xué)習(xí),我們知道我們?cè)趯?Shell 腳本的時(shí)候最好寫一些作者的信息,如果每次編寫都手動(dòng)添加一次就很麻煩,如果是 IDE 一般工具都可以自定義配置添加首部 banner,但是在 Linux 系統(tǒng)內(nèi)部編寫簡單 Shell 或文本,我們可以自定義小工具來實(shí)現(xiàn)。
4.2 思路
我們可以修改新增一個(gè)腳本將其添加進(jìn) PATH 中,如果利用此命令打開已存在的文件,利用 vim 直接打開,不對(duì)原內(nèi)容作出更改,如果之前文件未存在,就在文件首部自動(dòng)添加 banner 并用 vim 打開。
4.3 實(shí)現(xiàn)
- 創(chuàng)建文件
首先創(chuàng)建個(gè)文件 myvim - 編寫內(nèi)容
#!/bin/env bash
# Description: /mybin/myvim scripts
# Auth: kaliarch
# Email: kaliarch@163.com
# function: auto generate banner
# Date: 2020-02-15 13:36
# Version: 1.0
# file not exist
[ $# -eq 0 ] && echo "$0 [file],At least one parameter!" && exit 1
# add banner
add_banner() {
cat > $1 << EOF
#!/bin/env bash
# Description: $0 scripts
# Auth: $USER
# Date: $(date +%F" "%H:%M)
# Version: 1.0
EOF
}
# exist file
for file in $*;
do
if [ -f ${file} ];then
vim ${file} && exit 0
else
touch ${file} && add_banner ${file} && vim ${file} && exit 0
fi
done
- 添加進(jìn) PATH 中
[root@devops-server mybin]# chmod +x myvim # 添加可執(zhí)行權(quán)限
[root@devops-server mybin]# echo $PATH
/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
[root@devops-server mybin]# echo "export PATH=\$PATH:/mybin" >> /etc/profile # 將mybin添加進(jìn)PATH中
[root@devops-server mybin]# source /etc/profile
[root@devops-server mybin]# echo $PATH
/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin:/mybin
4.4 效果

利用 myvim 來編輯腳本可以自動(dòng)生成 banner,再次打開可以繼續(xù)編輯,這樣就免去了我們每次手動(dòng)編寫 banner 的麻煩。有興趣的同學(xué)可以進(jìn)行嘗試,是不是感覺 Shell 可以為我們帶來無窮的樂趣。
5. 注意事項(xiàng)
- 再次注意編寫 Shell 需要遵守其規(guī)范,這些約定俗成的規(guī)則能在日后的生產(chǎn)環(huán)境中為我們避免很多不必要的坑;
- 學(xué)習(xí) Shell 需要多動(dòng)手實(shí)踐,實(shí)踐出真理,多寫勤練,針對(duì)結(jié)果多思考,熟練運(yùn)用 man 指令來查看 Shell 腳本中常用的命令的參數(shù)及選項(xiàng);
- 舉一反三,針對(duì)一個(gè)腳本如何能無狀態(tài),更健壯,更靈活易維護(hù),需要多次的修改,反復(fù)的執(zhí)行驗(yàn)證,針對(duì)不同的應(yīng)用場景,將數(shù)據(jù)抽象為參數(shù)進(jìn)行傳遞,可以達(dá)到是事半功倍的效果。
6. 經(jīng)驗(yàn)分享
例如上面的我的第一個(gè) Shell 腳本例子,再次只是拋磚引玉作用,我們還可以舉一反三思考更多的用處,例如,可以獲取天氣,利用自制小工具來進(jìn)行 Shell 下快速翻譯等。
7. 小結(jié)
目前 Shell 的內(nèi)容非常多,其作為用戶和系統(tǒng)內(nèi)核的橋梁,其功能強(qiáng)大不言而喻,我們需要將有限的精力放在熱點(diǎn)知識(shí)上,好鋼用在刀刃上,注意學(xué)習(xí)方法學(xué)會(huì)舉一反三,這樣在后期的 Shell 學(xué)習(xí)中能夠更加地快速高效。