2021年2月22日 星期一

在 Ubuntu 上建立自定義的 Shell Script 達成一鍵部屬 .Net Core 應用程式

之前曾經分享過如何透過 Nginx 伺服器在 Ubuntu 上部屬 .Net Core 應用程式,由於部屬方式是採用將應用程式包成檔案的方式再用 Git 上傳到伺服器上,因此每次應用程式在發布新版時,都要先下指令將應用程式暫停,然後處理版控及權限更改等相關指令,最後再下指令將應用程式啟動。這些動作偶爾做還好,但如果常做不免覺得有點浪費時間,所以自己寫了一個 Shell script 來整合上述過程中所有用到的指令碼,指令碼內容可以再視個人需求做相關的修改。


1. 編輯 sudoers 檔(非必要,只是確保等等執行指令時,不會發生權限相關的錯誤)

輸入以下指令

$ sudo visudo

然後在檔案最下面加入要執行 Script 的帳號,如下所示

# This file MUST be edited with the 'visudo' command as root.
#
# Please consider adding local content in /etc/sudoers.d/ instead of
# directly modifying this file.
#
# See the man page for details on how to write a sudoers file.
#
Defaults        env_reset
Defaults        mail_badpass
Defaults        secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin"

# Host alias specification

# User alias specification

# Cmnd alias specification

# User privilege specification
root    ALL=(ALL:ALL) ALL

# Members of the admin group may gain root privileges
%admin ALL=(ALL) ALL

# Allow members of group sudo to execute any command
%sudo   ALL=(ALL:ALL) ALL

# See sudoers(5) for more information on "#include" directives:

#includedir /etc/sudoers.d

# 加入以下這行並將 {your_account_name} 改成你的帳號名稱
{your_account_name} ALL=(ALL) NOPASSWD:ALL

然後鍵入 Ctrl + X 按 Y 後存檔離開即完成

P.S. 這邊要提醒一下,最好是將要修改的部分放在 /etc/sudoers.d 資料夾下的相關檔案裡,這邊是為了示範所以才直接修改sudoers檔,然後也請一律使用 visudo 指令來修改該檔,以免造成不可挽回的錯誤(這又是另一個故事了…)


2. 建立 Shell Script 檔

使用 vi 編輯器建立檔案並編輯(這邊先假設您的網站皆部署在位置 /var/www 下)

$ vi deploy.sh


貼上以下程式碼

#!/bin/bash

# $1 為取得第一個引數,$2 則為第二個引數,依此類推...
# 將多餘的 / 拿掉,1個 / 為只取代第一個符合的字符串,2個 / 為取代所有符合字符串
# e.g. my_app_name/_/- 結果為 my-app_name,my_app_name//_/- 結果為 my-app-name
app_name=${1////}
app_service_name=${2////}   

# 由於該 script 需輸入 1 ~ 2 個引數,所以要先檢查使用者是否有輸入
if [ -z "$app_name" ] 
then
   echo    
   echo "************************** Error ***************************"
   echo "App name or directory name is required! e.g. www_appname_com"
   echo "************************************************************" 
   echo
   exit 1
fi    

# 設定系統服務名稱 
if [ -z "$app_service_name" ] 
then
   # 由於我專案目錄名稱和系統服務名稱兩者之命名方式是有關聯的,因此第二個引數可以不必給予並使用取代方式將差異的地方做更換,這邊可視個人需求做調整
   app_service="${app_name//_/-}.service"
else
   # 若第二個引數有給予則使用該值
   app_service="${app_service_name}.service"
fi      

# 專案根目錄,就是含有 Git 的目錄
app_dir=/var/www/"${app_name}"

# 檢查專案目錄及系統服務檔是否存在
if ! [ -d "$app_dir" ] || ! [ -f "/etc/systemd/system/$app_service" ];
then
  echo
  echo "************************* Error **************************"
  echo "The ${app_dir} directory or ${app_service} file not exist!"
  echo "**********************************************************"
  echo
  exit 1
fi

# 停止應用程式服務,也可透過 $? 來檢查(上一個)指令的離開狀況,正常會回傳 0,錯誤則是 1 或 2
if ! (systemctl stop "${app_service}");
then
  echo
  echo "******* Error ********"
  echo "Stop the service fail!"
  echo "**********************"
  echo 
  exit 1
fi

# 重置 Repository 下所有檔案狀態(將變更的權限狀態還原)
if ! (git -C "${app_dir}" reset --hard);
then    
  echo    
  echo "******* Error ********"
  echo "Reset repository fail!"
  echo "**********************"
  echo        
  exit 1
fi

# 更新應用程式
if ! (git -C "${app_dir}" pull); 
then    
  echo
  echo "******* Error *******"
  echo "Pull repository fail!"
  echo "*********************"
  echo
  exit 1
fi

# 修改 Repository 下所有檔案權限
owner_group="root:www-data"
if ! (chown -R $owner_group $app_dir) || ! (chmod 775 -R $app_dir);
then
    echo "*********************************************************"    
    echo "Resetting ownership to ${owner_group} on ${app_dir} fail!"
    echo "*********************************************************"
    exit 1
fi

# 重新啟動應用程式服務    
if ! (systemctl start "${app_service}");
then
  echo
  echo "******** Error ********"
  echo "Start the service fail!"
  echo "***********************"
  echo
  exit 1
fi

# 完成  
echo
echo "**************** Success ****************"
echo "Congratulations! Your deployment is done!"
echo "*****************************************"
echo
exit 0


3. 執行 Shell Script 檔

最後就是要來執行我們剛剛建立的 Script 檔,這邊有兩種方式,第一種為在檔案當前目錄下直接在終端機(Terminal)裡鍵入以下指令即可(2擇1)

# 只輸入1個引數  
$ ./deploy.sh app_directory_name

# 輸入2個引數  
$ ./deploy.sh app_directory_name service_name   

第二種為建立常駐的 Bash Shell 別名,使用起來就像是呼叫系統內建的指令一樣

# 先依序執行以下指令  
$ cd ~
$ vim .bashrc

檢查有沒有以下這段內容,若沒有則在檔案末處加上並存檔離開

if [ -f ~/.bash_aliases ]; then
    . ~/.bash_aliases
fi  

編輯或新增 .bash_aliases 檔

$ vim .bash_aliases

在檔案末處加入以下內容

alias deploy='sudo /var/www/deploy.sh'  # /var/www/deploy.sh 該路徑請依據你 Script 檔的位址來做修改

存檔後離開,最後執行以下指令

$ source .bashrc

現在直接輸入deploy <app_directory_name>或是deploy <app_directory_name> <service_name> 即可直接執行我們建立的 Script 了!




參考資料

[Howto] How to create a permanent Bash alias on Linux/Unix

[鳥哥的 Linux 私房菜] 學習 Shell Scripts

訪客統計

103262