:clap: 本系列持續更新中,歡迎關注:https://github.com/wi1dcard/laravel-deploy...。
由於課程上下文關聯比較緊密,在開始前請先閱讀 本文。
你的支援是我寫作的動力;關注我的客官們,請在右上角點個贊,將會讓文章在首頁展示,幫助更多人。
感謝 :clap: !
一鍵指令碼里都做了什麼?相信不少開發者有過這樣的疑問,在完全地熟悉 Shell 語法之前,許多奇葩的語句命令很難完全讀懂。在本節,我將大致剖析一鍵指令碼對我們的伺服器「進行了哪些改造」,為後文手動部署做好最基本的鋪墊。
流程解析
幾乎所有的一鍵指令碼,無外乎就是幫我們做兩件事:
- 安裝執行環境
- 配置執行環境
對於上節我們使用的指令碼,你可以在 這裡 檢視它的 安裝 流程,在 這裡 檢視到 配置 流程。
-
初始化
# 若出現錯誤則停止執行指令碼 set -e # 將變數 CURRENT_DIR 設定為指令碼所在的目錄 CURRENT_DIR=$( cd "$(dirname "${BASH_SOURCE[0]}")" ; pwd -P ) # 引入一些位於 common.sh 的公共函式,類似 PHP 的 require source ${CURRENT_DIR}/../common/common.sh # 判斷當前執行指令碼使用者是否為 root,若不是則報錯並推出 [ $(id -u) != "0" ] && { ansi -n --bold --bg-red "請用 root 賬戶執行本指令碼"; exit 1; } # 將變數 MYSQL_ROOT_PASSWORD 設定為 random_string 命令的返回值,也就是隨機字串 MYSQL_ROOT_PASSWORD=`random_string`
-
初始化系統
function init_system { # 將系統本地化配置修改為 en_US.UTF-8 export LC_ALL="en_US.UTF-8" echo "LC_ALL=en_US.UTF-8" >> /etc/default/locale locale-gen en_US.UTF-8 locale-gen zh_CN.UTF-8 # 設定系統時區為 Asia/Shanghai ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime # 「⚠️重點」更新本地軟體源,可理解為重新整理可安裝軟體的列表並記住它們的當前版本 apt-get update # 安裝名為 software-properties-common 的軟體包,用於配置第三方軟體源 apt-get install -y software-properties-common # 呼叫 init_alias 函式 init_alias }
function init_alias { # 配置名為 sudowww 的別名,用於快速切換為 WWW_USER 變數所代指的使用者 alias sudowww > /dev/null 2>&1 || { echo "alias sudowww='sudo -H -u ${WWW_USER} sh -c'" >> ~/.bash_aliases } }
-
初始化軟體源
function init_repositories { # 「⚠️重點」新增第三方軟體源,類似於配置 Packagist 映象 add-apt-repository -y ppa:ondrej/php add-apt-repository -y ppa:nginx/stable grep -rl ppa.launchpad.net /etc/apt/sources.list.d/ | xargs sed -i 's/ppa.launchpad.net/launchpad.proxy.ustclug.org/g' curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - echo "deb https://dl.yarnpkg.com/debian/ stable main" > /etc/apt/sources.list.d/yarn.list curl -s https://deb.nodesource.com/gpgkey/nodesource.gpg.key | apt-key add - echo 'deb https://mirrors.tuna.tsinghua.edu.cn/nodesource/deb_8.x xenial main' > /etc/apt/sources.list.d/nodesource.list echo 'deb-src https://mirrors.tuna.tsinghua.edu.cn/nodesource/deb_8.x xenial main' >> /etc/apt/sources.list.d/nodesource.list # 配置軟體源後立即更新 apt-get update }
-
安裝基礎軟體包
function install_basic_softwares { # 「⚠️重點」 # 安裝 curl,一款命令列 HTTP 客戶端,與 PHP 內的 cURL 擴充套件作用一致 # 安裝 git,可用於拉取原始碼等 # 安裝 build-essential,作為編譯其它軟體的必要基礎環境 # 安裝 unzip,可用於解壓 Zip 壓縮包 # 安裝 supervisor,可用於保證 Laravel 佇列處理器持續執行等 apt-get install -y curl git build-essential unzip supervisor }
-
安裝 PHP
function install_php { # 「⚠️重點」安裝 PHP 7.2、PHP 命令、PHP-FPM 以及一大堆常用 PHP 擴充套件。 apt-get install -y php7.2-bcmath php7.2-cli php7.2-curl php7.2-fpm php7.2-gd php7.2-mbstring php7.2-mysql php7.2-opcache php7.2-pgsql php7.2-readline php7.2-xml php7.2-zip php7.2-sqlite3 }
-
安裝其它軟體
function install_others { # 「⚠️重點」由於需要安裝 Nginx,故解除安裝 Apache apt-get remove -y apache2 # 配置 MySQL 密碼 debconf-set-selections <<< "mysql-server mysql-server/root_password password ${MYSQL_ROOT_PASSWORD}" debconf-set-selections <<< "mysql-server mysql-server/root_password_again password ${MYSQL_ROOT_PASSWORD}" # 安裝 Nginx、MySQL、Redis、Memcached、Beanstalkd、SQlite 3 apt-get install -y nginx mysql-server redis-server memcached beanstalkd sqlite3 # 「⚠️重點」將 /var/www 目錄的擁有者和擁有組分別配置為 WWW_USER 和 WWW_USER_GROUP 變數的值,通常均為 www-data chown -R ${WWW_USER}.${WWW_USER_GROUP} /var/www/ # 「⚠️重點」設定 Nginx 服務開機自啟 systemctl enable nginx.service }
-
安裝 Node.js 和 Yarn
function install_node_yarn { # 安裝 Node.js 和 Yarn apt-get install -y nodejs yarn # 配置 Yarn 國內映象源 sudo -H -u ${WWW_USER} sh -c 'cd ~ && yarn config set registry https://registry.npm.taobao.org' }
-
安裝 Composer
function install_composer { # 「⚠️重點」下載 Composer 的 PHAR 檔案 wget https://dl.laravel-china.org/composer.phar -O /usr/local/bin/composer # 「⚠️重點」給予該檔案可執行許可權 chmod +x /usr/local/bin/composer # 配置 Packagist 國內映象 sudo -H -u ${WWW_USER} sh -c 'cd ~ && composer config -g repo.packagist composer https://packagist.laravel-china.org' }
-
配置站點
# 讀入站點名(專案名) read -r -p "請輸入專案名:" project # 確保專案名正常,若包含非法字元則報錯並退出 [[ $project =~ ^[a-zA-Z\0-9_\-\.]+$ ]] || { ansi -n --bold --bg-red "專案名包含非法字元" exit 1 } # 讀入站點域名 read -r -p "請輸入站點域名(多個域名用空格隔開):" domains # 拼接站點根目錄 project_dir="/var/www/${project}" # 輸出資訊,以便使用者確認 ansi -n --bold --green "域名列表:${domains}" ansi -n --bold --green "專案名:${project}" ansi -n --bold --green "專案目錄:${project_dir}" # 確保使用者確認後繼續執行,否則退出 read -r -p "是否確認? [y/N] " response case "$response" in [yY][eE][sS]|[yY]) ;; *) ansi -n --bold --bg-red "使用者取消" exit 1 ;; esac # 「⚠️重點」讀入 Nginx 配置模板,並替換站點名、域名、根目錄 # 隨後寫入實際配置檔案 /etc/nginx/sites-available/<站點名>.conf cat ${CURRENT_DIR}/nginx_site_conf.tpl | sed "s|{{domains}}|${domains}|g" | sed "s|{{project}}|${project}|g" | sed "s|{{project_dir}}|${project_dir}|g" > /etc/nginx/sites-available/${project}.conf # 建立配置檔案軟連結,類似快捷方式 ln -sf /etc/nginx/sites-available/${project}.conf /etc/nginx/sites-enabled/${project}.conf # 輸出 ansi -n --bold --green "配置檔案建立成功"; # 建立站點根目錄,並分別配置目錄自身的擁有者和擁有組為 WWW_USER 與 WWW_USER_GROUP 變數的值 mkdir -p ${project_dir} && chown -R ${WWW_USER}.${WWW_USER_GROUP} ${project_dir} # 重啟 Nginx 服務 systemctl restart nginx.service # 輸出 ansi -n --bold --green "Nginx 重啟成功";
以上便是整個指令碼的核心程式碼;有些沒看懂?沒關係。你現在要做的是瞭解流程 —— 從乾乾淨淨的伺服器到完整的執行環境,需要做什麼?
因此,將以上程式碼簡化、總結,可歸納為:
- 初始化系統並安裝基礎軟體包
- 安裝 Nginx
- 安裝 PHP-FPM
- 安裝 Git 和 Composer
- 安裝其它可選軟體
- 配置 Nginx 站點
依舊存在的問題
雖然一鍵指令碼能夠幫我們完成大多數環境安裝與配置,相比 Web 皮膚在一定程度上更加安全,但它也存在著不可避免的問題:
- 維護困難 —— 需編寫大量判斷語句,除錯較為困難,且極易出現不相容。
- 無法定製 —— 難以處理環境定製化需求(例如測試環境與生產環境的不同配置),除非 Fork 修改原始碼倉庫並修改指令碼。
- 黑盒操作 —— 在指令碼執行過程中,它做了什麼?具體執行了那些命令?我們不得而知。
- 安全堪憂 —— 市面上幾乎所有一鍵指令碼均強行要求根使用者許可權(最高管理員),有潛在安全隱患。
- ...
在隨後的課程中,你將會切身感受到 —— 無論是編寫得多麼完善、在多少臺伺服器上測試通過的一鍵指令碼,都會有它十分受限的場景。實際上,目前已經存在不少方案能夠完美地解決這些問題;不過,在開始講解之前,我將先帶領大家按照剛剛歸納的步驟,一步一步地進行手動部署,在這個過程中,希望你能夠:
- 鞏固安裝、配置環境的流程思路
- 把流程轉化為具體命令,在腦海中形成大概的印象
所謂「無他,唯手熟爾」,勤動手、切勿畏懼報錯。如果你身處牆外,Google 和 StackOverflow 是你的好幫手;若是身處牆內,LearnKu(Laravel-China)也是不錯的選擇。善用搜尋引擎和社群,或是在本課程內提問,我將盡我所能答疑解惑。
準備好開始探險吧!
記住 —— 熟能生巧。
擴充:Cloud-Init
你是否聽說過 Cloud-Init?它的原理便是在伺服器啟動(首次執行)時,載入一段使用者自定義的指令碼並執行,與一鍵指令碼類似。但其執行過程完全無法除錯,若出現問題只能在伺服器啟動後檢視檔案日誌尋找線索,實在是萬分痛苦。因此,本課程將不講解採用 Cloud-Init 的部署方案,使用 Ansible 代替,敬請關注後續章節。