Linux下離線部署Node環境和前端服務

imJarvan發表於2018-10-10

背景說明

前端專案開發完成,需要部署在第三方伺服器。由於第三方伺服器是脫離公網的環境,所有的前端服務和所有的依賴都需要在離線環境中部署。記錄下解決方案,希望可以幫助到有類似需求的旁友。會涉及到基礎的Linux知識,對Linux不熟悉的童鞋可以先看看資料入門。

基本解決思路

  1. 把Node環境下載下來作為離線包備用。
  2. 本地構建前端程式碼,將所有前端構建產出以及node_modules依賴,node離線包全部打包成一個output.tar.gz
  3. 上傳到伺服器。
  4. 解壓,將node環境安裝到伺服器,執行。
  5. 要是都是指令碼控制就更完美了~

最終產出的output目錄內容

output
  bin      		// pm2 控制指令碼
  config 		// 配置檔案
  dist     		// webpack 產出
  node_modules  // 專案所有依賴,當然這裡面的內容可以只保留伺服器需要的依賴,根據需求定
  server  		// 代理伺服器,我想你的專案應該會用到
  thirdparty  	// 執行環境目錄,這裡是node-v8.x
  install.sh   	// 自動安裝node環境指令碼
複製程式碼

離線包製作步驟

這裡關於前端的webpack構建就不贅述了,直接看關鍵點:

  1. 準備node離線包。直接在Node官網下載圖示版本(這裡要根據需要下載Node的具體版本,我的專案用的是Node-LTS),這裡下載的是linux通用的可執行檔案,直接解壓就可執行,方便後續指令碼化操作。

    image.png

    1. 有了離線包,在上傳到伺服器之後肯定還要手動安裝啊,這個過程很機械,機械的東西就交給機器幹吧。準備一個node環境安裝指令碼output/install.sh,讓它來完成這些事情。由於下載的是可執行檔案,解壓後就相當於直接把node安裝到了 output/thirdparty目錄下,需要做的就是把node暴露給作業系統,讓它擁有node執行環境。常用的有兩種方法:
      • 新增全域性環境變數
      • 新增軟連結
    • 指令碼中有個問題,希望有大神能幫忙解答下,我把node環境變數新增到 /etc/profile後,使用 soure 呼叫了它,但是沒有生效,所以採用了軟連結的方法將node暴露在系統中。
    • 指令碼是在 CentOS7 中執行測試,開發時需要安裝虛擬機器模擬真實Linux環境,如果是mac,可能不能正常執行。具體安裝步驟,可自行百度。
    #!/bin/bash
    # install nodejs
    base_dir=$(dirname $(readlink -f $0))
    node_dir="node-v8.12.0-linux-x64"
    
    # 第一步:將node解壓到thirdparty,也就是當前資料夾
    
    if [ ! -d ${base_dir}/thirdparty/${node_dir} ]; then
      echo -e "\033[33m 正在解壓Node \033[0m"
      tar -xvf ${base_dir}/thirdparty/node-env.tar.xz -C ${base_dir}/thirdparty
      echo -e "\033[32m Node 解壓完成 \033[0m"
    else
      echo -e "\033[32m Node 已解壓完成 \033[0m"
    fi
    
    # 賦予執行許可權
    chmod u+x ${base_dir}/thirdparty/${node_dir}/bin/*
    
    #######問題########
    # 新增環境變數
    # export PATH=$PATH:${base_dir}/thirdparty/${node_dir}/bin
    # if [[ ! $PATH =~ "${base_dir}/thirdparty/${node_dir}/bin" ]]
    # then
    #   echo "export PATH=$PATH:${base_dir}/thirdparty/${node_dir}/bin" >> /etc/profile
    #   echo "Node 環境變數已新增"
    # fi
    
    # echo $PATH
    # source /etc/profile
    # echo $PATH
    #######問題########
    
    # 軟連結
    ln -sf ${base_dir}/thirdparty/${node_dir}/bin/node /usr/bin/node
    
    if [ -f /usr/bin/node ]; then
      echo -e "\033[32m Node 軟連結已新增 \033[0m"
    else
      echo -e "\033[31m Error: Node 軟連結新增失敗,確認是否以ROOT身份執行 \033[0m"
      exit
    fi
    
    # 聯動pm2控制
    if [ -f ./bin/control ]; then
      echo -e "\033[33m 啟動Server... \033[0m"
      ./bin/control start
      echo -e "\033[32m Server啟動成功,可使用./bin/control維護當前服務 \033[0m"
      ./bin/control help
    fi
    複製程式碼
  2. 在前端構建完成後把node壓縮包拷貝至output中。貼上我的構建指令碼build.sh(專案根目錄中),讓指令碼去執行npm install balabala... 可以參考下:

    #!/bin/sh
    echo $(date +"%Y-%m-%d %H:%M:%S") 'build begin'
    rm -rf node_modules
    echo $(date +"%Y-%m-%d %H:%M:%S") 'rm -rf node_modules end'
    npm install
    echo $(date +"%Y-%m-%d %H:%M:%S") 'install end'
    mkdir output
    echo $(date +"%Y-%m-%d %H:%M:%S") 'mkdir output end'
    npm run build
    echo $(date +"%Y-%m-%d %H:%M:%S") 'npm build end'
    # 將所有需要的檔案通通塞到output下
    cp -r build config node_modules server dist yunyi/bin thirdparty install output
    echo $(date +"%Y-%m-%d %H:%M:%S") 'move files end'
    # 給指令碼新增執行許可權
    chmod +x output/bin/control
    chmod +x output/install
    echo $(date +"%Y-%m-%d %H:%M:%S") 'build end'
    # GZ壓縮output
    tar -czvf output.tar.gz output
    複製程式碼
  3. 如果順利的話,執行完以上指令碼,你會在專案根目錄中發現一個output.tar.gz的檔案。至此,前端的離線部署包就完成了。

「真實」環境操作

  1. 這裡採用已經安裝好的虛擬環境CentOS7 , 有了虛擬環境,再把離線包複製到虛擬環境中,tar解壓之...
  2. 進入解壓出來的output中,你會看到 install
  3. 執行install指令碼安裝node,這裡注意要以root許可權執行,不然會報錯。如果終端中顯示 Node 軟連結已新增就說明node已經安裝完成了。
  4. 啟動你的server指令碼,我把維護server的指令碼(pm2操作)都放在了bin/controlinstall指令碼執行完畢後會呼叫這個檔案的start方法,這裡根據需求自行修改吧,執行如圖:
    image.png
  5. pm2控制指令碼
   #!/bin/sh
   cd "$(dirname $0)"/.. || exit 1
   PROC_NAME='proxy-server'
   
   help(){
       echo "${0} <start|stop|restart|status|monit|list|delete>"
       exit 1
   }
   
   status(){
       status=$(node_modules/pm2/bin/pm2 show $PROC_NAME | grep status | awk '{print $4}')
       echo $status
       if [ X"$status" == X"online" ]; then
           return 0
       else
           return 1
       fi
   }
   
   start(){
       node_modules/pm2/bin/pm2 set pm2-logrotate:max_size 100M
       node_modules/pm2/bin/pm2 set pm2-logrotate:retain 15
       node_modules/pm2/bin/pm2 start ./server/app.js --name $PROC_NAME -l "../log/nf1-server"
   }
   
   list(){
       node_modules/pm2/bin/pm2 list $PROC_NAME
   }
   restart(){
       node_modules/pm2/bin/pm2 restart $PROC_NAME
   }
   monit(){
       node_modules/pm2/bin/pm2 monit $PROC_NAME
   }
   stop(){
       node_modules/pm2/bin/pm2 stop $PROC_NAME
   }
   delete(){
       node_modules/pm2/bin/pm2 delete $PROC_NAME
   }
   
   case "${1}" in
       monit)
           monit
           ;;
       list)
           list
           ;;
       start)
           start
           ;;
       stop)
           stop
           ;;
       delete)
           delete
           ;;
       status|health|checkhealth|st)
           status
           ;;
       restart)
           restart
           ;;
       *)
           help
           ;;
   esac
   
複製程式碼

參考資料

Shell指令碼入門

Linux環境變數

Node服務一鍵離線部署

相關文章