1. 程式人生 > >Windows 10 用於 Linux 子系統的一鍵構建、打包指令碼「 Node、Gradle 專案」

Windows 10 用於 Linux 子系統的一鍵構建、打包指令碼「 Node、Gradle 專案」

最近正在開發一個 Java & Vue.js 全棧專案,該專案由以下幾部分組成:Java 後端伺服器、基於 Vue.js 的單頁應用、基於 JavaFX 的 GUI 客戶端以及其他輔助工具等。

其中 Java 服務端及客戶端均依賴公共的 Jar 包,基於 Vue.js 構建生成的靜態檔案亦須轉移至後端模組的相關目錄中,由後端模組附帶的 Web 伺服器管理。如果對專案中的某個子模組進行修改,需要對其手動編譯、移動,再對父模組進行編譯,操作繁瑣,本文探討通過 Windows 10 的 Linux 子系統執行 Shell 指令碼簡化上述操作並進行擴充套件。

之前的一篇文章已探討過 Linux 子系統的使用及在該系統下,Java、Node.js、Gradle 等工具的配置,本文不再贅述。本文開篇首先優化 Linux 子系統「Windows Subsystem for Linux (WSL) 」的使用體驗,

1. 使用 wsl-terminal 增強 WSL 的使用體驗

wsl-terminal 是專門為 WSL 準備的終端模擬器,主體是 mintty,另外整合了一些相當友好的特性,使用起來非常方便,也是目前使用者體驗最好的,推薦使用。

感覺自從用上了 wsl-terminal,完全同時獲得了 Windows 10 優異的介面效果和娛樂性,以及 Linux 的專業性和效率,並且兩者能夠完美融合在一起,完全可以取得好於 macOS 的使用體驗「此處為 YY,我未深度使用過 macOS,坐等打臉」。

wsl-terminal 主要具有如下特性:

  • 優秀的相容性(中文顯示/輸入、 24 位顏色、命令輸出等都正常了)。
  • 體積小巧,壓縮包僅 1.7 M 多,解壓後不到 10 M 。
  • 配置簡單, mintty 可以直接在標題欄右鍵配置, wsl-terminal 的配置檔案也很簡單。
  • 可以直接在資源管理器右鍵開啟終端模擬器並定位到當前目錄。
  • 可以將 .sh/.py/.pl 指令碼關聯到用 wsl-terminal 執行。
  • 可以將文字檔案關聯到用 wsl-terminal 裡的 vim 執行。
  • 支援 tmux ,可以在 tmux 裡開啟新目錄,恢復已有的 tmux 會話等。
  • 支援在 WSL 裡直接執行 Windows 程式。

注: 本小節摘抄了 這篇部落格 的部分內容。

2. 全棧專案的整體架構

專案的整體架構如下圖所示:

工程整體構架圖

3. 特定指令碼指令及其含義

3.1 獲取當前 Shell 指令碼所在的絕對路徑

dirname file # 獲取 file 檔案的相對路徑
echo $0      # 獲取當前執行的指令碼檔名
pwd          # 顯示當前工作目錄

由以上命令可總結出,獲取當前 Shell 指令碼所在的絕對路徑的命令如下:

SH_PATH=$(cd `dirname $0`; pwd)

3.2 Web 靜態檔案

Gradle / Spring 工程中,./src/main/resources/static 目錄下可存放靜態檔案,在服務端程式執行時,即可獲取此目錄下的靜態檔案,所以需要將通過 Webpack 編譯、構建生成的靜態檔案存放在該目錄下。

cp -r ./dist/* $SERVER_PATH/src/main/resources/static  # 將靜態檔案複製到指定位置

靜態檔案放在服務端工程的指定位置

3.3 獲取 Gradle 構建生成的目標 Jar 檔案的檔名

執行 gradle build 後,即可在 $PROJECT/build/libs 中生成目標 Jar 檔案,獲取該檔案的檔名,以備之後生成 Jar 執行指令碼所用:

NAME=`ls $PROJECT/build/libs`  # 獲取當前目錄下唯一的檔案的檔名

3.4 獲取該指令碼執行時的時間

各工程模組均編譯、構建完畢後,需要統一存放在同一個目錄中,各個時期生成的目錄以時間命名進行區分。

BUILD_TIME=`date "+%Y-%m-%d_%H-%M"`  # 獲取指令碼執行時的時間

4. 該專案的一鍵構建、打包 Shell 指令碼

4.1 指令碼具體執行流程

  1. 清理各個工程的歷史構建快取
  2. 編譯 Web 工程生成靜態檔案,移入後端工程相應目錄。
  3. 編譯公共依賴 Jar 包,移入後端工程、客戶端工程相應目錄。
  4. 編譯後端工程、客戶端工程。
  5. 後端工程、客戶端工程編譯後生成的 Jar 檔案移入打包目錄中,該目錄以指令碼執行時的時間作為區分。

該指令碼的具體執行流程如下圖所示,具體步驟如下:

指令碼執行流程

4.2 一鍵構建、打包指令碼

本文已經將指令碼的重點、流程等內容進行了詳細的介紹,現在貼出指令碼具體內容,如下所示:

#!/bin/bash
# 叢集裝置管理系統工程的 web 端、模擬客戶端、伺服器端等的整體清理、構建、打包、釋出

PROJECT_PATH=/mnt/d/project/ClusterDevicePlatform;       # 主工程所在目錄
WEB_PATH=/mnt/d/project/cluster-device-platform-web;     # Web 模組所在目錄
SH_PATH=$(cd `dirname $0`; pwd)                          # 指令碼所在目錄
BUILD_TIME=`date "+%Y-%m-%d_%H-%M"`                      # 指令碼執行時間
UTIL_JAR_PATH=$PROJECT_PATH/messageUtils;                # 公共 Jar 模組所在目錄
SERVER_PATH=$PROJECT_PATH/ClusterDevicePlatform-server;  # 伺服器模組所在目錄
CLIENT_PATH=$PROJECT_PATH/ClusterDevicePlatform-client;  # 硬體模擬客戶端模組所在目錄

# 專案已編譯歷史檔案的清理
cd $UTIL_JAR_PATH;
rm -rf ./build;
cd $CLIENT_PATH;
rm -rf ./build;
cd $SERVER_PATH;
rm -rf ./build;
rm -rf ./src/main/resources/static;
cd $WEB_PATH;
rm -rf ./dist;

# Web 編譯並將靜態頁面檔案移入伺服器專案中
npm run build
if [ ! $? -eq 0 ]
then echo "Web 編譯出錯"
    exit 1
fi
echo Web 編譯完畢
mkdir $SERVER_PATH/src/main/resources/static
cp -r ./dist/* $SERVER_PATH/src/main/resources/static

# Client、Server 的編譯
cd $UTIL_JAR_PATH;
gradle build

cd $CLIENT_PATH;
gradle build

cd $SERVER_PATH;
gradle build

# 組織並集中編譯生成的待發布檔案
mkdir -p $PROJECT_PATH/publish/release/serverRelease_$BUILD_TIME
cd $PROJECT_PATH/publish/release/serverRelease_$BUILD_TIME
cp $CLIENT_PATH/build/libs/* .
cp $SERVER_PATH/build/libs/* .
cp $SH_PATH/template/* .

# 組裝 Client、Server 的執行指令碼
CLIENT_NAME=`ls $CLIENT_PATH/build/libs`
SERVER_NAME=`ls $SERVER_PATH/build/libs`

echo chcp 65001 >> run-client.ps1
echo java -jar -\'Dfile.encoding\'=UTF-8 .\\$CLIENT_NAME cdg-pc 100 >> run-client.ps1
echo '$x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")' >> run-client.ps1

echo chcp 65001 >> run-server.ps1
echo java -jar -\'Dfile.encoding\'=UTF-8 .\\$SERVER_NAME >> run-server.ps1
echo '$x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")' >> run-server.ps1

參考連結