項目地址 https://github.com/chen-shang/BaseShell
____ _ _ _
| __ ) __ _ ___ ___ ___| |__ ___| | |
| _ \ / _` / __|/ _ \/ __| '_ \ / _ \ | |
| |_) | (_| \__ \ __/\__ \ | | | __/ | |
|____/ \__,_|___/\___||___/_| |_|\___|_|_|

BaseShell使用教程
我寫這套框架的初衷在于豐富自己的shell腳本庫,以期在寫一些簡單腳本輔助開發(fā)時候能夠像使用Java類庫一樣方便。同時為了寫出類Java的工具類,這會強迫自己深入學習Java的源代碼。
所以Java是我的第一語言,Scala作為第二語言,忠實的shell粉,但不排斥其他編程語言。這是我對編程語言的態(tài)度。
BaseShell類似于Java語言的SDK是為Shell腳本語言提供的一套工具庫,涵蓋多種類Java工具的實現(xiàn)
.
├── Annotation #函數(shù)參數(shù)校驗腳本
| └── BaseAnnotation.sh
├── Collection #集合處理腳本
| ├── BaseArrayList.sh
| ├── BaseHasMap.sh
| └── BaseMap.sh
├── Concurrent #并發(fā)控制腳本
| ├── BaseLock.sh
| ├── BaseThreadPool.sh
| └── BaseThreadPoolExecutor.sh
├── Constant #自定義常量
| └── BaseConstant.sh
├── Date #日期處理腳本
| ├── BaseLocalDate.sh
| ├── BaseLocalDateTime.sh
| ├── BaseLocalTime.sh
| ├── BaseMonth.sh
| ├── BaseTimeUnit.sh
| ├── BaseTimestamp.sh
| └── BaseWeek.sh
├── File #文件處理腳本
| ├── BaseFile.sh
| └── BaseTable.sh
├── Lang
| ├── BaseMath.sh
| ├── BaseObject.sh
| └── BaseString.sh
├── Log #日志腳本
| └── BaseLog.sh
├── Ssh #ssh工機具
| └── BaseSsh.sh
├── Starter #包導入輔助腳本
| ├── BaseDateTimeStarter.sh
| ├── BaseEnd.sh
| ├── BaseHeader.sh
| ├── BaseStarter.sh
| ├── BaseTestEnd.sh
| └── BaseTestHeader.sh
├── Test #單元測試腳本
| ├── BaseAnnotationTest.sh
| ├── BaseArrayListTest.sh
| ├── BaseLocalDateTest.sh
| ├── BaseLocalDateTimeTest.sh
| ├── BaseLocalTimeTest.sh
| ├── BaseLockTest.sh
| ├── BaseLogTest.sh
| ├── BaseMapTest.sh
| ├── BaseMiniTest.sh
| ├── BaseObjectTest.sh
| ├── BaseRandomTest.sh
| ├── BaseStringTest.sh
| ├── BaseTableTest.sh
| ├── BaseThreadPoolExecutorTest.sh
| ├── BaseThreadPoolTest.sh
| ├── BaseUuidTest.sh
| └── table
├── Utils #輔助工具腳本
| ├── BaseCodec.sh
| ├── BaseRandom.sh
| └── BaseUuid.sh
├── Banner #項目頭圖
├── config.sh #項目配置文件
├── init.sh #項目初始化腳本
├── BaseShellMini.sh #常用最小引入腳本
└── readme.md #項目介紹
目前還在完善當中。旨在簡化shell腳本的編寫、提高shell腳本的健壯性。豐富的腳本庫可以大大減少shell腳本編寫的難度,其類Java的實現(xiàn)方式可以使得面向?qū)ο蠓妒降某绦騿T很快的理解并使用。與之相配套的我會出一篇《Shell編程規(guī)約》,以期規(guī)范Shell腳本程序員的書寫習慣。
初始化項目
cd ~
mkdir shell && cd shell #新建一個script目錄用于存放所有的腳本
git clone https://github.com/chen-shang/BaseShell.git
sh $(pwd)/BaseShell/init.sh
根據(jù)提示輸入 project[項目目錄] 和 module[模塊名稱]
看到如下輸出,則新建項目成功
> sh $(pwd)/BaseShell/init.sh
project[項目目錄]:com.baseshell.learn
module[模塊名稱]:Script
./../../com.baseshell.learn
├── BaseShell -> /Users/chenshang/shell/BaseShell
└── Script
├── Resources
├── Service
| └── Main.sh
├── Test
├── Utils
├── config.sh
└── readme.md
6 directories, 3 files
運行項目
【強制】運行shell腳本要到腳本目錄下執(zhí)行
cd com.baseshell.learn/Script/Service/
sh Main.sh
看到如下輸出,說明項目運行ok,之后可以愉快的寫腳本了
____ ____ _ _ _
| __ ) __ _ ___ ___/ ___|| |__ ___| | |
| _ \ / _` / __|/ _ \___ \| '_ \ / _ \ | |
| |_) | (_| \__ \ __/___) | | | | __/ | |
|____/ \__,_|___/\___|____/|_| |_|\___|_|_|
hello world
目錄結(jié)構(gòu)
./../../com.baseshell.learn 項目目錄
├── BaseShell -> /Users/chenshang/shell/BaseShell BaseShell的源碼軟鏈
└── Script 模塊目錄:一般建議大寫,代表一個Shell模塊,里面專門是針對某個模塊兒的腳本
├── Resources 資源目錄:資源目錄: 一般放一些文本文件、圖片、csv等非腳本文件
├── Service 項目目錄:項目相關(guān)腳本所在的文件,如果想要寫一些輔助的腳本,建議與Service同級創(chuàng)建一個文件夾來寫
| └── Main.sh
├── Test 測試目錄:對腳本中的函數(shù)進行單元測試的腳本
├── Utils 工具目錄:工具類
├── config.sh 配置文件:項目的配置文件包括 頭圖、日志級別等以及一些項目中用到的配置項
└── readme.md 描述文件:項目名稱、項目介紹等等
└── Module2 模塊二
6 directories, 3 files
BaseShell相當于Java的JDK.
配置文件:
【推薦】config.sh 腳本中盡量之定義變量,不要定義函數(shù)或可執(zhí)行命令,類比Java項目中的properties
描述文件: 項目的描述文件
功能介紹
腳本應該怎么寫-示例
#!/usr/bin/env bash
# shellcheck disable=SC1091,SC2155
#===============================================================
import="$(basename "${BASH_SOURCE[0]}" .sh)_$$"
if [[ $(eval echo '$'"${import}") == 0 ]]; then return; fi
eval "${import}=0"
#===============================================================
source ./../../BaseShell/Starter/BaseHeader.sh
source ./../config.sh
#導入工具包
#===============================================================================
#業(yè)務代碼
main(){
echo "hello world"
}
#===============================================================================
source ../../BaseShell/Starter/BaseEnd.sh
- 解釋器聲明
對應上面示例腳本第一行
【推薦】首行寫法 #!/usr/bin/env bash
- shellcheck 忽略
對應上面示例腳本第二行
【強制】寫好腳本后,使用shellcheck進行語法檢查
- 防止循環(huán)引用代碼段
對應上面示例腳本3-7行
#===============================================================
import="$(basename "${BASH_SOURCE[0]}" .sh)_$$"
if [[ $(eval echo '$'"${import}") == 0 ]]; then return; fi
eval "${import}=0"
#===============================================================
這段代碼的作用是為了預防 像 A腳本引用B腳本,B腳本又引用A腳本導致的循環(huán)引用問題。其原理是以文件名定義一個變量,引用過之后變量的值設(shè)置為0,再次引用的時候直接return,注意再次引用的時候是直接return不是exit. 詳細用法,后面會有展開。
這段代碼目前是我能想到的最精簡的方式,不排除以后有更優(yōu)的方案。
- 引用各種工具類,類似于Java中的import
#===============================================================
source ./../../BaseShell/Starter/BaseHeader.sh
source ./../config.sh
#導入工具包
#===============================================================================
引用第三方腳本使用source命令,相當于Java的import關(guān)鍵字
source ./../../BaseShell/Starter/BaseHeader.sh,source ./../config.sh這兩個是必須要引用的,且放在所有引用的開頭。
source ./../config.sh 則是為了因為當前項目的配置文件,我們對項目的全局配置變量都在這里面定義
source ./../../BaseShell/Starter/BaseHeader.sh 目的是引入BaseShell框架. 相當于引用下面四個包
source ./../../BaseShell/Lang/BaseObject.sh
source ./../../BaseShell/Log/BaseLog.sh
source ./../../BaseShell/Annotation/BaseAnnotation.sh
source ./../../BaseShell/Lang/BaseString.sh
- 接下來是main入口函數(shù)和業(yè)務代碼
【推薦】Service包中的業(yè)務代碼都推薦寫入main
- 寫在最后
#===============================================================================
source ../../BaseShell/Starter/BaseEnd.sh
這樣直接執(zhí)行腳本的時候,會先尋找腳本里面的main函數(shù)去執(zhí)行,類似運行一個Java Class類中的main方法
如何引用包
我們規(guī)定項目目錄最大深度為2層,也就是不允許在Service同級的目錄下在創(chuàng)建目錄然后在里面寫腳本
引用包使用source命令
source 第三方腳本會使第三方腳本從頭到尾加載一遍,遇到函數(shù)就加載函數(shù)、遇到變量就加載變量、遇到可執(zhí)行的命令就會執(zhí)行,這個命令其實就是把第三方腳本定義的函數(shù)、全局變量加載到當前腳本的上下文中
這里推薦使用相對路徑,因為使用絕對路徑,IDEA無法進行代碼提示,也是醉了
示例
如果想引入日期相關(guān)的函數(shù) source ./../../BaseShell/Date/BaseLocalDate.sh
如果想引入文件相關(guān)的函數(shù) source ./../../BaseShell/File/BaseFile.sh
函數(shù)參數(shù)校驗腳本【Annotation】
.
├── Annotation #函數(shù)參數(shù)校驗腳本
| └── BaseAnnotation.sh
默認自動引入,此包下的工具是用來進行函數(shù)參數(shù)校驗的,類似Spring中的Validate的功能。一旦參數(shù)校驗沒有通過則會終止函數(shù)的執(zhí)行。 所有方法都是以 _ 開頭的,類似于Java中的@
曾想用@開頭,但發(fā)現(xiàn)@在shell中屬于特殊字符,不允許出現(xiàn)在函數(shù)命中,斟酌再三選擇了_
| 方法 | 表頭 | 備注 |
|---|---|---|
| _NotBlank | 入?yún)?shù)不為空(空或空字符串) | - |
| _Natural | 入?yún)?shù)為自然數(shù)(0,1,2,3...) | - |
| _Min | 最大不得小于此最小值 | - |
| _Max | 最大不得超過此最大值 | - |
示例
# 將文件內(nèi)容讀進內(nèi)存
function ssh_checkLogin(){ _NotBlank "$1" "ip can not be null" && _NotBlank "$2" "port can not be null" && _NotBlank "$3" "user can not bull" && _NotBlank "$4" "pass can not bull"
local ip=$1 ;local port=$2 ;local user=$3 ;local pass=$4
}
一般函數(shù)的參數(shù)校驗,我一般和函數(shù)也在一行上,第二行用具體的變量名接收參數(shù)。上面的函數(shù)如果有某個參數(shù)沒有傳,函數(shù)會異常退出,下面的代碼也不會執(zhí)行。

集合處理腳本【Collection】
├── Collection
| ├── BaseArrayList.sh
| ├── BaseHasMap.sh
| └── BaseMap.sh
默認自動引入,此包下的工具是用來對集合 和 Map 進行操作的。
BaseArrayList.sh
| 方法 | 表頭 | 備注 |
|---|---|---|
| new_arrayList | 新建一個list | - |
| list_add | 添加元素 | - |
| list_set | 設(shè)置元素 | - |
| list_removeByIndex | 按照下標移除元素 | - |
| list_removeByValue | 按照值移除元素 | - |
| list_get | 按照下標獲取元素 | - |
| list_forEach | 對列表中的每一個元素都進行操作 | - |
| list_size | 獲取當前l(fā)ist的元素個數(shù) | - |
| list_isEmpty | 判斷當前l(fā)ist是否為空 | - |
| list_contains | 判斷當前l(fā)ist是否包含某元素 | - |
| list_clear | 清空當前l(fā)ist | - |
| list_indexOf | 獲取指定元素的下標 | 從前往后第一個 |
| list_lastIndexOf | 獲取指定元素的下標 | 從后往前第一個 |
| list_sub | 截取指定下標的元素 | - |
| list_copy | 賦值一個新的數(shù)組 | - |
| list_values | 獲取元素的值列表 | - |
| list_mapper | 最每一個元素進行操作并返回一個新的列表 | - |
| list_reducer | 聚類操作 | - |
日志工具【Log】
如何引入
source ./../../BaseShell/Starter/BaseHeader.sh默認會引入Log框架source ./../../BaseShell/Log/BaseLog.sh 無需手動引入
默認配置
兩個系統(tǒng)默認配置,在 config.sh 配置文件中,用戶可根據(jù)自己的意愿修改
# 日志記錄位置
LOG_DIR="${HOME}/.baseshell"
# 日志級別
LOG_LEVEL=SYSTEM
使用方法
支持固定文本
log_debug "要記錄的日志內(nèi)容"
支持字符串插值
log_debug "要記錄的日志內(nèi)容. key=${key},value=${value}"
支持多參數(shù)
log_debug "要記錄的日志內(nèi)容." "1=$1" "2=$2"
支持函數(shù)
log_debug "要記錄的日志內(nèi)容." "now=$(date)" "index=$((i++))"
Log 包里面有8個方法
| 方法 | 配置文件配置 | 說明 |
|---|---|---|
| log_debug | LOG_LEVEL=DEBUG | 打印DEBUG級別的日志 |
| log_info | LOG_LEVEL=INFO | 打印INFO級別的日志,輸出顏色為白色 |
| log_success | LOG_LEVEL=INFO | 打印INFO級別的日志,輸出顏色為綠色 |
| log_fail | LOG_LEVEL=INFO | 打印INFO級別的日志,輸出顏色為紅色,并退出當前進程 |
| log_warn | LOG_LEVEL=WARN | 打印WARN級別的日志,輸出顏色為灰色 |
| log_error | LOG_LEVEL=ERROR | 打印ERROR級別的日志,輸出顏色為紅色 |
| log_system | LOG_LEVEL=SYSTEM | 打印SYSTEM級別的日志,輸出顏色為白色,是BaseShell使用的日志輸出格式 |
| log_trace | 只會記錄日志到文件,不會打印到控制臺 |
輸出示例
執(zhí)行Test下的測試用例,輸出如下
使用示例
使用示例
未完待續(xù)。。。明天再寫