Shell框架

項目地址 https://github.com/chen-shang/BaseShell

 ____                      _          _ _
| __ )  __ _ ___  ___  ___| |__   ___| | |
|  _ \ / _` / __|/ _ \/ __| '_ \ / _ \ | |
| |_) | (_| \__ \  __/\__ \ | | |  __/ | |
|____/ \__,_|___/\___||___/_| |_|\___|_|_|
init.gif

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
  1. 解釋器聲明

對應上面示例腳本第一行

【推薦】首行寫法 #!/usr/bin/env bash

  1. shellcheck 忽略

對應上面示例腳本第二行

【強制】寫好腳本后,使用shellcheck進行語法檢查

  1. 防止循環(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)的方案。

  1. 引用各種工具類,類似于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
  1. 接下來是main入口函數(shù)和業(yè)務代碼

【推薦】Service包中的業(yè)務代碼都推薦寫入main

  1. 寫在最后
#===============================================================================
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í)行。


annotation.jpg

集合處理腳本【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ù)。。。明天再寫

并發(fā)工具【Concurrent】

鎖【Concurrent】

Object工具【Lang】

數(shù)學工具【Lang】

常量【Constant】

字符串工具【Lang】

SSH【Ssh】

Starter包【Starter】

工具包【Utils】

測試【Utils】

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

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

  • 官網(wǎng) 中文版本 好的網(wǎng)站 Content-type: text/htmlBASH Section: User ...
    不排版閱讀 4,711評論 0 5
  • mean to add the formatted="false" attribute?.[ 46% 47325/...
    ProZoom閱讀 3,197評論 0 3
  • //Clojure入門教程: Clojure – Functional Programming for the J...
    葡萄喃喃囈語閱讀 4,044評論 0 7
  • 第 2 章 SHELL 基礎(chǔ)知識2.1 shell腳本我們在上面簡單介紹了一下什么是shell腳本,現(xiàn)在我們來進一...
    LiWei_9e4b閱讀 1,644評論 0 0
  • 原文地址Shell是用戶與Linux或Unix內(nèi)核通信的工具,shell編程指的并不是編寫這個工具,而是指利用現(xiàn)有...
    MrRobot閱讀 12,040評論 5 30

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