2019年12月17日 星期二

使用 Homebrew 安裝 PHP


移除使用 Homebrew/PHP Tap 安裝的舊版本 PHP


自 2018 年 3 月 31 日起,原屬於 Main Taps 的 Homebrew/PHP 版本庫被封存;所有的 Formulae 會被遷移至主要版本庫 Homebrew/core 中或是被刪除。因為 Homebrew 不再支援舊的 Homebrew/PHP Tap,如果之前有使用 Homebrew/PHP Tap 安裝過 PHP,需要先將其完整的移除。如果是新安裝或是使用  Homebrew/core 安裝 PHP,可以跳過本小節。

首先,需要更新所有的 Formulae、升級已安裝的軟體、以及移除所有舊的 Formulae:
brew update
brew upgrade
brew cleanup


(Homebrew 的簡介請參考。)


檢查目前安裝的套件中有那些跟 PHP 有關聯:
brew list | grep php


找到已安裝的 PHP 以及相關的套件後,使用 brew uninstall 將它們解除安裝;例如,之前安裝了 PHP 5.6 以及延伸套件 xdebug:
brew uninstall --force php56 php56-xdebug
brew cleanup


可以再次檢查是否完整的移除相關的 PHP 套件:
brew list | grep php


最後,清除 PHP 設定檔:
rm -Rf /usr/local/etc/php/*



安裝 PHP


PHP 有多個發行分支 (Release Branch),分屬於不同的主要版本 (Major Version)。每一個發行分支都會有兩年的完整支援,再加上一年的關鍵安全問題支援。PHP 5 的最後一個發行分支 PHP 5.6 在 2018 年 12 月 31 日停止了所有的支援,使得目前仍有支援的主要版本只剩下了 PHP 7。下表列出了 PHP 目前支援的發行分支(參考自):


分支 初始發行日 完整支援到 安全問題支援到
7.2 2017 年 11 月 30 日 2019 年 11 月 30 日 2020 年 11 月 30 日
7.3 2018 年 12 月 6 日 2020  年 12 月 6 日 2021 年 12 月 6 日
7.4 2019 年 11 月 28 日 2021 年 11 月 28 日 2022 年 11 月 28 日


因為 PHP 7.2 的完整支援已經在 2019 年 11 月 30 日到期,所以目前 Homebrew/core 只提供 PHP 7.3 以及 PHP 7.4 的安裝。下列令可以安裝 Homebrew/core 上的 PHP 7.4:
brew update
brew upgrade
brew install php@7.41


註1. Homebrew 現在改用 "php@發行分支" (例如 PHP@7.3) 取代原來的 "PHP發行分支無句點" (例如 PHP74);如果不指定要安裝的發行分支,預設會安裝最新的發行分支。


使用 PHP 的 Apache 2 Handler 模組


在 "PHP 與伺服器之間的應用程式介面" 一文中,介紹了 PHP 共有 4 種不同 SAPIs。針對不同的開發環境,可以選擇適合的SAPI。如果是做為個人網頁開發,建議可以選擇設定上較為簡便的 Apache 2 Handler 模組


1. 設定 httpd.conf


根據 PHP 手冊,使用 PHP 的 Apache 2 Handler 模組,不建議 httpd 使用執行緒類型的 MPM (請參考);而且使用 Homebrew/core 安裝的 PHP 也不再支援執行緒安全 (Thread Safty) 選項2。因此,httpd 的 MPM 模組3使用預設的 Prefork 模組即可。


確認 httpd.conf 載入的是 Prefork 模組:
LoadModule mpm_prefork_module lib/httpd/modules/mod_mpm_prefork.so


要讓 httpd 能夠處理 php 文件,需要:
1) 在啟動時就戴入 Apache 2 Handler (libphp) 模組,
2) 讓 httpd 知道副檔名為 php 的檔案要交由 php 模組處理,
3) 執行完 php 後生成的文件的內容類型 (Content Type) 是 text/html。


在 IfModule mpm_prefork_module 區塊加上下列的設定4
<IfModule mpm_prefork_module>
    LoadModule php7_module /usr/local/opt/php/lib/httpd/modules/libphp7.so
    <FilesMatch \.php$>
        SetHandler application/x-httpd-php
    </FilesMatch>
    AddType text/html .php
</IfModule>



最後,確認 httpd 在尋找目錄首頁的順序與類別:
<IfModule dir_module>
    DirectoryIndex index.php index.html
</IfModule>


重新啟動 HTTP Server:
sudo apachectl -k stop
sudo apachectl start



2. 測試 PHP 網頁是否正常

在文件根目錄檔案夾新增 index.php,內容如下:
<?php

phpinfo();


在瀏覽器的網址列輸入:
http://localhost/info.php


應該可以看到系統和 PHP 的相關資訊。

(如果網站要提供服務給其他人,在測試完後記得要將 index.php 刪除。)


註2. 之前的 Homebrew/php tap 可以使用 --with-thread-safety 或是 --enable-maintainer-zts 選項,讓 Apache 2 Handler 模組可以在多執行緒環境下執行。

註3. 在 "Apache HTTP Server 的多程序處理模組 (Multi-Processing Module, MPM)" 一文中介紹了 httpd 在 unix 系統的 3 種 MPM。在不同的 MPM 模組下,要使用不同的 SAPI。

註4. 考量安全因素,建議使用 SetHandler 取代 AddHandler;因為使用 AddHandler 時只要檔案名稱中有 .php (例如 test.php.png),就會被送到 PHP 解析器執行。這讓惡意的使用者可以利用這個方式上傳惡意的程式碼,並且加以執行。

2019年12月13日 星期五

在 macOS 安裝 Apache HTTP Server


Apache HTTP Server (httpd) 是一款常見的開源網頁伺服器軟體。近年來面對 Nginx、IIS 等網頁伺服器軟體的競爭,仍然具有很高的市佔率。是不少的網頁開發套件 (例如,XAMPP) 內建的網頁伺服器。httpd 的設定問題容易在網路上找到相關的解決方法,適合做為小型開發專案或是輕量服務需求的網頁伺服器。

卸載 macOS 內建的 httpd


檢查 macOS 是否內建 Apache HTTP Server (httpd)1,並且已經將其載入到 Launchd:
sudo launchctl list | grep httpd


如果 macOS 有內建 httpd,並且已經將其載入到 Launchd 時;必須先將其從 Launchd 中卸載:
sudo apachectl stop
sudo launchctl unload -w /System/Library/LaunchDaemons/org.apache.httpd.plist 2>/dev/null


(launchctl 以及 Launchd 的簡介請參考。)


註1:配合 macOS Server 5.7 以後不再支援來自開源軟體的圖形化管理介面,從 macOS 10.14 開始,已不再內建 httpd (請參考 macOS Server 的前世今生)。


使用 Homebrew 安裝 httpd

安裝 httpd 最簡單的方式是使用網頁開發套件。但是,使用套件會有下列的缺點:打包好的軟體不一定包含需要的軟體、軟體的版本受到限制、更新的速度較慢等。為了安裝與管理應用程式,套件管理工具被廣為使用。其中 Homebrew 是 macOS 使用者最常使用的套件管理工具 (Homebrew 的簡介請參考)。


使用 Homebrew 安裝 httpd 只需要執行下列的命令:
brew update
brew upgrade
brew install httpd


Homebrew 會執行下列的安裝工作:
1. 安裝檔案夾在 /usr/local/Cellar/httpd/2.24.xx (xx為版本號碼),
2. 執行程式 (例如,apachectl、httpd 等) 會被符號連結 (symlink) 到 /usr/local/bin,
3. 設定檔則是放在 /usr/local/etc/httpd,
4. /usr/local/opt 檔案夾中的 apache-httpd、apache2、以及 httpd 是安裝檔案夾的符號連結。


我們可以透過執行 echo $PATH 檢查 PATH 環境變數的設定,確認在使用 apachectl 等命令時,會優先執行使用 Homebrew 安裝的 httpd:
echo $PATH
PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin


因為 /usr/local/bin 在路徑設定的最前面,所以被 symlink 到該檔案夾的命令會被優先執行。


安裝完成後可以執行下列的命令來啟動 httpd:
apachectl start


開啟瀏覽器,連線到 http://localhost:8080/,可以看到 It works! 的網頁。

注意:存取記錄 (Access Log) 跟錯誤記錄 (Error Log) 預設是記錄在 /usr/local/var/log/httpd/ 檔案夾,並且對應到 /private/var/log/apache2/ 檔案夾。如果之前已經使用過 root 啟動過 httpd,命令前面需要加上 sudo,不然執行 apachectl start 時會出現需要 root 權限的提示,執行 httpd -k start 時會出現 AH00091: httpd: could not open error log file /private/var/log/apache2/error_log.
解決的方法為使用 root 權限刪除記錄檔。

設定 httpd (修改 httpd.conf)


/usr/local/etc/httpd/httpd.conf 是 httpd 的主要設定檔。為了使用上的需求,我們需要修改某些設定。下面列出幾個常見的設定。


監聽埠

安裝完後的預設監聽埠是 8080,而不是常用的 80 埠;我們需要找到 httpd.conf 中的 Listen 設定,更改為監聽 80 埠:
Listen 80


伺服器名稱

當沒有在 httpd.conf 設定伺服器名稱時,在啟動或關閉 httpd 時會出現下列的訊息:
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using MacBook-Pro.local. Set the 'ServerName' directive globally to suppress this message


找到 ServerName 設定,取消註解並且改為下列的設定:
ServerName localhost


文件根目錄

做為個人開發平台,預設的文件根目錄 /usr/local/var/www,在文件的相關操作上會比較不方便。將文件根目錄改設為使用者家目錄下的 www 檔案夾,可以方便文件的編修以及檢視。找到 httpd.conf 中的 DocumentRoot 設定,指定文件根目錄到使用者家目錄下的檔案夾:

DocumentRoot "/Usrs/user_name/www"
<directory "/usr/local/www></directory>


在文件根目錄設定的下方會有一個針對該檔案夾的設定,我們需要改為新的文件根目錄:
<Directory "/Usrs/user_name/www">


注意:因為 macOS 的系統完整保護 (System Integrity Protection, SIP)機制,建議文件根目錄設定為使用者家目錄下的檔案夾,或是使用預設值。


在使用者家目錄建立文件根目錄檔案夾並且新增一個 index.html 檔案:
mkdir ~/www
echo "<h1>My Page</h1>" > ~/www/index.html



重新啟動 httpd:
sudo apachectl -k restart


注意:因為使用了 80 埠,此時命令要加上 sudo。


開啟瀏覽器,連線到 http://localhost/,可以看到 My Page 的網頁。



將 httpd 設定為開機時啟動的守護行程 (Daemon)


要讓 httpd 能夠在開機自動執行,可以執行下列的命令:
sudo brew services start httpd


brew services 的簡介可以參考這裡

安裝 Homebrew-services 後,也可以使用它將 httpd 從  Launchd 移除:
sudo brew services stop httpd


或是重新加入 Launchd:
sudo brew services restart httpd


將 httpd 設定為登入時啟動的任務項 (Agent)


要讓 httpd 能夠在登入後自動執行 (注意,此時 httpd.conf 中的監聽埠不可以小於 1024,LOG 檔的擁有者要是使用者),可以執行下列的命令:
brew services start httpd


安裝 Homebrew-services 後,也可以使用它將 httpd 從任務項中移除:
brew services stop httpd


或是重新加入任務項:
sudo brew services restart httpd


僅啟動 httpd


Homebrew-services 也可以只用來啟動 httpd:
brew services run httpd


brew services run 使用目前使用者的權限執行,所以要注意監聽埠、檔案夾權限等設定問題。



2019年12月12日 星期四

在 WSUS 伺服器環境中如何替 Windows 10 安裝 .net Framework 3.5

Windows 10 不再內建 .net Framework 3.5,如果需要使用 .net Framework 3.5 的功能,需要透過 [控制台/程式集/開啟或關閉 Windows 功能] 自行安裝。

如果內部有使用 WSUS 伺服器,在安裝 .net Framework 3.5 時,出現了 0X800F0954 的錯誤;代表 WSUS 伺服器無法讓你正確下載 .net Framework 3.5。那是因為 "Windows 10 Feature on Demand" 中的  .net Framework 3.5 只有支援到 Windows 10 1703。



可以使用下列兩種方式來解決這個問題:
1. 讓電腦離開網域,安裝完後再重新加入網域。

2. 讓電腦暫時不受 WSUS 伺服器管理。

(1) 在 [工作管理員/服務] 停用 wuauserv;

(2) 執行 regedit,展開至HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU,將 UseWUServer 的數值資料改成 0;

(3) 在 [控制台/程式和功能/開啟或關閉 Windows 功能],安裝 .net Framework 3.5;

(4) 執行 regedit,展開至HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU,將 UseWUServer 的數值資料改回來 1;

(5) 重新啟用 wuauserv。




另外,如果要安裝 XPS Viewer,記得在步驟 (3) 之後要執行下列的命令:

dism /Online /Add-Capability /CapabilityName:XPS.Viewer~~~~0.0.1.0

2019年11月7日 星期四

macOS Server 的前世與今生

雖然名稱為 macOS Server,這是一套只適合用來管理 Apple 自有服務的 Mac APP。

前世:Apple 的伺服器作業系統


相較於 Microsoft 的 Windows NT Server 作業系統,Apple 在早期也有一套伺服器作業系統,稱為 Mac OS X Server。兩者都是以圖形化介面來管理各種網路服務伺服器。不同的是 Windows NT Server 採用的是 "Wintel" 架構,系統可以安裝在不同廠商出品的 X86 主機上;而 Mac OS X Server 則是隨著 Apple 伺服器主機一起出售,或是購買後安裝在 Mac 主機上。


Apple 在 1999 年推出稱為 Mac OS X Server 的伺服器作業系統 (當時的桌面作業系統稱為 Mac OS X),並且在 2002 年推出名稱為 Xserve 的機架伺服器。作業系統並不支援中文,只有支援英文等少數的語系。Xserve 在售量上並不理想,經過了多次的更新後,在 2011 年停產。雖然 Apple 建議使用者可以選購安裝有 Mac OS X Server 的 Mac Pro、Mac Mini 或是 iMac Pro 主機做為替代,但是從 2011 年 (桌面作業系統為 Mac OS X Lion 10.7) 開始,Apple 不再販售可獨立安裝的 Mac OS X Server 作業系統,而是將 Mac OS X Server 的功能獨立成一個名稱為 OS X Server 的 APP,在 Mac App Store 上販售。隨著 OS X 在 2016 年更名為 macOS (Sierra 10.12),這個獨立的 APP 也被改名為 macOS Server。


早期的 OS X Server 使用圖形化介面來管理各種網路服務伺服器,除了 Apple 本身的服務外,這些伺服器還包含了 Apache HTTP Server (httpd)、MySQL1、RADIUS、BIND、以及 Sendmail 等服務。透過統一的圖形化介面,使用者不再需要透過繁雜的指令就能夠輕鬆的管理網路伺服器。不過,和 Windows Sever 自行開發各種伺服器軟體不同的是,這些伺服器軟體大多是源自於開源軟體,OS X Server 只是為這些伺服器軟體加上圖形化的管理介面。


註1:2009 年的 Mac OS X Server 10.6 (含) 以前的版本支援 MySQL,2011 年的 Mac OS X 10.7 Server (以 APP 型式發行的) 以後的版本則改用 PostgreSQL。可能是因為 2009 年 Oracle 收購了之前收購了 MySQL 的 SUN Microsystems。

今世:macOS Server


雖然改採 APP 的型式發行,macOS server 仍然會隨著 macOS 的更新而更新。從 OS X 10.10 Yosemite 開始,發行版號就不再跟 macOS 一樣,而是有自己的版號:OS X Server 4.0。一開始的 macOS Server 仍然提供來自開源軟體的伺服器的圖型化管理介面;但是從 2018 年發行的 macOS Server 5.7 (對應的是 macOS 10.14) 開始,這些伺服器軟體的圖型化管理介面都被移除了,只提供了 Open Directory、「描述檔管理程式」和 Xsan 管理等的管理介面2


所以,從 macOS Server 5.7 開始,雖然名稱為 macOS Server,但是卻只是一套只適合用來管理 Apple 自有服務的 Mac APP;跟之前的版本的功能有著非常顯著的不同。如果習慣舊有的 macOS Server 管理介面,macOS 就別升級到 macOS Mojave 10.14 或是更新的版本。至於 Mac App Store 目前 (2019/11/07) 只有最新的 macOS Server 5.9 可以購買。


註2:雖然 Apple 官方並沒有明說,不過一直以來 macOS Server 的伺服器軟體大多是源自於開源軟體,開源社群對此其實一直都有一些批評。

2019年10月28日 星期一

PHP 與伺服器之間的應用程式介面 (Server Application Programming Interface, SAPI)

PHP 和伺服器之間的應用程式介面 (Application Programming Interface, API) 可分為四種,分別為:共用閘道介面 (Common Gateway Interface, CGI)、伺服器應用程式介面 (Server Application Programming Interface, SAPI)、快速共用閘道介面 (Fast Common Gateway Interface, FastCGI)、以及命令列介面 (Command Line Interface, CLI) 等。透過這四種 API,可以在伺服器上執行 PHP 程式。

CGI

共用閘道介面 (Common Gateway Interface, CGI) 是一個用來在網頁伺服器上執行外部應用程式的標準協定 (Protocol)。早期要經由網頁伺服器執行其它的應用程式都需要透過 CGI。例如,當網頁服務收到具有 php 副檔名的頁面請求時,會啟動一個執行 php-cgi 的程序來處理 .php 網頁,並在網頁內容執行完畢後關閉該程序。


CGI 模式的執行流程為:
網頁伺服器收到請求 -> 啟動 php-cgi 程序 -> php-cgi 處理請求 -> 關閉 php-cgi


使用 CGI 的好處是穩定,當 PHP 網頁發生執行錯誤時只會影響 php-cgi,其它的程序不會受到影響。CGI 的主要缺點是執行效能,在每一次收到一個新的請求時,都要啟動一個執行 php-cgi 的程序,這個程序需要載入 PHP 的相關設定檔案以及所有的擴充。這樣的過程需要花費較多的時間以及伺服器資源。因此 Fork-and-Execute 模式成為 CGI 最為人所詬病的一個缺點。

SAPI

根據維基百科,伺服器應用程式介面 (Server Application Programming Interface, SAPI) 是網頁伺服器的直接模組介面,是一種由網頁伺服器所提供的應用程式介面,用來擴展網頁伺服器的功能1

不同的網頁伺服器所提供的介面並不相容,因此應用程式需要針對不同的網頁伺服器開發專用的 SAPI 模組 (因此 SAPI 模式也被稱為模組模式)。例如,PHP 針對 IIS2 以及 httpd3 等都有相對應的 SAPI 模組。SAPI 模組使用直接模組介面,所以只要將模組資訊寫入網頁伺服器的設定檔中,在網頁伺服器啟動時就會被載入。例如,將下列 PHP SAPI 模組資訊寫入 Apache HTTP Server (httpd) 的設定檔 httpd.conf 中,當重新啟動 httpd 時,PHP 的 SAPI 模組就會被載入:
LoadModule php7_module /usr/local/opt/php/lib/httpd/modules/libphp7.so


模組模式的執行流程為:
網頁伺服器收到請求 -> php 模組


使用 SAPI 模組執行 PHP 意謂著 PHP 會在網頁伺服器的程序中執行,而不再需要針對每個請求啟動一個新的程序。例如,當 httpd 採用 Prefork 模式4時,在啟動時就會預先 fork 一些子程序來等待請求,當有新的請求出現時,httpd 會調用閒罝的子程序來回應請求。這樣的過程可以減少啟動新程序所花費的時間以及降低伺服器的負載。

穩定性是使用 SAPI 模組會遭遇到的最大問題。因為 PHP 在網頁伺服器的程序中執行,當 PHP 應用程式出問題時,可能會使得網頁伺服器發生當機的情況。當 PHP 在執行時具有網頁伺服器程序的所有權限,這也會造成資訊安全問題。最後,目前除了 httpd 之外,主流的網頁伺服器皆不支援 SAPI 模組。


註1. SAPI 有時也泛指伺服器與應用程式之間的 API,因此除了 SAPI 外,CGI、FastCGI、以及 CLI 等也都可以視為是不同類型的 SAPI。
註2. IIS 上的 SAPI 被稱為 ISAPI,ISAPI 的擴充都是實作成為 DLLs,會被載入由 IIS 控制的程序中。從 IIS 7.0 開始,已經統一改用 FastCGI,而不建議使用 ISAPI。
註3. httpd 2.x 上的 SAPI 稱為 Apache 2.0 Handler。
註4. Prefork 是 httpd 的一種 MPM,相關介紹介請參考


FastCGI


和 CGI 相同,快速共用閘道介面 (Fast Common Gateway Interface, FastCGI) 也是一個協定;它是 CGI 的加強版,不僅保留了 CGI 的好處,而且還提升了 CGI 的性能。FastCGI 將 CGI 應用程式包裝起來,並且使用 FastCGI 伺服器來建立程序並且管理從網頁伺服器送來的請求。

FastCGI 的運作機制為,當系統啟動 FastCGI 伺服器時,會建立一個主要程序 (Master Process),Master Process 會建立多個稱為工作者 (Worker) 的子程序;當收到請求時,網頁伺服器可以透過插座 (Socket) 或是 TCP 連線跟 FastCGI 模組進行通信;Master Process 會選擇一個閒置的 Worker Process 處理並回應請求,處理完畢後 Worker Process 會回到閒置狀態,而不是結束行程。當 Worker Process 不夠時,Master Process 可以動態配罝新的 Worker Process;當有過多的 Worker Process 閒置時,則可以適度的終止 Worker Process。這樣的機制可以解決 CGI 需要反覆的建立程序的缺點。


FastCGI 模式的執行流程為:
網頁伺服器收到請求 -> 主要程序 -> 工作者子程序


PHP-FPM(FastCGI Process Manager)是 PHP 實作 FastCGI 的管理套件。通常 PHP 在搭配 httpd 使用時,預設會使用 Prefork 加上 SAPI 的方式。但是如果基於效能考量,httpd 可以使用 Event 模組,再搭配使用 PHP-FPM。


CLI

PHP 的命令列介面 (Command Line Interface, CLI) 主要的用途是開發 Shell 應用程式。通常我們在終端機執行的 PHP Script 就是透過 CLI。例如,我們可透過下列的指令查詢 PHP 的版本以及所使用的 SAPI 為何:
php -v


PHP 7.3.10 (cli) (built: Sep 30 2019 19:59:54) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.3.10, Copyright (c) 1998-2018 Zend Technologies
    with Zend OPcache v7.3.10, Copyright (c) 1999-2018, by Zend Technologies


在版本號碼 7.3.10 後面的 (cli),表示在終端機執行的 PHP 是使用 CLI SAPI。


CLI 模式的執行流程為:
終端機輸入請求 -> CLI SAPI


大部份的腳本語言 (Script Language) 都有提供交互模式,進行簡易的程式執行與測試。從 PHP 5.1.0 開始,藉由 php -a 指令,CLI SAPI 提供了交互模式:
php -a
Interactive shell


我們可以在互動模式下執行程式或內建的函數:
php > phpinfo();


要結束交互模式可以使用 control+z 或是 control+c 組合鍵。


從 PHP 5.4.0 開始,CLI SAPI 還提供一個簡單的內建網頁伺服器,供使用者進行簡單的 PHP 網頁程式開發測試。不過,這個伺服器在執行時僅使用單一執行緒程序,如果有請求受阻時,應用程式將會停滯。使用下列的指令可以執行內建網頁伺服器:
php -S localhost:8000



終端機會有下列的訊息:
PHP 7.3.11 Development Server started at Wed Oct 30 16:36:39 2019
Listening on http://localhost:8000
Document root is /usr/local/Cellar/httpd/2.4.41_1
Press Ctrl-C to quit.



結論


要使用 PHP 開發 Shell 應用程式或是進行簡易的程式測試與除錯,可以選擇 CLI;如果是要用來做為網頁應用程式開發使用,則可以使用 SAPI 或是 FastCGI。CGI 因為效能較差,再加上目前主流的網頁伺服器都支援具有增強功能的 FastCGI,因此已經較少人使用。


在使用 httpd + PHP + MySQL 開發網頁應用時,目前多數的套件預設為使用 SAPI,在設定上也較為簡單,所以初學者適合使用 SAPI。但是如果是使用 nginx 或是 IIS 做為網頁伺服器,或是重視應用程式的效能,則需要使用 FastCGI。

2019年10月14日 星期一

Homebrew 簡介


Homebrew 簡介


要在 macOS 上安裝應用程式可以透過:Mac App Store (MAS)、應用程式的官網、或是下載原始碼等方式。MAS 提供了簡便的應用程式安裝方式,只要在 App Store 搜尋到需要的應用程式,再點選「取得」即可安裝。但是,有許多的應用程式(特別是許多系統開發工具),並沒有在 MAS 上架,無法藉由 MAS 取得。而由較具規模的組織或公司所開發的應用程式,大多有設有官網可以下載應用程式,安裝過程也十分簡單1。但是某些透過進階安裝的應用程式,較不容易控管其版本與安裝內容,而且在移除時需要注意是否有殘留的檔案或資料夾。下載原始碼安裝,雖可以讓使用者量身打造自己的應用程式。但是應用程式彼此之間的相依性問題以及未來的升級管理,都會對使用者造成困擾。

為了安裝與管理應用程式,不少的作業系統、伺服端執行環境、程式語言等,都提供了套件管理工具。例如,Debian 的 APT、openSUSE 的 Zypper、Fedora 及 CentOS 的 YUM 、node.js 的 NPM、或是 Python 的 PIP 等。而在 macOS,Homebrew 就是最被廣為使用的套件管理工具。

Homebrew 是 macOS 缺少套件的管理工具 (The missing package manager for macOS)2,官網為 https://brew.sh/。Brew 通常可以指 "釀造啤酒",Homebrew 是在家裡釀造啤酒;套件管理工具 Homebrew,代表使用者需要 "自行"(home) "下載並安裝" 套件(brew)。因為借用了釀造啤酒一詞,所以在相關的術語中,使用了配方 (Formula)、酒桶 (Keg)、酒瓶 (Bottle)、出酒閥 (Tap)、酒窖 (Cellar) 等許多和釀造啤酒有關的名詞。相關術語的介紹請參考下一小節。

Homebrew 是以 Ruby 語言寫成的命令列套件管理 (command line package manager) 程式 ,它提供了一個統一的方法讓使用者可以輕易地在 macOS 上進行安裝、升級與移除軟體。它的功能有 git 版本庫訪問 (Repository Access)、相依性處理 (Dependency Solving)、以及套件安裝 (Package Installation) 等。

註1. 雙擊下載的 DMG 檔會自動掛載虛擬磁碟機,並且開啟一個 Finder 視窗:1)視窗內如果有一個 APP 檔和指向 "應用程式" 資料夾的捷徑,只需要將 APP 檔拖拉至 "應用程式" 資料夾捷徑即可完成安裝。2)視窗內如果沒有 "應用程式" 資料夾捷徑,通常代表需要雙擊 APP 檔或是 PKG 檔,進行進階安裝。
註2. Homebrew 現在也可以用於 Linux 以及 Windows Subsystem for Linux(WSL),所以英文版的首頁已經改為 The missing package manager for macOS (or Linux)。


Homebrew 相關術語


釀造啤酒需要 Formula、Keg、Bottle、Tap、Cellar 等器具或場所。Homebrew 借用了這些詞語做為相關的術語。首先,釀造啤酒需要有 Formula 來決定需要使用那些材料以及其使用量。在 Homebrew 中,Formula 是一種特定領域語言 (Domain-specific language, DSL),是由 Ruby 指令碼集所構成的套件定義檔,用來管理軟體間的相依性、原始碼的下載、以及進行軟體的配置與編譯等。在使用 Homebrew 時,會先從 Git 版本庫 (Homebrew 預設使用的是 GitHub 提供的版本庫) 中下載 Formulae。

當釀好酒後,需要 Keg 來存放成品,並且需要 Cellar 來存放的 Kegs。在 Homebrew 中,Keg 為套件的安裝前綴,通常包含了套件名稱以及版本,而 Cellar 則為 存放 Kegs 的目錄。預設 Cellar 路徑為 /usr/local/Cellar,完整的套件安裝路徑預設為:
/usr/local/Cellar/套件名稱/版本

要將 Keg 中的啤酒倒出來,通常會在 Keg 上加上 Tap(Tap a keg);Tap 當名詞時是指出酒閥,當動詞時是指在 Keg 加上 TAP 的動作。在 Homebrew,Tap 當名詞時是指由 formulae 所形成的 Git 版本庫3,當動詞時是指在本機建立這些 Git 版本庫的複本。

啤酒除了可以裝在 Keg 中之外,也可以分裝在小酒瓶(Bottle)中。在 Homebrew 中, Bottle 是依照預設參數編譯好的套件 (通常為 .tar.gz 檔),會依照打包時的路徑進行安裝。Homebrew 的目標是希望所有的套件都是利用 Bottle 安裝(We aim to bottle everything.)。


下表參考自:https://github.com/Homebrew/brew/blob/master/docs/Formula-Cookbook.md#homebrew-terminology

名稱描述範例
Formula套件定義/usr/local/Homebrew/Library/Taps/homebrew/homebrew-core/Formula/foo.rb
KegFormula 的安裝前綴預設為 /usr/local/Cellar/套件名稱/版本
opt prefixKeg 現行安裝版本的 symlink/usr/local/opt/套件名稱
Cellar所有的 Kegs 將被安裝在此/usr/local/Cellar
TapFormulae (以及/或是命令) 的 Git 版本庫homebrew/core 在本機會存放在 /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core
Bottle預建的 Keg (預先編譯好的套件)在 .tar.gz 前會有 bottle 關鍵字,例如qt-4.8.4.mavericks.bottle.tar.gz
Cask用來安裝 macOS 原生 Apps 的 homebrew 擴充/Applications/MacDown.app/Contents/SharedSupport/bin/macdown
Brew Bundle用來描述相依性的 homebrew 擴充brew 'myservice', restart_service: true


註3. Taps 之前被分類為:
1) 主要版本庫 (Main repository),通常指的是 homebrew/core;
2) 主要 Taps (Main taps),包含了 homebrew/nginx、homebrew/php、homebrew/science 等;
3) 其他有趣的 Taps (Other interesting taps) 或是第三方版本庫 (Third-party repositories),格式為 <user/repo> 的 Taps。
但是從 2018 年(Homebrew 1.5.0)開始,大部份的 Main taps 已經被移入 Main repository,Tap 也被更名為第三方版本庫(請參考這裡這裡以及這裡)。


安裝以及移除 Homebrew



安裝 Xcode 命令列工具 (Command Line Tools)4
xcode-select --install


要安裝 Homebrew 只需要在終端機命令列提示貼上下列的指令:
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"


要移除 Homebrew 只需要在終端機命令列提示貼上下列的指令:
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/uninstall)"


註4. Command Line Tools 為 Xcode 的子集,是一個獨立套件。能在 macOS 終端機介面提供 clang、cpp、GCC、git、make、perl 等許多常用的工具,實用程序和編譯器。

軟體安裝簡易流程


1. 找到軟體所屬的 Tap(如果套件不屬於 Homebrew/core)。

2. 更新所有的 Formulae、升級已安裝的軟體、以及移除所有舊的 formulae
brew update
brew upgrade
brew cleanup


3. 下載軟體所屬的 Tap (不屬於主要版本庫的套件)
brew tap <user/repo>


4. 查詢軟體的安裝選項 (如果需要的話)
brew info <formula>


5. 安裝套件5, 6, 7
brew install <formula> [--with-參數]


6. 將已安裝套件的服務加入 Launchd,設定為開機啟動的守護行程 (daemon),brew services 的介紹請參考
brew services start <formula>


註5. 如果沒有使用安裝選項,預設是使用 bottled 版本。
註6. Homebrew 預設會將套件安裝在 /usr/local/Cellar,執行檔則會 symlink 到 /usr/local/bin,設定檔會在 /usr/local/etc,而 /usr/local/opt 則是套件現行版本的 symlink。
註7. 在安裝完套件後,如果顯示套件為 keg-only,表示套件將僅安裝在 Cellar,而不會被連結到 /usr/local;通常的原因是因為電腦中已經相同名稱的套件。如果要手動符號連結到 /usr/local/ 可以使用 brew link 指令。


指令簡易介紹


顯示 Homebrew 版本
brew -v


檢查 Homebrew 狀態
brew doctor


使用說明
brew help


顯示 Homebrew 安裝路徑
brew --prefix


更新電腦上全部的 Formulae
brew update


更新所有已安裝的套件
brew upgrade


更新指定的套件
brew upgrade <formula>


列出過時 (需要更新) 的套件
brew outdated


列出目前電腦上所有版本庫的名稱
brew tap


下載或更新指定的 Tap
brew tap <homebrew/homebrew-repo>
brew tap <user/repo>


移除指定的 Tap
brew untap <homebrew/homebrew-repo>
brew untap <user/repo>


查詢套件的資訊  (可以用來查詢套件有那些安裝參數可以使用)
brew info <formula>


安裝套件
brew install <formula> [--with-參數]


移除套件
brew uninstall <formula>


將套件符號連結至 /usr/local
brew link <formula>


移除已安裝套件的 symlink,但是不移除套件
brew unlink <formula>


將已安裝套件的服務加入 Launchd,設定為開機啟動的守護行程(brew services 的介紹請參考
brew services start <formula>


顯示已安裝的套件清單
brew list


顯示已安裝的特定套件的安裝內容(檔案夾以及檔案)
brew list <formula>


顯示全部可安裝的套件清單
brew search


搜尋特定的套件
brew search <formula>


列出指定軟體的依賴關係
brew deps <formula>


顯示特定套件的安裝路徑
brew --prefix <formula>


移除所有舊的 formulae
brew cleanup


移除舊的 formula
brew cleanup <formula>


固定第三方版本庫
brew tap-pin <username/repo>


停止對套件進行 update/upgrade
brew pin <formula>


恢復對套件進行 update/upgrade
brew unpin <formula>



補充說明:


1. 安裝套件前一定要先執行 brew update,並建議執行 brew upgrade。

2. 在安裝軟體時,如果有多個版本庫所提供的套件 (配方) 名稱重複,brew 會依照下列的順序來決定要使用那一個 formula:(1) 使用 tap-pin 固定的版本庫 (pinned taps)、(2) 核心配方 (core formulae,在 homebrew/core 的 formulae)、(3) 其它的版本庫 (other taps)。

3. 其他的操作可以參考 https://docs.brew.sh/FAQ.html


2019年10月9日 星期三

使用 Homebrew 安裝 MariaDB


MariaDB 簡介


MariaDB 是一個關聯式資料庫管理系統(Relational Database Management System, RDBMS),是一個主要由開源社群維護、採用 GPL v2 授權的 MySQL 分叉(Fork)。MariaDB 由 MySQL 的主要創始人 Ulf Michael Widenius 所主導開發,會建立這個分支的原因之一是原本收購了 MySQL AB 的 Sun Microsystems 被資料庫巨擘 Oracle 給收購了,使得 MySQL 有被閉源的風險。和 MySQL 的名稱來自 Widenius 女兒 My 一樣,MariaDB 的名稱來自 Widenius 女兒的名字 Maria。

要選擇 MySQL 或是 MariaDB 並不是一件容易的事,因為兩者之間的差異逐漸擴大。本文將僅介紹 MariaDB 的安裝以及簡易的使用方式。

安裝 MariaDB

要在 macOS 上安裝 MariaDB 十分簡單,只需要執行下列的命令:

brew update
brew upgrade
brew install mariadb


(Homebrew 的簡介請參考。)


啟動與連線 MariaDB Server


為了要保持跟 MySQL 的操作相容性,MariaDB 大部份的操作命令沿用了 MySQL 的命令。要啟動 MariaDB server 需要執行下列的命令:
mysql.server start

mysql.server 是 MariaDB 用來啟動、停止、重新啟動、以及檢查狀態的腳本 (Script)。


要停止 MariaDB server 需要執行下列的命令:
mysql.server stop --user=[my_current_user]


因為是使用目前的使用者啟動,所以在停止時需要加上使用者名稱 --user=[my_current_user]。如果沒有加上使用者名稱,會出現下列的錯誤訊息:
ERROR! MariaDB server process #Pro_ID is not running!


若是使用下列的命令檢查伺服器的狀態:
mysql.server status


則會出現下列的錯誤訊息
ERROR! MariaDB is not running, but PID file exists


解決的方式,一樣是在命令中加入 --user 這個參數。


在啟動 MariaDB 後,可以使用下列的命令連線 MariaDB:
sudo mysql -uroot


剛安裝完 MariaDB 時,root 帳號是沒有密碼的。在之前的版本,只要使用本機使用者帳號即可連線 MariaDB,這樣的機制會有資訊安全的疑慮。因此,從 MariaDB 10.4.3 開始,在未設定 root 帳號密碼前,MariaDB 會使用 unix_socket 插件 (Plugin)保護 root@localhost,需要透過系統用戶憑證來連線。如果沒有使用 sudo,會出現下列的錯誤:
ERROR 1698 (28000): Access denied for user 'root'@'localhost'


設定 root 密碼


傳統設定密碼的方式為使用 mysqladmin 命令:
sudo mysqladmin -uroot password your_password


在設定好 root 的密碼後,可以使用傳統的認證方式 (mysql_native_password) 連線到 MariaDB:
mysql -uroot -pyour_password


MariaDB 也提供了 mysql_secure_installation 這個設定腳本,來進行密碼以及伺服器的相關設定,並且建議在上線服務前需要先執行該腳本。在設定完密碼後,可以直接執行該命令 (未設定 root 密碼時,要加上 sudo):
mysql_secure_installation


該腳本會進行下列的設定:

1. 是否更換為 unix_socket 認證:建議選擇 N,保留目前的認證方式1

2. 設定 MariaDB 的 root 密碼:密碼已經設定好了,可以選擇 N,否則選 Y 進行密碼設定;

3. 移除匿名使用者:建議選擇 Y;

4. 禁止 root 遠端登入:建議選擇 Y;

5. 移除 test 資料庫:建議選擇 Y;

6. 重新載入權限表格:建議選擇 Y,讓上面的設定生效。


註1:在選擇 Y 後,目前的 mysql_native_password 密碼會失效,在不是使用 sudo 命令時,將無法繼續執行腳本。

將 mysqld 設定為守護行程 (daemon)


brew services start mysql



brew services 的簡介可以參考這裡