

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 自訂 OpsWorks Stacks
<a name="customizing"></a>

**重要**  
 AWS OpsWorks Stacks 此服務已於 2024 年 5 月 26 日終止，並已針對新客戶和現有客戶停用。我們強烈建議客戶盡快將其工作負載遷移至其他解決方案。如果您對遷移有任何疑問，請透過 [AWS re：Post](https://repost.aws/) 或透過 [AWS Premium Support](https://aws.amazon.com/support) 聯絡 AWS 支援 團隊。

OpsWorks Stacks 內建 layer 提供的標準功能足以用於許多用途。不過，您可能會遇到下列一或多種情況：
+ 內建 layer 的標準組態雖足夠但不理想，您希望針對您的特定需求最佳化。

  例如，您可能想要透過指定自己的值來調整靜態 Web 伺服器層的 Nginx 伺服器組態，例如工作者程序數目上限或`keepalivetimeout`值。
+ 內建 layer 的功能很好，但您想要安裝額外的套件或執行一些自訂安裝程式碼擴展它。

  例如，您可能也想要安裝 Redis 伺服器來擴展 PHP App Server layer。
+ 您有任何內建 layer 都不處理的要求。

  例如， OpsWorks Stacks 不包含某些熱門資料庫伺服器的內建層。您可以建立自訂 layer，在 layer 的執行個體上安裝這些伺服器。
+ 您執行的是 Windows 堆疊，它只支援自訂 layer。

OpsWorks Stacks 提供多種自訂 layer 的方式，以符合您的特定需求。下列範例依增加複雜度和功能的順序列出：

**注意**  
這些方法有部分只適用於 Linux 堆疊。請參閱以下主題以了解詳細資訊。
+ 使用自訂 JSON OpsWorks 覆寫預設的 Stacks 設定。
+ 使用覆寫預設 Stacks 設定的屬性檔案實作自訂 Chef OpsWorks 技術指南。
+ 使用覆寫或擴展預設 Stacks 範本的範本實作自訂 Chef OpsWorks 技術指南。
+ 使用執行 shell 指令碼的簡單配方實作自訂的 Chef 技術指南。
+ 使用執行任務 (例如建立和設定目錄、安裝套件、建立組態檔案、部署應用程式等等) 的配方，實作自訂的 Chef 技術指南。

您也可以覆寫配方，視堆疊的 Chef 版本和作業系統而定。
+ 使用 Chef 0.9 和 11.4 堆疊，您無法透過以相同的技術指南和配方名稱實作自訂配方，來覆寫內建配方。

  對於每個生命週期事件， OpsWorks Stacks 一律會先執行內建配方，接著執行任何自訂配方。由於這些 Chef 版本不會執行兩次有相同技術指南和配方名稱的配方，所以內建配方優先，不執行自訂配方。
+ 您可以在 Chef 11.10 堆疊上覆寫內建配方。

  如需詳細資訊，請參閱[技術指南安裝與優先順序](workingcookbook-chef11-10.md#workingcookbook-chef11-10-override)。
+ 您無法在 Windows 堆疊上覆寫內建配方。

  Stacks 處理 Chef 為 Windows OpsWorks 堆疊執行的方式不允許覆寫內建配方。

**注意**  
由於許多技術都使用自訂技術指南，[技術指南和配方](workingcookbook.md)如果您尚未熟悉技術指南實作，應先閱讀。 [技術指南基本概念](cookbooks-101-basics.md)提供實作自訂技術指南的詳細教學簡介，並[實作 Stacks OpsWorks 的技術指南](cookbooks-101-opsworks.md)涵蓋如何實作 Stacks OpsWorks 執行個體技術指南的一些詳細資訊。

**Topics**
+ [透過覆寫屬性自訂 OpsWorks Stacks 組態](workingcookbook-attributes.md)
+ [使用自訂範本擴展 OpsWorks Stacks 組態檔案](workingcookbook-template-override.md)
+ [擴充 Layer](workingcookbook-extend.md)
+ [建立自訂 Tomcat 伺服器 Layer](create-custom.md)
+ [堆疊組態及部署屬性](workingcookbook-json.md)

# 透過覆寫屬性自訂 OpsWorks Stacks 組態
<a name="workingcookbook-attributes"></a>

**重要**  
 AWS OpsWorks Stacks 此服務已於 2024 年 5 月 26 日終止，並已針對新客戶和現有客戶停用。我們強烈建議客戶盡快將其工作負載遷移至其他解決方案。如果您對遷移有任何疑問，請透過 [AWS re：Post](https://repost.aws/) 或透過 [AWS Premium Support](https://aws.amazon.com/support) 聯絡 AWS 支援 團隊。

**注意**  
對於 Windows 堆疊和 Chef 12 Linux 堆疊， OpsWorks Stacks 會針對內建配方和自訂配方使用個別的 Chef 執行。這表示您無法使用本節討論的技術覆寫 Windows 堆疊和 Chef 12 Linux 堆疊的內建屬性。

配方和範本取決於執行個體的各種 Chef 屬性，或堆疊限定的資訊 (例如 layer 組態或應用程式伺服器設定)。這些屬性有幾個來源：
+ **自訂 JSON** – 您可以在建立、更新或複製堆疊或部署應用程式時選擇性地指定自訂 JSON 屬性。
+ **堆疊組態屬性** –OpsWorks 堆疊會定義這些屬性以保留堆疊組態資訊，包括您透過主控台設定指定的資訊。
+ **部署屬性** – AWS OpsWorks 會定義部署事件的部署相關屬性。
+ **技術指南屬性** – 內建和自訂技術指南通常包含一或多個[屬性檔案](workingcookbook-installingcustom-components-attributes.md)，其中包含代表技術指南特定值的屬性，例如應用程式伺服器組態設定。
+ **Chef**–Chef 的 [Ohai 工具](http://docs.chef.io/resource_ohai.html)定義了代表各種系統組態設定的屬性，例如 CPU 類型和已安裝的記憶體。

如需堆疊組態、部署屬性和內建技術指南屬性的完整清單，請參閱[堆疊組態及部署屬性：Linux](attributes-json-linux.md) 和[內建技術指南屬性](attributes-recipes.md)。如需 Ohai 屬性的詳細資訊，請參閱 [Ohai](https://docs.chef.io/ohai.html)。

當部署或設定等[生命週期事件](workingcookbook-events.md)發生時，或是您執行像是 [ 或 ](workingstacks-commands.md) 等`execute_recipes`堆疊命令`update_packages`時， OpsWorks Stacks 會執行下列作業：
+ 將對應的命令傳送到每個受影響之執行個體的代理程式。

  代理程式會執行適當的配方。例如，針對部署事件，代理程式會執行內建的部署配方，其後跟隨任何自訂部署配方。
+ 將任何自訂 JSON 和部署屬性與堆疊組態屬性合併，然後在執行個體上安裝他們。

來自自訂 JSON、堆疊組態和部署屬性、技術指南屬性和 Ohai 屬性的屬性會合併成一個「*節點物件*」，該物件會將屬性值提供給配方。針對堆疊組態屬性，執行個體基本上是無狀態的，包含任何自訂 JSON。當您執行部署或堆疊命令時，關聯的配方會使用以命令下載的堆疊組態屬性。

**Topics**
+ [屬性優先順序](workingcookbook-attributes-precedence.md)
+ [使用自訂 JSON 覆寫屬性](workingcookbook-json-override.md)
+ [使用自訂技術指南屬性覆寫 OpsWorks Stacks 屬性](workingcookbook-cookbook-attributes.md)

# 屬性優先順序
<a name="workingcookbook-attributes-precedence"></a>

**重要**  
 AWS OpsWorks Stacks 此服務已於 2024 年 5 月 26 日終止，並已針對新客戶和現有客戶停用。我們強烈建議客戶盡快將其工作負載遷移至其他解決方案。如果您對遷移有任何疑問，請透過 [AWS re：Post](https://repost.aws/) 或透過 [AWS Premium Support](https://aws.amazon.com/support) 聯絡 AWS 支援 團隊。

若屬性的定義是唯一的，Chef 會直接將其併入節點物件。但是，任何屬性來源都可以定義任何屬性，因此相同的屬性可能會有值不同的多個定義。例如，內建的 `apache2` 技術指南定義了 `node[:apache][:keepalive]`，但您也可以在自訂 JSON 或自訂技術指南中定義該屬性。若屬性具有多個定義，他們會按照稍後說明的順序進行評估，並且節點物件會接收到具有最高優先順序的定義。

一個屬性定義如下：

```
node.type[:attribute][:sub_attribute][:...]=value
```

如果屬性有多個定義， 類型會決定哪個定義具有優先順序，且該定義會併入節點物件中。 OpsWorks Stacks 會使用下列屬性類型：
+ **default** – 這是最常見的類型，基本上表示「如果尚未定義屬性，請使用此值」。若所有屬性的定義皆為 `default` 類型，評估順序中的第一個定義便具有優先順序，其餘值則會遭到忽略。請注意， Stacks OpsWorks 會將所有堆疊組態和部署屬性定義設定為 `default`類型。
+ 具有此類型的 **normal**–Attributes 會覆寫先前在評估順序中定義的任何 `default`或 `normal` 屬性。例如，若第一個屬性是來自內建的技術指南，並且具有 `default` 類型，而第二個則是具有 `normal` 類型的使用者定義屬性，則第二個定義便具有優先順序。
+ **set** – 這是您在舊版技術指南中可能看到的已棄用類型。它已由具有相同優先順序的 `normal` 取代。

Chef 支援數種額外的屬性類型，包含優先順序高於任何其他屬性定義的 `automatic` 類型。由 Chef 的 Ohai 工具產生的屬性定義全部皆為 `automatic` 類型，因此他們基本上等同於唯讀。這通常不是問題，因為沒有理由覆寫它們，而且它們與 OpsWorks Stacks 的屬性不同。不過，建議您小心地為自訂技術指南屬性命名，使其與 Ohai 屬性相異。如需詳細資訊，請參閱[關於屬性](http://docs.chef.io/attributes.html)。

**注意**  
Ohai 工具為您可以從命令列執行的可執行檔。若要列出執行個體的 Ohai 屬性，請登入執行個體並在終端機視窗中執行 `ohai`。請注意，它會產生非常長的輸出。

以下為將各種屬性定義併入節點物件的步驟：

1. 將任何自訂堆疊組態屬性併入堆疊組態和部署屬性。

   您可為堆疊或特定部署設定自訂 JSON 屬性。他們會位於評估的第一優先順序，基本上等同於 `normal` 類型。若一或多個堆疊組態屬性也在自訂 JSON 中定義，則自訂 JSON 的值會具有優先順序。否則 OpsWorks Stacks 會直接將自訂 JSON 屬性併入堆疊組態。

1. 將任何部署自訂 JSON 屬性併入堆疊組態和部署屬性。

   部署自訂 JSON 屬性也等同於 `normal` 類型，因此他們會優先於內建和自訂堆疊組態 JSON 及內建部署 JSON。

1. 將堆疊組態和部署屬性合併成執行個體的節點物件。

1. 將執行個體的內建技術指南屬性合併成節點物件。

   內建技術指南屬性全部皆為 `default` 類型。如果堆疊組態和部署屬性中也定義了一或多個內建技術指南屬性，通常是因為您使用自訂 JSON 定義它們，則堆疊組態定義優先於內建技術指南定義。所有其他內建技術指南屬性也會直接併入節點物件。

1. 將執行個體的自訂技術指南屬性合併成節點物件。

   自訂技術指南屬性通常不是 `normal` 就是 `default` 類型。唯一屬性會併入節點物件。如果步驟 1–3 中也定義了任何自訂技術指南屬性 （通常是因為您使用自訂 JSON 定義了它們），則優先順序取決於自訂技術指南屬性的類型：
   + 步驟 1-3 中定義的屬性優先於自訂技術指南`default`屬性。
   + 自訂 c ookbook `normal` 屬性優先於步驟 1–3 的定義。

**重要**  
請勿使用自訂技術指南的 `default` 屬性覆寫堆疊組態或內建技術指南屬性。由於自訂技術指南屬性會在最後評估，`default` 屬性具有最低的優先順序，因此無法覆寫任何內容。

# 使用自訂 JSON 覆寫屬性
<a name="workingcookbook-json-override"></a>

**重要**  
 AWS OpsWorks Stacks 此服務已於 2024 年 5 月 26 日終止，並已針對新客戶和現有客戶停用。我們強烈建議客戶盡快將其工作負載遷移至其他解決方案。如果您對遷移有任何疑問，請透過 [AWS re：Post](https://repost.aws/) 或透過 [AWS Premium Support](https://aws.amazon.com/support) 聯絡 AWS 支援 團隊。

**注意**  
由於 OpsWorks Stacks 處理 Chef 的執行方式與 Linux 堆疊不同，因此您無法針對 Windows 堆疊使用本節中討論的技術。

覆寫 OpsWorks Stacks 屬性的最簡單方法是在自訂 JSON 中定義它，其優先順序高於堆疊組態和部署屬性，以及內建和自訂技術指南`default`屬性。如需詳細資訊，請參閱[屬性優先順序](workingcookbook-attributes-precedence.md)。

**重要**  
建議您小心覆寫堆疊組態和部署屬性。例如：覆寫 `opsworks` 命名空間中的屬性可能會影響內建配方。如需詳細資訊，請參閱[堆疊組態及部署屬性](workingcookbook-json.md)。

您也可以使用自訂 JSON 定義唯一屬性，通常是將資料傳遞到您的自訂配方。屬性會直接併入節點物件，並且配方可以透過使用標準 Chef 節點語法參考他們。

## 如何指定自訂 JSON
<a name="workingcookbook-json-override-specify"></a>

若要使用自訂 JSON 覆寫屬性值，您必須先判斷屬性的完整屬性名稱。您接著會建立包含您希望覆寫之屬性的 JSON 物件，將其設為您喜好的值。為了方便起見，[堆疊組態及部署屬性：Linux](attributes-json-linux.md) 和[內建技術指南屬性](attributes-recipes.md)文件常會使用堆疊組態、部署和內建技術指南屬性，包含其完整名稱。

物件的父系和子系關聯必須對應到適當的完整 Chef 節點。例如，假設您希望變更以下 Apache 屬性：
+ 節點為 [ 並且預設值為 `keepalivetimeout` 的 ](attributes-recipes-apache.md#attributes-recipes-apache-keep-timeout)`node[:apache][:keepalivetimeout]``3` 屬性。
+ 節點為 `logrotate` 並且預設值為 [ 的 `schedule`](attributes-recipes-apache.md#attributes-recipes-apache-log-schedule)`node[:apache][:logrotate][:schedule]``"daily"` 屬性。

若要覆寫屬性並將值分別設為 `5` 和 `"weekly"`，您會使用下列自訂 JSON：

```
{
  "apache" : {
    "keepalivetimeout" : 5,
    "logrotate" : {
       "schedule" : "weekly"
    }
  }
}
```

## 何時指定自訂 JSON
<a name="workingcookbook-json-override-when"></a>

您可以為下列任務指定自訂 JSON：
+ [建立新的堆疊](workingstacks-creating.md)
+ [更新堆疊](workingstacks-edit.md)
+ [執行堆疊命令](workingstacks-edit.md)
+ [複製堆疊](workingstacks-cloning.md)
+ [部署應用程式](workingapps-deploying.md)

對於每個任務， OpsWorks Stacks 會將自訂 JSON 屬性與堆疊組態和部署屬性合併，並將其傳送至執行個體，以合併至節點物件。但是，請注意以下內容：
+ 若您在建立、複製或更新堆疊時指定自訂 JSON，針對後續生命週期事件和堆疊命令，屬性會合併至堆疊組態和部署屬性。
+ 若您為部署指定自訂 JSON，屬性只會針對對應的事件合併至堆疊組態和部署屬性。

  若您希望針對後續部署使用那些自訂屬性，您必須再次明確指定自訂 JSON。

請務必記得，屬性只有在由配方使用時才會影響執行個體。若您覆寫屬性值，但是沒有任何後續的配方參考該屬性，則變更便不具有效果。您必須確保在關聯配方執行前傳送自訂 JSON，或是重新執行適當的配方。

## 自訂 JSON 最佳實務
<a name="workingcookbook-json-override-best"></a>

您可以使用自訂 JSON 覆寫任何 OpsWorks Stacks 屬性，但手動輸入資訊有些麻煩，而且不在任何來源控制下。自訂 JSON 最適合用於以下目的：
+ 當您希望覆寫少量的屬性，並且不需要使用自訂技術指南時。

  透過自訂 JSON，您可以免於僅為了覆寫幾個屬性而設定及維護技術指南儲存庫的額外負荷。
+ 敏感性值，例如密碼或身分驗證金鑰。

  技術指南屬性存放於儲存庫中，因此任何敏感性資訊都會暴露在洩漏的風險中。相反的，請使用 dummy 值定義屬性，並使用自訂 JSON 設定真正的值。
+ 值應不同。

  例如，建議的實務是使用獨立的開發和預備堆疊支援您的生產堆疊。假設這些堆疊支援接受付款的應用程式。若您使用自訂 JSON 指定付款端點，您可以為您的預備堆疊指定測試 URL。當您準備好將更新後的堆疊遷移至您的生產堆疊時，您可以使用相同的技術指南，並使用自訂 JSON 將付款端點設為生產 URL。
+ 特定堆疊或部署命令專屬的值。

# 使用自訂技術指南屬性覆寫 OpsWorks Stacks 屬性
<a name="workingcookbook-cookbook-attributes"></a>

**重要**  
 AWS OpsWorks Stacks 此服務已於 2024 年 5 月 26 日終止，並已針對新客戶和現有客戶停用。我們強烈建議客戶盡快將其工作負載遷移至其他解決方案。如果您對遷移有任何疑問，請透過 [AWS re：Post](https://repost.aws/) 或透過 [AWS Premium Support](https://aws.amazon.com/support) 聯絡 AWS 支援 團隊。

**注意**  
對於 Windows 堆疊， OpsWorks Stacks 會針對內建配方和自訂配方使用個別的 Chef 執行。這表示您無法使用本節討論的技術覆寫 Windows 堆疊的內建屬性。

自訂 JSON 是覆寫 OpsWorks Stacks 堆疊組態和內建技術指南屬性的便利方式，但有一些限制。特別是您必須為每一次的使用手動輸入自訂 JSON，因此您可用來管理定義的強固方法。較佳的方法通常是使用自訂技術指南屬性檔案覆寫內建的屬性。這樣做可讓您將定義置放在來源控制之下。

使用自訂屬性檔案覆寫 OpsWorks Stacks 定義的程序非常簡單。

**覆寫 OpsWorks Stacks 屬性定義**

1. 設定技術指南儲存庫，如[技術指南和配方](workingcookbook.md)中所述。

1. 使用與內建技術指南相同的名稱建立技術指南，其中包含您希望覆寫的屬性。例如，若要覆寫 Apache 屬性，技術指南的名稱應為 apache2。

1. 將一個 `attributes` 資料夾新增至技術指南，並在該資料夾中新增一個名為 `customize.rb` 的檔案。

1. 針對每一個內建技術指南中您希望覆寫的屬性，將屬性定義新增至檔案，並設為您喜好的值。屬性必須是 `normal` 類型或更高版本，並且與對應的 OpsWorks Stacks 屬性具有完全相同的節點名稱。如需 OpsWorks Stacks 屬性的詳細清單，包括節點名稱，請參閱 [堆疊組態及部署屬性：Linux](attributes-json-linux.md)和 [內建技術指南屬性](attributes-recipes.md)。如需屬性和屬性檔案的詳細資訊，請參閱[關於屬性檔案](http://docs.chef.io/attributes.html)。
**重要**  
您的屬性必須是`normal`類型才能覆寫 OpsWorks Stacks 屬性；`default`類型沒有優先順序。例如，若您的 `customize.rb` 檔案包含 `default[:apache][:keepalivetimeout] = 5` 屬性定義，內建 `apache.rb` 屬性檔案中的對應屬性會先受到評估，並取得優先順序。如需詳細資訊，請參閱[覆寫屬性](workingcookbook-attributes.md)。

1. 為每個內建技術指南重複步驟 2 – 4，其中包含您要覆寫的屬性。

1. 為您的堆疊啟用自訂技術指南，並提供 Stacks OpsWorks 將技術指南下載至堆疊執行個體所需的資訊。如需詳細資訊，請參閱[安裝自訂技術指南](workingcookbook-installingcustom-enable.md)。

**注意**  
如需此程序的完整演練，請參閱[覆寫內建屬性](cookbooks-101-opsworks-attributes.md)。

後續生命週期事件、部署命令和堆疊命令所使用的節點物件現在將包含您的屬性定義，而不是 OpsWorks Stacks 值。

例如，若要覆寫`keepalivetimeout` 中討論的內建 Apache `logrotate schedule` 和 [如何指定自訂 JSON](workingcookbook-json-override.md#workingcookbook-json-override-specify) 設定，請將 `apache2` 技術指南新增至您的儲存庫，然後將 `customize.rb` 檔案新增至技術指南的 `attributes` 資料夾，並帶有以下內容。

```
normal[:apache][:keepalivetimeout] = 5
normal[:apache][:logrotate][:schedule] = 'weekly'
```

**重要**  
您不應透過修改相關聯的內建屬性檔案複本來覆寫 OpsWorks Stacks 屬性。假設您將 `apache.rb` 複製到您的 `apache2/attributes` 資料夾並修改其部分設定，您基本上便已覆寫內建檔案中的每個屬性。配方會使用您複本中的屬性定義，並忽略內建檔案。若 OpsWorks Stacks 稍後修改了內建屬性檔案，配方將無法存取變更，除非您手動更新您的複本。  
為避免這種情況，所有內建的技術指南都包含一個空白的 `customize.rb` 屬性檔案，為所有透過 `include_attribute` 指示詞之模組的必要項目。透過覆寫您 `customize.rb` 複本中的屬性，您只會影響那些特定的屬性。配方會從內建屬性檔案取得任何其他的屬性值，並自動取得任何您未覆寫之屬性的目前值。  
這種方法可協助您將您技術指南儲存庫中的屬性維持在較小的數目，減少您的維護額外負荷，並使未來的升級更容易管理。

# 使用自訂範本擴展 OpsWorks Stacks 組態檔案
<a name="workingcookbook-template-override"></a>

**重要**  
 AWS OpsWorks Stacks 此服務已於 2024 年 5 月 26 日終止，並已針對新客戶和現有客戶停用。我們強烈建議客戶盡快將其工作負載遷移至其他解決方案。如果您對遷移有任何疑問，請透過 [AWS re：Post](https://repost.aws/) 或透過 [AWS Premium Support](https://aws.amazon.com/support) 聯絡 AWS 支援 團隊。

**注意**  
由於 OpsWorks Stacks 處理 Chef 的執行方式與 Linux 堆疊不同，因此您無法針對 Windows 堆疊使用本節中討論的技術。

OpsWorks Stacks 使用 範本來建立組態檔案等檔案，這些檔案通常取決於許多設定的屬性。如果您使用自訂 JSON 或自訂技術指南屬性來覆寫 OpsWorks Stacks 定義，您偏好的設定會併入組態檔案中，以取代 OpsWorks Stacks 設定。不過， OpsWorks Stacks 不一定會為每個可能的組態設定指定屬性；它接受某些設定的預設值，並直接在範本中硬式編碼其他設定。如果沒有對應的 Stacks 屬性，則無法使用自訂 JSON OpsWorks 或自訂技術指南屬性來指定偏好的設定。

您可以藉由建立自訂範本，來擴展組態檔案以包含額外組態設定。然後，您可以將所需的任何組態設定或其他內容新增至該檔案，並覆寫任何硬式編碼的設定。如需範本的詳細資訊，請參閱[範本](workingcookbook-installingcustom-components-templates.md)。

**注意**  
您可以覆寫任何內建範本，但 opsworks-agent.monitrc.erb「除外」**。

**建立自訂範本**

1. 使用與內建技術指南相同的結構和目錄名稱來建立技術指南。接著，在適當的目錄中，使用您想要自訂之內建範本的相同結構和目錄名稱，來建立範本檔案。例如，若要使用自訂範本以擴展 Apache `httpd.conf` 組態檔案，您必須在儲存庫中實作 `apache2` 技術指南，且您的範本檔案必須為 `apache2/templates/default/apache.conf.erb`。使用完全相同的名稱可讓 OpsWorks Stacks 辨識自訂範本，並使用它而非內建範本。

   最簡單的方法是從[內建技術指南的 GitHub 儲存庫](https://github.com/aws/opsworks-cookbooks)，將內建的範本檔案複製到您的技術指南，並視需要修改。
**重要**  
除了您想要自訂的範本檔案以外，請不要從內建的技術指南複製任何檔案。其他類型的技術指南檔案 (例如配方) 複本會建立重複的 Chef 資源，並可能造成錯誤。

   技術指南也可以包含自訂屬性、配方和相關的檔案，但它們的檔案名稱不應與內建的檔案名稱重複。

1. 自訂範本檔案以產生符合您要求的組態檔案。您可以新增更多設定、刪除現有的設定、取代硬式編碼的屬性等。

1. 如果您尚未執行，請編輯堆疊設定以啟用自訂技術指南，並指定您的技術指南儲存庫。如需詳細資訊，請參閱[安裝自訂技術指南](workingcookbook-installingcustom-enable.md)。

**注意**  
如需此程序的完整演練，請參閱[覆寫內建範本](cookbooks-101-opsworks-templates.md)。

您不需要實作任何配方或[將配方新增至 layer 組態](workingcookbook-assigningcustom.md)，即可覆寫範本。 OpsWorks Stacks 一律會執行內建配方。當您執行配方以建立組態檔案時，它會自動使用您的自訂範本，而不是使用內建的範本。

**注意**  
如果 OpsWorks Stacks 對內建範本進行任何變更，您的自訂範本可能會變得不同步且無法正常運作。例如，假設您的範本參考相依檔案，且檔案名稱變更。 OpsWorks Stacks 不會經常進行此類變更，當範本確實變更時，它會列出變更，並讓您選擇升級至新版本。您應該監控 OpsWorks Stacks 儲存庫的變更，並視需要手動更新範本。

# 擴充 Layer
<a name="workingcookbook-extend"></a>

**重要**  
 AWS OpsWorks Stacks 此服務已於 2024 年 5 月 26 日終止，並已針對新客戶和現有客戶停用。我們強烈建議客戶盡快將其工作負載遷移至其他解決方案。如果您對遷移有任何疑問，請透過 [AWS re：Post](https://repost.aws/) 或透過 [AWS Premium Support](https://aws.amazon.com/support) 聯絡 AWS 支援 團隊。

針對透過修改 OpsWorks Stacks 屬性或自訂範本處理的項目以外的項目，您有時需要自訂內建 layer。例如，假設您需要建立符號連結、設定檔案或資料夾模式、安裝額外的套件，以此類推。您必須擴充自訂 layer，以提供高於最少功能的功能。在該情況下，您需要實作一或多個具有配方的自訂技術指南來處理自訂任務。本主題提供如何使用配方來擴充 layer 的一些範例。

如果您是第一次使用 Chef，建議您先閱讀[技術指南 101](cookbooks-101.md)，該教學介紹如何實作技術指南以執行各種常見任務的基本概念。如需如何實作自訂 layer 的詳細範例，請參閱[建立自訂 Tomcat 伺服器 Layer](create-custom.md)。

**Topics**
+ [使用配方執行指令碼](workingcookbook-extend-scripts.md)
+ [使用 Chef 部署勾點](workingcookbook-extend-hooks.md)
+ [在 Linux 執行個體上執行 Cron 任務](workingcookbook-extend-cron.md)
+ [在 Linux 執行個體上安裝和設定套件](workingcookbook-extend-package.md)

# 使用配方執行指令碼
<a name="workingcookbook-extend-scripts"></a>

**重要**  
 AWS OpsWorks Stacks 此服務已於 2024 年 5 月 26 日終止，並已針對新客戶和現有客戶停用。我們強烈建議客戶盡快將其工作負載遷移至其他解決方案。如果您對遷移有任何疑問，請透過 [AWS re：Post](https://repost.aws/) 或透過 [AWS Premium Support](https://aws.amazon.com/support) 聯絡 AWS 支援 團隊。

如果您的現有指令碼執行所需的自訂任務，則擴充 layer 的最簡單方式實作通常是實作簡單配方來執行指令碼。您接著可以將配方指派給適當的生命週期事件 (一般是安裝或部署)，或使用 `execute_recipes` 堆疊命令手動執行配方。

下列範例會在 Linux 執行個體上執行 Shell 指令碼，但您可以將相同的方式用於其他類型的指令碼 (包括 Windows PowerShell 指令碼)。

```
cookbook_file "/tmp/lib-installer.sh" do
  source "lib-installer.sh"
  mode 0755
end

execute "install my lib" do
  command "sh /tmp/lib-installer.sh"
end
```

`cookbook_file` 資源代表存放在技術指南 `files` 目錄之子目錄中的檔案，並將檔案傳輸至執行個體上的指定位置。此範例會將 Shell 指令碼 `lib-installer.sh` 傳輸至執行個體的 `/tmp` 目錄，並將檔案的模式設定為 `0755`。如需詳細資訊，請參閱 [cookbook\$1file](https://docs.chef.io/chef/resources.html#cookbook-file)。

`execute` 資源代表命令 (如 Shell 命令)。此範例執行 `lib-installer.sh`。如需詳細資訊，請參閱 [execute](https://docs.chef.io/chef/resources.html#execute)。

您也可以將指令碼併入配方來執行指令碼。下列範例會執行 bash 指令碼，但 Chef 也支援 Csh、Perl、Python 和 Ruby。

```
script "install_something" do
  interpreter "bash"
  user "root"
  cwd "/tmp"
  code <<-EOH
    #insert bash script
  EOH
end
```

`script` 資源代表指令碼。此範例指定 bash 解譯器、將使用者設定為 `"root"`，並將工作目錄設定為 `/tmp`。它接著會執行 `code` 區塊中的 bash 指令碼，可視需要包括多行。如需詳細資訊，請參閱 [script](https://docs.chef.io/chef/resources.html#script)。

如需如何使用配方執行指令碼的詳細資訊，請參閱[範例 7：執行命令和指令碼](cookbooks-101-basics-commands.md)。如需如何在 Windows 執行個體上執行 PowerShell 指令碼的範例，請參閱[執行 Windows PowerShell 指令碼](cookbooks-101-opsworks-opsworks-powershell.md)。

# 使用 Chef 部署勾點
<a name="workingcookbook-extend-hooks"></a>

**重要**  
 AWS OpsWorks Stacks 此服務已於 2024 年 5 月 26 日終止，並已針對新客戶和現有客戶停用。我們強烈建議客戶盡快將其工作負載遷移至其他解決方案。如果您對遷移有任何疑問，請透過 [AWS re：Post](https://repost.aws/) 或透過 [AWS Premium Support](https://aws.amazon.com/support) 聯絡 AWS 支援 團隊。

部署的自訂方式是實作自訂配方來執行所需任務，並將它指派給適當 layer 的部署事件。替代且有時更簡單的方法，特別是當您不需要實作技術指南用於其他用途時，就是使用 Chef 部署勾點來執行自訂程式碼。此外，自訂部署配方會在內建配方已執行部署之後執行。部署勾點可讓您在部署期間互動，例如，從儲存庫簽出應用程式碼之後，但在重新啟動 Apache 之前。

Chef 會以四個階段部署應用程式：
+ **結帳** – 從儲存庫下載檔案
+ **Migrate** – 視需要執行遷移
+ **Symlink** – 建立符號連結
+ **重新啟動** – 重新啟動應用程式

Chef 部署勾點提供一種簡單的方法，選擇性地在每個階段完成之後執行使用者所提供的 Ruby 應用程式來自訂部署。若要使用部署勾點，請實作一或多個 Ruby 應用程式，並將它們放入您應用程式的 `/deploy` 目錄中 (如果您的應用程式沒有 `/deploy` 目錄，則請在 `APP_ROOT` 層級建立該目錄)。應用程式必須具有下列其中一個名稱，以決定其何時執行。
+ `before_migrate.rb` 是在 Checkout (簽出) 階段完成之後但在 Migrate (遷移) 之前執行。
+ `before_symlink.rb` 是在 Migrate (遷移) 階段完成之後但在 Symlink (符號連結) 之前執行。
+ `before_restart.rb` 是在 Symlink (符號連結) 階段完成之後但在 Restart (重新啟動) 之前執行。
+ `after_restart.rb` 是在 Restart (重新啟動) 階段完成之後執行。

Chef 部署勾點使用標準節點語法，即可存取節點物件，就像配方一樣。部署勾點也可以存取您所指定之任何[應用程式環境變數](workingapps-creating.md#workingapps-creating-environment)的值。不過，您必須使用 `new_resource.environment["VARIABLE_NAME"] ` 存取變數的值，而不是 `ENV["VARIABLE_NAME"]`。

# 在 Linux 執行個體上執行 Cron 任務
<a name="workingcookbook-extend-cron"></a>

**重要**  
 AWS OpsWorks Stacks 此服務已於 2024 年 5 月 26 日終止，並已針對新客戶和現有客戶停用。我們強烈建議客戶盡快將其工作負載遷移至其他解決方案。如果您對遷移有任何疑問，請透過 [AWS re：Post](https://repost.aws/) 或透過 [AWS Premium Support](https://aws.amazon.com/support) 聯絡 AWS 支援 團隊。

Linux Cron 任務會指示 Cron 協助程式依指定的排程執行一或多個命令。例如，假設您的堆疊支援 PHP 電子商務應用程式。您可以設定 cron 任務，讓伺服器在每週的指定時間將銷售報告傳送給您。如需 cron 的詳細資訊，請參閱 Wikipedia 上的 [cron](http://en.wikipedia.org/wiki/Cron)。如需如何直接在 Linux 電腦或執行個體上執行 cron 任務的詳細資訊，請參閱 Indiana University 知識庫網站上的 [What are cron and crontab, and how do I use them? (什麼是 cron 和 crontab 以及如何使用它們？)](https://kb.iu.edu/d/afiz)。

雖然您可以使用 SSH 連線 `cron` 任務並編輯其 `crontab` 項目以在個別 Linux 執行個體上手動設定它們，但是 OpsWorks Stacks 的主要優點是您可以指示它跨整 layer 的執行個體執行任務。下列程序說明如何在 PHP App Server layer 的執行個體上設定`cron`任務，但您可以將相同的方法與任何 layer 搭配使用。

**若要在 layer 執行個體上設定 `cron` 任務**

1. 實作配方具有已設定任務之 `cron` 資源的技術指南。此範例假設配方命名為 `cronjob.rb`；稍後會說明實作詳細資訊。如需技術指南和配方的詳細資訊，請參閱[技術指南和配方](workingcookbook.md)。

1. 在您的堆疊上安裝技術指南。如需詳細資訊，請參閱[安裝自訂技術指南](workingcookbook-installingcustom-enable.md)。

1. 讓 OpsWorks Stacks 透過將配方指派給下列生命週期事件，在 layer 的執行個體上自動執行配方。如需詳細資訊，請參閱[自動執行配方](workingcookbook-assigningcustom.md)。
   + **設定** – 指派給`cronjob.rb`此事件會指示 OpsWorks Stacks 在所有新執行個體上執行配方。
   + **部署** – 當您將應用程式部署或重新部署至 layer 時，指派`cronjob.rb`至此事件會指示 OpsWorks Stacks 在所有線上執行個體上執行配方。

   您也可以使用 `Execute Recipes` 堆疊命令手動在線上執行個體上執行配方。如需詳細資訊，請參閱[執行堆疊命令](workingstacks-commands.md)。

以下是 `cronjob.rb` 範例，可設定 Cron 任務一週一次執行使用者實作的 PHP 應用程式，以從伺服器收集銷售資料，並透過郵件傳送報告。如需如何使用 cron 資源的更多範例，請參閱 [cron](https://docs.chef.io/chef/resources.html#cron)。

```
cron "job_name" do
  hour "1"
  minute "10"
  weekday "6"
  command "cd /srv/www/myapp/current && php .lib/mailing.php"
end
```

`cron` 是代表 `cron` 任務的 Chef 資源。當 OpsWorks Stacks 在執行個體上執行配方時，相關聯的提供者會處理設定任務的詳細資訊。
+ `job_name` 是 `cron` 任務的使用者定義名稱，例如 `weekly report`。
+ `hour`/`minute`/`weekday` 指定何時應該執行命令。此範例會在每週六的上午 1:10 執行命令。
+ `command` 指定要執行的命令。

  此範例執行兩個命令。第一個導覽至 `/srv/www/myapp/current` 目錄。第二個執行使用者實作的 `mailing.php` 應用程式，以收集銷售資料並傳送報告。

**注意**  
`bundle` 命令預設不會與 `cron` 任務搭配運作。原因是 OpsWorks Stacks 在 `/usr/local/bin`目錄中安裝 Bundler。若要搭配使用 `bundle` 與 `cron` 任務，您必須將路徑 `/usr/local/bin` 明確地新增至 Cron 任務。此外，因為 \$1PATH 環境變數可能不會在 `cron` 任務中擴展，所以最佳實務是將任何必要的路徑資訊明確地新增至任務，而不依賴擴展 \$1PATH 變數。下列範例顯示兩種在 `cron` 任務中使用 `bundle` 的方式。  

```
cron "my first task" do
  path "/usr/local/bin"
  minute "*/10"
  command "cd /srv/www/myapp/current && bundle exec my_command"
end
```

```
cron_env = {"PATH" => "/usr/local/bin"}
cron "my second task" do
  environment cron_env
  minute "*/10"
  command "cd /srv/www/myapp/current && /usr/local/bin/bundle exec my_command"
end
```

如果您的堆疊有多個應用程式伺服器，`cronjob.rb`則指派給 PHP App Server layer 的生命週期事件可能不是理想的方法。例如，配方會在 layer 的所有執行個體上執行，因此您會收到多份報告。較佳的方式是使用自訂 layer，確保只有一部伺服器傳送報告。

**只在 layer 的其中一個執行個體上執行配方**

1. 建立自訂 layer (例如稱為 PHPAdmin)，並將 `cronjob.rb` 指派給其安裝和部署事件。自訂 layer 不一定需要執行很多操作。在此情況下，PHPAdmin 只會在其執行個體上執行一個自訂配方。

1. 將其中一個 PHP App Server 執行個體指派給 AdminLayer。如果執行個體屬於多個 layer， OpsWorks Stacks 會執行每個 layer 的內建和自訂配方。

由於只有一個執行個體屬於 PHP App Server 和 PHPAdmin layer，因此 `cronjob.rb`只會在該執行個體上執行，而且您只會收到一個報告。

# 在 Linux 執行個體上安裝和設定套件
<a name="workingcookbook-extend-package"></a>

**重要**  
 AWS OpsWorks Stacks 此服務已於 2024 年 5 月 26 日終止，並已針對新客戶和現有客戶停用。我們強烈建議客戶盡快將其工作負載遷移至其他解決方案。如果您對遷移有任何疑問，請透過 [AWS re：Post](https://repost.aws/) 或透過 [AWS Premium Support](https://aws.amazon.com/support) 聯絡 AWS 支援 團隊。

內建 layer 只支援特定套件。如需詳細資訊，請參閱[層](workinglayers.md)。您可以安裝其他套件 (例如 Redis 伺服器)，方法是實作自訂配方來處理相關的安裝、組態和部署任務。在某些情況下，最佳方式是擴充內建 layer，讓它在其執行個體上安裝套件以及 layer 的標準套件。例如，如果您的堆疊支援 PHP 應用程式，而且您想要包含 Redis 伺服器，則除了 PHP 應用程式伺服器之外，您還可以擴展 PHP App Server layer 在 layer 的執行個體上安裝和設定 Redis 伺服器。

套件安裝配方一般需要執行任務，如下所示：
+ 建立一或多個目錄，並設定其模式。
+ 從範本建立組態檔案。
+ 在執行個體上執行安裝程式來安裝套件。
+ 啟動一或多個服務。

如需如何安裝 Tomcat 伺服器的範例，請參閱[建立自訂 Tomcat 伺服器 Layer](create-custom.md)。本主題說明如何設定自訂 Redis layer，但您可以使用更多相同的程式碼，以在內建 layer 上安裝和設定 Redis。如需如何安裝其他套件的範例，請參閱內建技術指南，網址為 https：//[https://github.com/aws/opsworks-cookbooks](https://github.com/aws/opsworks-cookbooks)。

# 建立自訂 Tomcat 伺服器 Layer
<a name="create-custom"></a>

**重要**  
 AWS OpsWorks Stacks 此服務已於 2024 年 5 月 26 日終止，並已針對新客戶和現有客戶停用。我們強烈建議客戶盡快將其工作負載遷移至其他解決方案。如果您對遷移有任何疑問，請透過 [AWS re：Post](https://repost.aws/) 或透過 [AWS Premium Support](https://aws.amazon.com/support) 聯絡 AWS 支援 團隊。

**注意**  
本主題說明如何實作 Linux 堆疊的自訂 layer。不過，基本原則和部分程式碼經改寫後也能用於實作 Windows 堆疊的自訂 layer，特別是應用程式部署一節的內容。

在 Stacks OpsWorks 執行個體上使用非標準套件的最簡單方法是[擴展現有的 layer](workingcookbook-extend-package.md)。但是，此方法會在 layer 的執行個體上同時安裝及執行標準和非標準套件，而這並非是您所想要的。有一種要求較高也更強大的方式，便是實作自訂 layer，讓您幾乎可以完全控制 layer 的執行個體，包含下列項目：
+ 要安裝的套件
+ 每個套件的設定方式
+ 從儲存庫將應用程式部署到執行個體的方式

無論您是使用主控台還是 API，您建立和管理自訂 layer 的方式與其他 layer 幾乎一模一樣，如[自訂 Layer](workinglayers-custom.md)所述。但是，自訂 layer 的內建配方會執行一些非常基本的任務，例如安裝 Ganglia 用戶端以將指標報告給 Ganglia 主機。若要使自訂 layer 執行個體不僅具有最低限度的功能，您必須使用 Chef 配方和相關檔案實作一或多個自訂技術指南，以處理安裝及設定套件、部署應用程式等任務。但您不一定需要從頭開始實作所有東西。例如，若您在其中一個標準儲存庫中存放應用程式，您可以使用內建的部署配方處理在 layer 的執行個體上安裝應用程式的大部分工作。

**注意**  
如果您是第一次使用 Chef，建議您先閱讀[技術指南 101](cookbooks-101.md)，該教學介紹如何實作技術指南以執行各種常見任務的基本概念。

下列演練說明如何實作支援 Tomcat 應用程式伺服器的自訂 layer。layer 是以名為 Tomcat 的自訂技術指南為基礎，其中包含處理套件安裝、部署等的配方。演練包含摘錄自 Tomcat 技術指南的摘要。您可以從其 [GitHub 儲存庫](https://github.com/amazonwebservices/opsworks-example-cookbooks/tree/master/tomcat)下載完整的技術指南。若您不熟悉 [Opscode Chef](http://www.opscode.com/chef/)，建議您先閱讀[技術指南和配方](workingcookbook.md)。

**注意**  
OpsWorks Stacks 包含用於生產用途的完整功能 [Java App Server layer](layers-java.md)。Tomcat 技術指南的目的是示範如何實作自訂 layer，使其支援 Tomcat 限制版本 (不包含諸如 SSL 等功能)。如需完整實作的範例，請參閱內建的 [opsworks\$1java](https://github.com/aws/opsworks-cookbooks/tree/release-chef-11.10/opsworks_java) 技術指南。

Tomcat 技術指南支援執行個體具有下列特性的自訂 layer：
+ 他們支援使用 Apache 前端的 Tomcat Java 應用程式伺服器。
+ Tomcat 設定為允許應用程式使用 JDBC `DataSource` 物件連線到單獨的 MySQL 執行個體，做為後端資料存放區。

此專案的技術指南涉及幾項主要元件：
+ [屬性檔案](create-custom-attributes.md)包含各種配方會使用的組態設定。
+ [安裝配方](create-custom-setup.md)會指派給 layer 的安裝[生命週期事件](workingcookbook-events.md)。他們會在執行個體啟動並執行像是安裝套件和建立組態檔案等任務後執行。
+ [設定配方](create-custom-configure.md)會指派給 layer 的設定生命週期事件。它們會在堆疊的組態變更後執行，主要是在執行個體上線或離線時，並處理任何必要的組態變更。
+ [部署配方](create-custom-deploy.md)會指派給 layer 的部署生命週期事件。他們會在安裝配方之後，以及您手動部署應用程式，然後在 layer 的執行個體上安裝程式碼和相關檔案時執行，並會處理相關任務 (例如重新啟動服務)。

最後一節 說明如何建立堆疊，其中包含以 Tomcat 技術指南為基礎的自訂 layer[建立堆疊和執行應用程式](create-custom-stack.md)，以及如何部署和執行簡單的 JSP 應用程式，以顯示在屬於個別 MySQL layer 的執行個體上執行之 MySQL 資料庫的資料。

**注意**  
Tomcat 技術指南配方取決於一些 OpsWorks Stacks 內建配方。為使每個配方的來源更為清晰，本主題會使用 Chef *cookbookname*::*recipename* 慣例識別配方。

**Topics**
+ [屬性檔案](create-custom-attributes.md)
+ [安裝配方](create-custom-setup.md)
+ [設定配方](create-custom-configure.md)
+ [部署配方](create-custom-deploy.md)
+ [建立堆疊和執行應用程式](create-custom-stack.md)

# 屬性檔案
<a name="create-custom-attributes"></a>

**重要**  
 AWS OpsWorks Stacks 此服務已於 2024 年 5 月 26 日終止，並已針對新客戶和現有客戶停用。我們強烈建議客戶盡快將其工作負載遷移至其他解決方案。如果您對遷移有任何疑問，請透過 [AWS re：Post](https://repost.aws/) 或透過 [AWS Premium Support](https://aws.amazon.com/support) 聯絡 AWS 支援 團隊。

在查看配方前，先檢查 Tomcat 技術指南的屬性檔案 (包含各種配方使用的組態設定) 會非常有用。屬性並非必要項目。您可以直接以硬式編碼的方式在您的配方或範本中撰寫這些值。不過，如果您使用屬性定義組態設定，您可以使用 OpsWorks Stacks 主控台或 API 透過定義自訂 JSON 屬性來修改值，這比每次變更設定時重寫配方或範本程式碼更簡單且更具彈性。舉例來說，這種方法可讓您針對多個堆疊使用相同的技術指南，但為每一個堆疊分別設定不同的 Tomcat 伺服器。如需屬性和其覆寫方式的詳細資訊，請參閱[覆寫屬性](workingcookbook-attributes.md)。

下列範例顯示完整的屬性檔案 (`default.rb`)，位於 Tomcat 技術指南的 `attributes` 目錄。

```
default['tomcat']['base_version'] = 6
default['tomcat']['port'] = 8080
default['tomcat']['secure_port'] = 8443
default['tomcat']['ajp_port'] = 8009
default['tomcat']['shutdown_port'] = 8005
default['tomcat']['uri_encoding'] = 'UTF-8'
default['tomcat']['unpack_wars'] = true
default['tomcat']['auto_deploy'] = true
case node[:platform]
when 'centos', 'redhat', 'fedora', 'amazon'
  default['tomcat']['java_opts'] = ''
when 'debian', 'ubuntu'
  default['tomcat']['java_opts'] = '-Djava.awt.headless=true -Xmx128m -XX:+UseConcMarkSweepGC'
end
default['tomcat']['catalina_base_dir'] = "/etc/tomcat#{node['tomcat']['base_version']}"
default['tomcat']['webapps_base_dir'] = "/var/lib/tomcat#{node['tomcat']['base_version']}/webapps"
default['tomcat']['lib_dir'] = "/usr/share/tomcat#{node['tomcat']['base_version']}/lib"
default['tomcat']['java_dir'] = '/usr/share/java'
default['tomcat']['mysql_connector_jar'] = 'mysql-connector-java.jar'
default['tomcat']['apache_tomcat_bind_mod'] = 'proxy_http' # or: 'proxy_ajp'
default['tomcat']['apache_tomcat_bind_config'] = 'tomcat_bind.conf'
default['tomcat']['apache_tomcat_bind_path'] = '/tc/'
default['tomcat']['webapps_dir_entries_to_delete'] = %w(config log public tmp)
case node[:platform]
when 'centos', 'redhat', 'fedora', 'amazon'
  default['tomcat']['user'] = 'tomcat'
  default['tomcat']['group'] = 'tomcat'
  default['tomcat']['system_env_dir'] = '/etc/sysconfig'
when 'debian', 'ubuntu'
  default['tomcat']['user'] = "tomcat#{node['tomcat']['base_version']}"
  default['tomcat']['group'] = "tomcat#{node['tomcat']['base_version']}"
  default['tomcat']['system_env_dir'] = '/etc/default'
end
```

設定本身會在稍後的相關章節中討論。下列注意事項一概適用：
+ 所有的節點定義都是 `default` 類型，讓您可以使用[自訂 JSON 屬性](workingcookbook-json-override.md)予以覆寫。
+ 檔案使用 `case` 陳述式，根據執行個體的作業系統，有條件的設定一些屬性值。

  `platform` 節點是由 Chef 的 Ohai 工具產生的，代表執行個體的作業系統。

# 安裝配方
<a name="create-custom-setup"></a>

**重要**  
 AWS OpsWorks Stacks 此服務已於 2024 年 5 月 26 日終止，並已針對新客戶和現有客戶停用。我們強烈建議客戶盡快將其工作負載遷移至其他解決方案。如果您對遷移有任何疑問，請透過 [AWS re：Post](https://repost.aws/) 或透過 [AWS Premium Support](https://aws.amazon.com/support) 聯絡 AWS 支援 團隊。

安裝配方會指派給 layer 的安裝[生命週期](workingcookbook-events.md)事件，並會在執行個體啟動後執行。他們會執行像是安裝套件、建立組態檔案和啟動服務等任務。安裝配方完成執行後， OpsWorks Stacks 會執行[部署配方](create-custom-deploy.md)，將任何應用程式部署到新的執行個體。

**Topics**
+ [tomcat::setup](#create-custom-setup-setup)
+ [tomcat::install](#create-custom-setup-install)
+ [tomcat::service](#create-custom-setup-service)
+ [tomcat::container\$1config](#create-custom-setup-config)
+ [tomcat::apache\$1tomcat\$1bind](#create-custom-setup-bind)

## tomcat::setup
<a name="create-custom-setup-setup"></a>

`tomcat::setup` 配方用於指派給 layer 的安裝生命週期事件。

```
include_recipe 'tomcat::install'
include_recipe 'tomcat::service'

service 'tomcat' do
  action :enable
end

# for EBS-backed instances we rely on autofs
bash '(re-)start autofs earlier' do
  user 'root'
  code <<-EOC
    service autofs restart
  EOC
  notifies :restart, resources(:service => 'tomcat')
end

include_recipe 'tomcat::container_config'
include_recipe 'apache2'
include_recipe 'tomcat::apache_tomcat_bind'
```

`tomcat::setup` 配方基本上就是一個中繼配方。它包含一組處理大部分安裝和設定 Tomcat 之詳細資訊和相關套件的依存配方。`tomcat::setup` 的第一個部分會執行下列配方。下列配方會在稍後進行討論：
+ [tomcat::install](#create-custom-setup-install) 配方會安裝 Tomcat 伺服器套件。
+ [tomcat::service](#create-custom-setup-service) 配方會設定 Tomcat 服務。

`tomcat::setup` 的中間部分會啟用並執行 Tomcat 服務：
+ Chef [service 資源](https://docs.chef.io/chef/resources.html#service)會在開機時啟用 Tomcat 服務。
+ Chef [bash 資源](https://docs.chef.io/chef/resources.html#bash)會執行 Bash 指令碼來啟動 autofs 協助程式，這是 Amazon EBS 後端執行個體的必要項目。資源接著會通知 `service` 資源重新啟動 Tomcat 服務。

  如需詳細資訊，請參閱 [autofs](https://access.redhat.com/site/documentation/en-US/Red_Hat_Enterprise_Linux/6/html/Storage_Administration_Guide/s2-nfs-config-autofs.html) (Amazon Linux 適用) 或 [Autofs](https://help.ubuntu.com/community/Autofs) (Ubuntu 適用)。

`tomcat::setup` 的最後部分會建立組態檔案，安裝及設定前端 Apache 伺服器：
+ [tomcat::container\$1config](#create-custom-setup-config) 配方會建立組態檔案。
+ `apache2` 配方 ( 的速記`apache2::default`) 是安裝和設定 Apache 伺服器的 OpsWorks Stacks 內建配方。
+ [tomcat::apache\$1tomcat\$1bind](#create-custom-setup-bind) 配方會設定 Apache 伺服器，做為 Tomcat 伺服器的前端。

**注意**  
您通常可以透過使用內建配方執行一部分的必要任務，省下時間和精力。此配方使用內建的 `apache2::default` 配方安裝 Apache，而非從零開始實作。如需如何使用內建配方的另一個範例，請參閱[部署配方](create-custom-deploy.md)。

下列章節會更詳細的說明 Tomcat 技術指南的安裝配方。如需 `apache2` 配方的詳細資訊，請參閱 [opsworks-cookbooks/apache2](https://github.com/aws/opsworks-cookbooks/tree/release-chef-11.4/apache2)。

## tomcat::install
<a name="create-custom-setup-install"></a>

`tomcat::install `配方會安裝 Tomcat 伺服器、OpenJDK 和處理 MySQL 伺服器連線的 Java 連接器程式庫。

```
tomcat_pkgs = value_for_platform(
  ['debian', 'ubuntu'] => {
    'default' => ["tomcat#{node['tomcat']['base_version']}", 'libtcnative-1', 'libmysql-java']
  },
  ['centos', 'redhat', 'fedora', 'amazon'] => {
    'default' => ["tomcat#{node['tomcat']['base_version']}", 'tomcat-native', 'mysql-connector-java']
  },
  'default' => ["tomcat#{node['tomcat']['base_version']}"]
)

tomcat_pkgs.each do |pkg|
  package pkg do
    action :install
  end
end

link ::File.join(node['tomcat']['lib_dir'], node['tomcat']['mysql_connector_jar']) do
  to ::File.join(node['tomcat']['java_dir'], node['tomcat']['mysql_connector_jar'])
  action :create
end

# remove the ROOT webapp, if it got installed by default
include_recipe 'tomcat::remove_root_webapp'
```

配方會執行下列任務：

1. 根據執行個體的作業系統建立要安裝的套件清單。

1. 安裝清單中的每個套件。

   Chef [套件資源](https://docs.chef.io/chef/resources.html#id146)使用適用於 Amazon Linux 和 `apt-get` Ubuntu 的適當提供者`yum`來處理安裝。套件提供者會將 OpenJDK 做為 Tomcat 的依存安裝，但 MySQL 連接器程式庫必須明確安裝。

1. 使用 Chef [link 資源](https://docs.chef.io/chef/resources.html#link)，在 Tomcat 伺服器的 lib 目錄中建立連結到 JDK 中 MySQL 連接器程式庫的 symlink。

   使用預設屬性值，Tomcat lib 目錄為 `/usr/share/tomcat6/lib`，MySQL 連接器程式庫 (`mysql-connector-java.jar`) 則位於 `/usr/share/java/`。

`tomcat::remove_root_webapp` 配方會移除 ROOT web 應用程式 (預設為 `/var/lib/tomcat6/webapps/ROOT`)，避免某些安全問題。

```
ruby_block 'remove the ROOT webapp' do
  block do
    ::FileUtils.rm_rf(::File.join(node['tomcat']['webapps_base_dir'], 'ROOT'), :secure => true)
  end
  only_if { ::File.exists?(::File.join(node['tomcat']['webapps_base_dir'], 'ROOT')) && !::File.symlink?(::File.join(node['tomcat']['webapps_base_dir'], 'ROOT')) }
end
```

`only_if` 陳述式會確保只有在檔案存在時，配方才會移除他們。

**注意**  
Tomcat 的版本以 `['tomcat']['base_version']` 屬性指定，其在屬性檔案中已設為 6。若要安裝 Tomcat 7，您可以使用自訂 JSON 屬性覆寫屬性。您只需[編輯您的堆疊設定](workingstacks-edit.md)並在 **Custom Chef JSON (自訂 Chef JSON)** 方塊中輸入下列 JSON，或是將其新增至任何現有的自訂 JSON：  

```
{
  'tomcat' : {
    'base_version' : 7
  }
}
```
自訂 JSON 屬性會覆寫預設屬性，並將 Tomcat 的版本設為 7。如需覆寫屬性的詳細資訊，請參閱[覆寫屬性](workingcookbook-attributes.md)。

## tomcat::service
<a name="create-custom-setup-service"></a>

`tomcat::service` 配方會建立 Tomcat 服務定義。

```
service 'tomcat' do
  service_name "tomcat#{node['tomcat']['base_version']}"

  case node[:platform]
  when 'centos', 'redhat', 'fedora', 'amazon'
    supports :restart => true, :reload => true, :status => true
  when 'debian', 'ubuntu'
    supports :restart => true, :reload => false, :status => true
  end

  action :nothing
end
```

配方會使用 Chef [service 資源](https://docs.chef.io/chef/resources.html#service)指定 Tomcat 服務名稱 (預設為 tomcat6)，並設定 `supports` 屬性，以定義 Chef 管理服務重新啟動、重新載入和在不同作業系統上狀態命令的方式。
+ `true` 表示 Chef 可使用 init 指令碼或其他服務提供者執行命令。
+ `false` 表示 Chef 必須嘗試使用其他方式執行命令。

請注意，`action` 已設為 `:nothing`。對於每個生命週期事件， OpsWorks Stacks 會啟動 [Chef 執行](https://docs.chef.io/chef_client_overview.html#the-chef-client-run)，以執行適當的配方集。Tomcat 技術指南遵循讓配方建立服務定義，但不重新啟動服務的常見模式。Chef 執行中的其他配方會處理重新啟動，其方式通常為藉由在用來建立組態檔案的 `notifies` 資源中包含 `template` 命令。通知為重新啟動服務的一種便利方式，因為他們只會在組態變更時才會執行此作業。此外，當 Chef 執行具有多個服務的重新啟動通知時，Chef 最多只會重新啟動服務一次。這種做法可避免在嘗試重新啟動未完全運作的服務時可能發生的問題。此為 Tomcat 錯誤的常見來源。

 必須為任何使用重新啟動通知的 Chef run 定義 Tomcat 服務。因此，`tomcat::service` 會包含在數個配方中，確保為每一個 Chef run 定義服務。即使 Chef 執行包含多個 `tomcat::service` 的執行個體，也不會有任何損失，因為 Chef 會確保每個配方只會在每次執行時執行一次，無論其包含多少次在內。

## tomcat::container\$1config
<a name="create-custom-setup-config"></a>

`tomcat::container_config` 配方會從技術指南範本檔案建立組態檔案。

```
include_recipe 'tomcat::service'

template 'tomcat environment configuration' do
  path ::File.join(node['tomcat']['system_env_dir'], "tomcat#{node['tomcat']['base_version']}")
  source 'tomcat_env_config.erb'
  owner 'root'
  group 'root'
  mode 0644
  backup false
  notifies :restart, resources(:service => 'tomcat')
end

template 'tomcat server configuration' do
  path ::File.join(node['tomcat']['catalina_base_dir'], 'server.xml')
  source 'server.xml.erb'
  owner 'root'
  group 'root'
  mode 0644
  backup false
  notifies :restart, resources(:service => 'tomcat')
end
```

配方首先會呼叫 `tomcat::service`，其將於必要時定義服務。大量的配方皆由兩個 [template 資源](https://docs.chef.io/chef/resources.html#template)組成，這兩個資源會各自從其中一個技術指南範本檔案建立組態檔案、設定檔案屬性，並通知 Chef 重新啟動服務。

### Tomcat 環境資訊檔案
<a name="create-custom-setup-config-env"></a>

第一個 `template` 資源會使用 `tomcat_env_config.erb` 範本檔案建立 Tomcat 環境資訊檔案，用於設定像是 `JAVA_HOME` 等環境變數。預設檔案名稱為 `template` 資源的引數。`tomcat::container_config` 會使用 `path` 屬性覆寫預設值及命名組態檔 `/etc/sysconfig/tomcat6` (Amazon Linux) 或 `/etc/default/tomcat6` (Ubuntu)。`template` 資源也會指定檔案的擁有者、群組和模式設定，並指示 Chef 不要建立備份檔案。

若您查看來源碼，通常會有三種版本的 `tomcat_env_config.erb`，每一種都位於 `templates` 目錄中的不同子目錄內。`ubuntu` 和 `amazon` 目錄包含其各自作業系統的範本。`default` 資料夾則包含僅有一行註解的 dummy 範本，僅會在您嘗試在使用不支援作業系統的執行個體上執行此配方時使用。`tomcat::container_config` 配方不需要指定要使用何種 `tomcat_env_config.erb`。Chef 會自動根據[檔案精確性](http://docs.chef.io/templates.html#file-specificity)中描述的規則，為執行個體的作業系統挑選適當的目錄。

此範例的 `tomcat_env_config.erb` 檔案大部分由註解組成。若要設定其他環境變數，只需要取消註解適當的行，並提供您喜好的值即可。

**注意**  
任何可能變更的組態設定都應定義為屬性，而非在範本中硬式編碼。如此一來，您便不需要重新撰寫範本以變更設定；您可以直接覆寫屬性。

Amazon Linux 範本只會設定一個環境變數，如下列摘要所示。

```
...
# Use JAVA_OPTS to set java.library.path for libtcnative.so
#JAVA_OPTS="-Djava.library.path=/usr/lib"

JAVA_OPTS="${JAVA_OPTS} <%= node['tomcat']['java_opts'] %>"

# What user should run tomcat
#TOMCAT_USER="tomcat"
...
```

JAVA\$1OPTS 可用來指定 Java 選項 (例如程式庫路徑)。若使用預設屬性值，範本便不會為 Amazon Linux 設定任何 Java 選項。您可以藉由覆寫 `['tomcat']['java_opts']` 屬性 (例如：使用自訂 JSON 屬性)，來設定您自己的 Java 選項。如需範例，請參閱 [建立堆疊](create-custom-stack.md#create-custom-stack-stack)。

Ubuntu 範本會設定數個環境變數，如下列範本摘要所示。

```
# Run Tomcat as this user ID. Not setting this or leaving it blank will use the
# default of tomcat<%= node['tomcat']['base_version'] %>.
TOMCAT<%= node['tomcat']['base_version'] %>_USER=tomcat<%= node['tomcat']['base_version'] %>
...
# Run Tomcat as this group ID. Not setting this or leaving it blank will use
# the default of tomcat<%= node['tomcat']['base_version'] %>.
TOMCAT<%= node['tomcat']['base_version'] %>_GROUP=tomcat<%= node['tomcat']['base_version'] %>
...
JAVA_OPTS="<%= node['tomcat']['java_opts'] %>"

<% if node['tomcat']['base_version'].to_i < 7 -%>
# Unset LC_ALL to prevent user environment executing the init script from
# influencing servlet behavior.  See Debian bug #645221
unset LC_ALL
<% end -%>
```

若使用預設屬性值，範本便會設定 Ubuntu 環境變數，如下所示：
+ 代表 Tomcat 使用者和群組的 `TOMCAT6_USER` 和 `TOMCAT6_GROUP` 都已設為 `tomcat6`。

  若您將 ['tomcat']['base\$1version'] 設為 `tomcat7`，變數名稱會解析為 `TOMCAT7_USER` 和 `TOMCAT7_GROUP`，並且都會設為 `tomcat7`。
+ `JAVA_OPTS` 已設定為 `-Djava.awt.headless=true -Xmx128m -XX:+UseConcMarkSweepGC`：
  + 將 `-Djava.awt.headless` 設為 `true` 會向圖形引擎通知執行個體沒有標題並且也沒有主控台，表示特定圖形應用程式的錯誤行為。
  + `-Xmx128m` 可確保 JVM 具有足夠的記憶體資源，此範例為 128MB。
  + `-XX:+UseConcMarkSweepGC` 指定同時標記整理記憶體回收，協助限制記憶體回收造成的暫停。

    如需詳細資訊，請參閱 [Concurrent Mark Sweep Collector Enhancements](http://docs.oracle.com/javase/6/docs/technotes/guides/vm/cms-6.html)。
+ 若 Tomcat 的版本低於 7，範本會取消設定處理 Ubuntu 錯誤的 `LC_ALL`。

**注意**  
若使用預設屬性，部分環境變數便會設為其預設值。但是，明確將環境變數設為屬性表示您可以定義自訂 JSON 屬性覆寫預設屬性，並提供自訂的值。如需覆寫屬性的詳細資訊，請參閱[覆寫屬性](workingcookbook-attributes.md)。

如需完整的範本檔案，請參閱[來源碼](https://github.com/amazonwebservices/opsworks-example-cookbooks/tree/master/tomcat)。

### Server.xml 組態檔案
<a name="create-custom-setup-config-server"></a>

第二個 `template` 資源會使用 `server.xml.erb` 建立 [`system.xml` 組態檔](http://tomcat.apache.org/tomcat-7.0-doc/config/)，設定 servlet/JSP 容器。`server.xml.erb` 沒有包含任何作業系統限定設定，因此它會位於 `template` 目錄的 `default` 子目錄中。

範本使用者使用標準設定，但它也可以為 Tomcat 6 或 Tomcat 7 建立 `system.xml` 檔案。例如，下列來自範本的伺服器區段的程式碼會為指定的版本適當設定接聽程式。

```
<% if node['tomcat']['base_version'].to_i > 6 -%>
  <!-- Security listener. Documentation at /docs/config/listeners.html
  <Listener className="org.apache.catalina.security.SecurityListener" />
  -->
<% end -%>
  <!--APR library loader. Documentation at /docs/apr.html -->
  <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
  <!--Initialize Jasper prior to webapps are loaded. Documentation at /docs/jasper-howto.html -->
  <Listener className="org.apache.catalina.core.JasperListener" />
  <!-- Prevent memory leaks due to use of particular java/javax APIs-->
  <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
<% if node['tomcat']['base_version'].to_i < 7 -%>
  <!-- JMX Support for the Tomcat server. Documentation at /docs/non-existent.html -->
  <Listener className="org.apache.catalina.mbeans.ServerLifecycleListener" />
<% end -%>
  <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
<% if node['tomcat']['base_version'].to_i > 6 -%>
  <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
<% end -%>
```

範本使用屬性，而非硬式編碼設定，讓您可以藉由定義自訂 JSON 屬性，輕易變更設定。例如：

```
<Connector port="<%= node['tomcat']['port'] %>" protocol="HTTP/1.1"
           connectionTimeout="20000"
           URIEncoding="<%= node['tomcat']['uri_encoding'] %>"
           redirectPort="<%= node['tomcat']['secure_port'] %>" />
```

如需詳細資訊，請參閱[來源碼](https://github.com/amazonwebservices/opsworks-example-cookbooks/tree/master/tomcat)。

## tomcat::apache\$1tomcat\$1bind
<a name="create-custom-setup-bind"></a>

`tomcat::apache_tomcat_bind` 配方會啟用 Apache 伺服器做為 Tomcat 的前端，接受傳入的請求，並將他們轉遞至 Tomcat 並將回應傳回用戶端。此範例使用 [mod\$1proxy](https://httpd.apache.org/docs/2.2/mod/mod_proxy.html) 做為 Apache 代理/閘道。

```
execute 'enable mod_proxy for apache-tomcat binding' do
  command '/usr/sbin/a2enmod proxy'
  not_if do
    ::File.symlink?(::File.join(node['apache']['dir'], 'mods-enabled', 'proxy.load')) || node['tomcat']['apache_tomcat_bind_mod'] !~ /\Aproxy/
  end
end

execute 'enable module for apache-tomcat binding' do
  command "/usr/sbin/a2enmod #{node['tomcat']['apache_tomcat_bind_mod']}"
  not_if {::File.symlink?(::File.join(node['apache']['dir'], 'mods-enabled', "#{node['tomcat']['apache_tomcat_bind_mod']}.load"))}
end

include_recipe 'apache2::service'

template 'tomcat thru apache binding' do
  path ::File.join(node['apache']['dir'], 'conf.d', node['tomcat']['apache_tomcat_bind_config'])
  source 'apache_tomcat_bind.conf.erb'
  owner 'root'
  group 'root'
  mode 0644
  backup false
  notifies :restart, resources(:service => 'apache2')
end
```

若要啟用 `mod_proxy`，您必須啟用 `proxy` 模組及通訊協定式模組。您有兩個通訊協定模組選項：
+ HTTP: `proxy_http`
+ [Apache JServ 通訊協定](http://tomcat.apache.org/connectors-doc/ajp/ajpv13a.html) (ASP)：`proxy_ajp`

  AJP 是一種內部 Tomcat 通訊協定。

兩種配方的 [execute 資源](https://docs.chef.io/chef/resources.html#execute)都會執行 `a2enmod` 命令，透過建立必要的 symlink 啟用指定的模組：
+ 第一個 `execute` 資源會啟用 `proxy` 模組。
+ 第二個 `execute` 資源會啟用通訊協定模組，根據預設設為 `proxy_http`。

  若您要使用 AJP，您可以定義自訂 JSON 覆寫 `apache_tomcat_bind_mod` 屬性，將其設為 `proxy_ajp`。

`apache2::service` 配方是定義 Apache OpsWorks 服務的 Stacks 內建配方。如需詳細資訊，請參閱 Stacks GitHub OpsWorks 儲存庫中的[配方](https://github.com/aws/opsworks-cookbooks/blob/release-chef-11.4/apache2/recipes/service.rb)。

`template` 資源使用 `apache_tomcat_bind.conf.erb` 建立根據預設名為 `tomcat_bind.conf` 的組態檔案。它會將檔案置放在 `['apache']['dir']/.conf.d` 目錄中。`['apache']['dir']` 屬性會在內建的 `apache2` 屬性檔案中定義，並根據預設設為 `/etc/httpd` (Amazon Linux) 或 `/etc/apache2` (Ubuntu)。若 `template` 資源建立或變更組態檔案，`notifies` 命令會排程 Apache 服務重新啟動。

```
<% if node['tomcat']['apache_tomcat_bind_mod'] == 'proxy_ajp' -%>
ProxyPass <%= node['tomcat']['apache_tomcat_bind_path'] %> ajp://localhost:<%= node['tomcat']['ajp_port'] %>/
ProxyPassReverse <%= node['tomcat']['apache_tomcat_bind_path'] %> ajp://localhost:<%= node['tomcat']['ajp_port'] %>/
<% else %>
ProxyPass <%= node['tomcat']['apache_tomcat_bind_path'] %> http://localhost:<%= node['tomcat']['port'] %>/
ProxyPassReverse <%= node['tomcat']['apache_tomcat_bind_path'] %> http://localhost:<%= node['tomcat']['port'] %>/
<% end -%>
```

範本使用 [ProxyPass](https://httpd.apache.org/docs/2.0/mod/mod_proxy.html#proxypass) 和 [ProxyPassReverse](https://httpd.apache.org/docs/2.0/mod/mod_proxy.html#proxypassreverse) 指示詞設定用來在 Apache 和 Tomcat 間傳遞流量的連接埠。因為兩個伺服器都位於相同的執行個體上，他們可以使用 localhost URL，並且根據預設都會設為 `http://localhost:8080`。

# 設定配方
<a name="create-custom-configure"></a>

**重要**  
 AWS OpsWorks Stacks 此服務已於 2024 年 5 月 26 日終止，並已針對新客戶和現有客戶停用。我們強烈建議客戶盡快將其工作負載遷移至其他解決方案。如果您對遷移有任何疑問，請透過 [AWS re：Post](https://repost.aws/) 或透過 [AWS Premium Support](https://aws.amazon.com/support) 聯絡 AWS 支援 團隊。

設定配方會指派給 layer 的設定[生命週期](workingcookbook-events.md)事件，該事件會在執行個體進入或離開線上狀態時，在所有堆疊的執行個體上發生。您可使用設定配方調整執行個體的組態，以適當回應變更。當您實作設定配方時，請記得堆疊組態變更可能會涉及與這一 layer 無關的執行個體。配方必須要能適當地進行回應，在某些案例中，可能不會進行任何行為。

## tomcat::configure
<a name="create-custom-configure-configure"></a>

`tomcat::configure` 配方用於 layer 的設定生命週期事件。

```
include_recipe 'tomcat::context'
# Optional: Trigger a Tomcat restart in case of a configure event, if relevant
# settings in custom JSON have changed (e.g. java_opts/JAVA_OPTS):
#include_recipe 'tomcat::container_config'
```

`tomcat::configure` 配方基本上就是執行兩個依存配方的中繼配方。

1. `tomcat::context` 配方會建立 web 應用程式內容組態檔案。

   此檔案會設定應用程式用來與 MySQL 執行個體通訊的 JDBC 資源，如下一節所討論。執行此配方以回應設定事件，可讓 layer 在資料庫 layer 變更時更新 web 應用程式內容組態檔案。

1. `tomcat::container_config` 安裝配方會再次執行，以擷取任何容器組態中的變更。

`include` 的 `tomcat::container_config` 在此範例中已標示為註解。若您希望使用自訂的 JSON 修改 Tomcat 設定，您可以移除註解。設定生命週期事件接著會執行 `tomcat::container_config` 更新 Tomcat 的相關組態檔案 (如 [tomcat::container\$1config](create-custom-setup.md#create-custom-setup-config) 所述) 並重新啟動 Tomcat 服務。

## tomcat::context
<a name="create-custom-configure-context"></a>

Tomcat 技術指南可透過使用 [J2EE DataSource](http://docs.oracle.com/javase/tutorial/jdbc/basics/sqldatasources.html) 物件，讓應用程式存取可能在分離的執行個體上執行的 MySQL 資料庫伺服器。透過 Tomcat，您可以藉由建立和安裝每個應用程式的 web 應用程式內容組態檔案，來啟用連線。此檔案定義應用程式和應用程式用來與資料庫通訊之 JDBC 資源間的關聯。如需詳細資訊，請參閱[內容容器](http://tomcat.apache.org/tomcat-7.0-doc/config/context.html)。

`tomcat::context` 配方的主要用途是建立此組態檔案。

```
include_recipe 'tomcat::service'

node[:deploy].each do |application, deploy|
  context_name = deploy[:document_root].blank? ? application : deploy[:document_root]

  template "context file for #{application} (context name: #{context_name})" do
    path ::File.join(node['tomcat']['catalina_base_dir'], 'Catalina', 'localhost', "#{context_name}.xml")
    source 'webapp_context.xml.erb'
    owner node['tomcat']['user']
    group node['tomcat']['group']
    mode 0640
    backup false
    only_if { node['datasources'][context_name] }
    variables(:resource_name => node['datasources'][context_name], :webapp_name => application)
    notifies :restart, resources(:service => 'tomcat')
  end
end
```

除了 Tomcat 技術指南屬性之外，此配方還使用 OpsWorks Stacks 隨設定事件一起安裝的[堆疊組態和部署屬性](workingcookbook-json.md)。Stacks OpsWorks 服務會將屬性新增至每個執行個體的節點物件，其中包含配方通常會使用資料包或搜尋取得的資訊，並在每個執行個體上安裝屬性。屬性包含堆疊組態、部署應用程式和任何使用者希望包含之自訂資料的詳細資訊。配方可透過使用標準 Chef 節點語法，從堆疊組態和部署屬性取得資料。如需詳細資訊，請參閱[堆疊組態及部署屬性](workingcookbook-json.md)。透過 Chef 11.10 堆疊，您也可以使用 Chef 搜尋取得堆疊組態和部署資料。如需詳細資訊，請參閱[使用 Chef 搜尋](workingcookbook-chef11-10.md#workingcookbook-chef11-10-search)。

`deploy` 屬性是指`[:deploy]`命名空間，其中包含透過主控台或 API 定義的部署相關屬性，或由 Stacks OpsWorks 服務產生的屬性。`deploy` 屬性包含每個部署應用程式的屬性，以應用程式的短名命名。每個應用程式屬性都包含一組描述應用程式的屬性，例如文件根 (`[:deploy][:appname][:document_root]`)。

`context` 配方首先會透過呼叫 [tomcat::service](create-custom-setup.md#create-custom-setup-service)，確認已為此 Chef 執行定義服務。它接著會定義 `context_name` 變數，代表組態檔案的名稱 (排除 `.xml` 副檔名)。若您使用預設文件根，`context_name` 會設為應用程式的短名。否則，它會設為指定的文件根。[建立堆疊和執行應用程式](create-custom-stack.md)中討論的範例會將文件根設為 `"ROOT"`，因此內容為 ROOT，組態檔案則名為 `ROOT.xml`。

大量的配方都會穿過每個應用程式的部署應用程式清單，使用 `webapp_context.xml.erb` 範本建立內容組態檔案。範例只會部署一個應用程式，但 `deploy` 屬性的定義仍會要求您將其視為應用程式清單處理。

`webapp_context.xml.erb` 範本並非作業系統限定，因此它會位於 `templates` 目錄的 `default` 子目錄中。

配方會建立組態檔案如下：
+ 當使用預設屬性值時，組態檔案名稱會設為 `context_name.xml`，並安裝在 `/etc/tomcat6/Catalina/localhost/` 目錄中。

  堆疊組態屬性的 `['datasources']` 節點包含一或多個屬性，每一種都會將一個內容名稱映射到關聯應用程式用來與資料庫通訊的 JDBC 資料來源。節點和其內容都會在您建立堆疊時，使用自訂 JSON 定義，如稍後的[建立堆疊和執行應用程式](create-custom-stack.md)所述。範例具有將 ROOT 內容名稱與名為 jdbc/mydb 的 JDBC 資源建立關聯的單一屬性。
+ 使用預設屬性值，檔案的使用者和群組都會設為由 Tomcat 套件定義的值：`tomcat` (Amazon Linux) 或 `tomcat6` (Ubuntu)。
+ `template` 資源只會在 `['datasources']` 節點存在且包含 `context_name` 屬性值建立組態檔案。
+ `template` 資源會定義兩個變數：`resource_name` 和 `webapp_name`。

  `resource_name` 已設為與 `context_name` 關聯的資源名稱，`webapp_name` 則已設為應用程式的短名。
+ 範本資源會重新啟動 Tomcat 服務，載入及啟用變更。

`webapp_context.xml.erb` 範本由包含具有自己屬性組之 `Context` 元素的 `Resource` 元素組成。

`Resource` 屬性會描述內容組態的特性：
+ **name** – JDBC 資源名稱，設定為 中定義的`resource_name`值`tomcat::context`。

  例如，資源名稱已設為 jdbc/mydb。
+ **驗證**和**類型** – 這些是 JDBC `DataSource`連線的標準設定。
+ **maxActive**、**maxIdle** 和 **maxWait** – 作用中和閒置連線的數量上限，以及傳回連線的等待時間上限。
+ **username**， and **password** – 從`deploy`屬性取得的資料庫使用者名稱和根密碼。
+ **driverClassName** – JDBC 驅動程式的類別名稱，設定為 MySQL 驅動程式。
+ **url** – 連線 URL。

  前綴取決於資料庫。其應設為 `jdbc:mysql` (MySQL)、`jdbc:postgresql` (Postgres) 和 `jdbc:sqlserver` (SQL Server)。範例將 URL 設為 `jdbc:mysql://host_IP_Address:3306:simplejsp`，其中 *simplejsp* 為應用程式的短名。
+ **factory** – MySQL 資料庫需要的 `DataSource` factory。

如需此組態檔案的詳細資訊，請參閱 Tomcat 維基的 [Using DataSources](http://wiki.apache.org/tomcat/UsingDataSources) 主題。

# 部署配方
<a name="create-custom-deploy"></a>

**重要**  
 AWS OpsWorks Stacks 此服務已於 2024 年 5 月 26 日終止，並已針對新客戶和現有客戶停用。我們強烈建議客戶盡快將其工作負載遷移至其他解決方案。如果您對遷移有任何疑問，請透過 [AWS re：Post](https://repost.aws/) 或透過 [AWS Premium Support](https://aws.amazon.com/support) 聯絡 AWS 支援 團隊。

部署配方會指派給 layer 的部署[生命週期](workingcookbook-events.md)事件。每當您部署應用程式時，它通常會在所有堆疊的執行個體上發生，但您可以選擇將事件限制為僅指定執行個體。安裝配方完成後， OpsWorks 堆疊也會在新執行個體上執行部署配方。部署配方的主要用途是從儲存庫將程式碼和相關檔案部署到應用程式伺服器 layer 的執行個體。但是，您通常也需要在其他 layer 執行部署配方。這可讓那些 layer 的執行個體進行像是更新其組態以適應新部署之應用程式等行為。當您實作部署配方時，請記得部署事件不一定表示應用程式正部署到執行個體。它可能只是一項針對應用程式正在部署到堆疊中其他執行個體的通知，讓執行個體進行任何必要的更新。配方必須要能適當地進行回應，其可能不會進行任何行為。

OpsWorks Stacks 會自動將標準應用程式類型的應用程式部署到對應的內建應用程式伺服器層。若要將應用程式部署到自訂 layer，您必須實作自訂部署配方，從儲存庫將應用程式檔案下載到執行個體上的適當位置。但是，您通常可以藉由使用內建的[部署技術指南](https://github.com/aws/opsworks-cookbooks/tree/release-chef-11.4/deploy)限制您必須撰寫的程式碼數量，處理一部分的部署。例如，若您將您的檔案存放在其中一個支援的儲存庫，內建技術指南可以處理從儲存庫將檔案下載到 layer 的執行個體的詳細資訊。

`tomcat::deploy` 技術指南用於指派給部署生命週期事件。

```
include_recipe 'deploy'

node[:deploy].each do |application, deploy|
  opsworks_deploy_dir do
    user deploy[:user]
    group deploy[:group]
    path deploy[:deploy_to]
  end

  opsworks_deploy do
    deploy_data deploy
    app application
  end
...
```

`tomcat::deploy` 配方針對部署中非應用程式限定的一部分使用內建的部署技術指南。`deploy` 配方 (為內建 `deploy::default` 配方的速記) 是一種內建的配方，可根據 `deploy` 屬性的資料處理設定使用者、群組等詳細資訊。

配方使用兩個內建 Chef 定義 (`opsworks_deploy_dir` 和 `opworks_deploy`) 安裝應用程式。

`opsworks_deploy_dir` 定義會根據應用程式部署 JSON 的資料設定目錄結構。定義基本上是封裝資源定義的便利方式，位於技術指南的 `definitions` 目錄中。配方可像資源一樣使用定義，但定義本身不具有關聯的提供者，只有包含在定義內的資源。您可以在配方中定義變數，該變數會傳遞到基礎資源定義。`tomcat::deploy` 配方會根據部署 JSON 的資料設定 `user`、`group` 和 `path` 變數。他們會傳遞到定義的 [directory 資源](https://docs.chef.io/chef/resources.html#directory)，該資源會管理目錄。

**注意**  
您部署應用程式的使用者和群組由 `[:opsworks][:deploy_user][:user]` 和 `[:opsworks][:deploy_user][:group]` 屬性決定，這兩個屬性的定義位於[內建部署技術指南的 `deploy.rb` 屬性檔案](https://github.com/aws/opsworks-cookbooks/blob/release-chef-11.4/deploy/attributes/deploy.rb)中。`[:opsworks][:deploy_user][:user]` 的預設值為 `deploy`。`[:opsworks][:deploy_user][:group]` 的預設值視執行個體的作業系統而定。  
若是 Ubuntu 執行個體，預設群組為 `www-data`。
對於使用 Nginx 和 Unicorn 的 Rails App Server layer 成員的 Amazon Linux 執行個體，預設群組為 `nginx`。
若是其他所有 Amazon Linux 執行個體，預設群組為 `apache`。
您可以透過使用自訂 JSON 或自訂屬性檔案覆寫適當的屬性，來變更設定。如需詳細資訊，請參閱[覆寫屬性](workingcookbook-attributes.md)。

其他定義 (`opsworks_deploy`) 會根據 `deploy` 屬性的資料，處理檢查來自儲存庫的應用程式程式碼和相關檔案，以及將他們部署到執行個體的詳細資訊。您可以針對任何應用程式類型使用此定義。部署詳細資訊 (例如目錄名稱) 會在主控台中或透過 API 指定，並置放於 `deploy` 屬性中。但是，`opsworks_deploy` 僅適用於四種[支援的儲存庫類型](workingcookbook-installingcustom-repo.md)：Git、Subversion、S3 和 HTTP。若您希望使用不同的儲存庫類型，您必須自行實作程式碼。

您會在 Tomcat `webapps` 目錄中安裝應用程式的檔案。典型的做法是將檔案直接複製到 `webapps`。不過， OpsWorks Stacks 部署的設計可在執行個體上保留最多五個版本的應用程式，因此您可以視需要轉返至較早的版本。 OpsWorks Stacks 因此會執行下列動作：

1. 將應用程式部署到名稱包含時間戳記的相異目錄，例如 `/srv/www/my_1st_jsp/releases/20130731141527`。

1. 建立連結到此唯一目錄，名為 `current` 的 symlink，例如 `/srv/www/my_1st_jsp/current`。

1. 若尚未存在，請從 `webapps` 目錄建立連結到步驟 2 中建立之 `current` symlink 的 symlink。

若您需要轉返至較早的版本，請修改 `current` symlink 指向包含適當時間戳記的相異目錄 (例如，變更 `/srv/www/my_1st_jsp/current` 的連結目標)。

`tomcat::deploy` 中間的區段會設定 symlink。

```
  ...
  current_dir = ::File.join(deploy[:deploy_to], 'current')
  webapp_dir = ::File.join(node['tomcat']['webapps_base_dir'], deploy[:document_root].blank? ? application : deploy[:document_root])

  # opsworks_deploy creates some stub dirs, which are not needed for typical webapps
  ruby_block "remove unnecessary directory entries in #{current_dir}" do
    block do
      node['tomcat']['webapps_dir_entries_to_delete'].each do |dir_entry|
        ::FileUtils.rm_rf(::File.join(current_dir, dir_entry), :secure => true)
      end
    end
  end

  link webapp_dir do
    to current_dir
    action :create
  end
  ...
```

配方首先會建立兩個變數 (`current_dir` 和 `webapp_dir`) 分別代表 `current` 和 `webapp`。它接著會使用 `link` 資源將 `webapp_dir` 連結到 `current_dir`。Stacks OpsWorks `deploy::default`配方會建立此範例不需要的一些 stub 目錄，因此摘錄的中間部分會將其移除。

`tomcat::deploy` 的最終部分會重新啟動 Tomcat 服務 (若必要的話)。

```
  ...
  include_recipe 'tomcat::service'

  execute 'trigger tomcat service restart' do
    command '/bin/true'
    not_if { node['tomcat']['auto_deploy'].to_s == 'true' }
    notifies :restart, resources(:service => 'tomcat')
  end
end

include_recipe 'tomcat::context'
```

配方首先會執行 `tomcat::service`，確保已為此 Chef 執行定義服務。它接著會使用 [execute 資源](https://docs.chef.io/chef/resources.html#execute)通知服務重新啟動，但只有在 `['tomcat']['auto_deploy']` 設為 `'true'` 時才會這麼做。否則，Tomcat 會接聽其 `webapps` 目錄中的變更，使明確重新啟動 Tomcat 服務為非必要事項。

**注意**  
`execute` 資源不會執行任何實際操作。`/bin/true` 僅是一個 dummy shell 指令碼，只會傳回成功代碼。在此使用它的目的只是為了方便產生重新啟動通知。如先前所述，使用通知可確保服務不會太頻繁的重新啟動。

最後，`tomcat::deploy` 會執行 `tomcat::context`，更新 web 應用程式內容組態檔案 (若您有變更後端資料庫的話)。

# 建立堆疊和執行應用程式
<a name="create-custom-stack"></a>

**重要**  
 AWS OpsWorks Stacks 此服務已於 2024 年 5 月 26 日終止，並已針對新客戶和現有客戶停用。我們強烈建議客戶盡快將其工作負載遷移至其他解決方案。如果您對遷移有任何疑問，請透過 [AWS re：Post](https://repost.aws/) 或透過 [AWS Premium Support](https://aws.amazon.com/support) 聯絡 AWS 支援 團隊。

本節說明如何使用 Tomcat 技術指南實作基本堆疊設定，執行名為 SimpleJSP 的簡易 Java 伺服器頁面 (JSP) 應用程式。堆疊包含名為 TomCustom 的 Tomcat 型自訂層和 MySQL 層。SimpleJSP 會部署到 TomCustom，並顯示 MySQL 資料庫中的一些資訊。如果您尚未熟悉如何使用 OpsWorks Stacks 的基本概念，您應該先閱讀 [Chef 11 Linux 堆疊入門](gettingstarted.md)。

## SimpleJSP 應用程式
<a name="create-custom-stack-jsp"></a>

SimpleJSP 應用程式會示範如何設定資料庫連線和從堆疊的 MySQL 資料庫擷取資料的基本操作。

```
<html>
  <head>
    <title>DB Access</title>
  </head>
  <body>
    <%@ page language="java" import="java.sql.*,javax.naming.*,javax.sql.*" %>
    <%
      StringBuffer output = new StringBuffer();
      DataSource ds = null;
      Connection con = null;
      Statement stmt = null;
      ResultSet rs = null;
      try {
        Context initCtx = new InitialContext();
        ds = (DataSource) initCtx.lookup("java:comp/env/jdbc/mydb");
        con = ds.getConnection();
        output.append("Databases found:<br>");
        stmt = con.createStatement();
        rs = stmt.executeQuery("show databases");
        while (rs.next()) {
          output.append(rs.getString(1));
          output.append("<br>");
        }
      }
      catch (Exception e) {
        output.append("Exception: ");
        output.append(e.getMessage());
        output.append("<br>");
      }
      finally {
        try {
          if (rs != null) {
            rs.close();
          }
          if (stmt != null) {
            stmt.close();
          }
          if (con != null) {
            con.close();
          }
        }
        catch (Exception e) {
          output.append("Exception (during close of connection): ");
          output.append(e.getMessage());
          output.append("<br>");
        }
      }
    %>
    <%= output.toString() %>
  </body>
</html>
```

SimpleJSP 使用 `DataSource` 物件與 MySQL 資料庫通訊。Tomcat 使用 [Web 應用程式內容組態檔案](create-custom-configure.md#create-custom-configure-context)中的資料建立和初始化 `DataSource` 物件，並將其繫結到邏輯名稱。它接著會使用 Java 命名及目錄界面 (JNDI) 命名服務註冊邏輯名稱。為取得適當 `DataSource` 物件的執行個體，您會建立 `InitialContext` 物件，並將資源的邏輯名稱傳遞給物件的 `lookup` 方法，擷取適當的物件。SimpleJSP 範例的邏輯名稱 (`java:comp/env/jdbc/mydb`) 包含下列元件：
+ 根命名空間 (`java`)，以冒號 (:) 與名稱的剩餘部分分開。
+ 任何額外的命名空間，都會以斜線 (/) 分開。

  Tomcat 會自動將資源新增到 `comp/env` 命名空間。
+ 資源名稱，定義於 web 應用程式內容組態檔案中，並以斜線與命名空間分隔。

  此範例的資源名稱為 `jdbc/mydb`。

為建立資料庫的連線，SimpleJSP 會執行下列作業：

1. 呼叫 `DataSource` 物件的 `getConnection` 方法，傳回 `Connection` 物件。

1. 呼叫 `Connection` 物件的 `createStatement` 方法，建立 `Statement` 物件，您會使用此物件與資料庫通訊。

1. 透過呼叫適當的 `Statement` 方法與資料庫通訊。

   SimpleJSP 會呼叫 `executeQuery` 執行 SHOW DATABASES 查詢，列出伺服器的資料庫。

`executeQuery` 方法會傳回 `ResultSet` 物件，其中包含查詢的結果。SimpleJSP 會從傳回的 `ResultSet` 物件取得資料庫名稱，然後串連它們以建立輸出字串。最後，範例會關閉 `ResultSet`、`Statement` 和 `Connection` 物件。如需 JSP 和 JDBC 的詳細資訊，請分別參考 [JavaServer Pages Technology](http://docs.oracle.com/javaee/5/tutorial/doc/bnagx.html) 和 [JDBC Basics](http://docs.oracle.com/javase/tutorial/jdbc/basics/)。

若要搭配堆疊使用 SimpleJSP，您必須將其置放在儲存庫中。您可以使用任何支援的儲存庫，但若要搭配下列章節中討論的範例堆疊使用 SimpleJSP，您必須將其置放在公有 S3 封存中。如需如何使用其他標準儲存庫的資訊，請參閱[技術指南儲存庫](workingcookbook-installingcustom-repo.md)。

**將 SimpleJSP 置放在 S3 封存儲存庫中**

1. 將範例程式碼複製到名為 `simplejsp.jsp` 的檔案，然後將檔案置放在名為 `simplejsp` 的目錄中。

1. 建立 `simplejsp` 目錄的 `.zip` 存檔。

1. 建立公有 Amazon S3 儲存貯體、上傳至`simplejsp.zip`儲存貯體，並將檔案設為公有。

   如需如何執行此任務的說明，請參閱 [Amazon Simple Storage Service 入門](https://docs.aws.amazon.com/AmazonS3/latest/gsg/GetStartedWithS3.html)。

## 建立堆疊
<a name="create-custom-stack-stack"></a>

若要執行 SimpleJSP，您需要具有下列 layer 的堆疊。
+ 支援後端 MySQL 資料庫的 MySQL layer。
+ 使用 Tomcat 技術指南支援 Tomcat 伺服器執行個體的自訂 layer。

**建立堆疊**

1. 在 OpsWorks Stacks 儀表板上，按一下**新增堆疊**以建立新的堆疊，然後按一下**進階 >>** 以顯示所有選項。設定堆疊如下。
   + **名稱** – 使用者定義的堆疊名稱；此範例使用 TomStack。
   + **使用自訂 Chef 技術指南** – 將切換設定為**是**，這會顯示一些額外的選項。
   + **儲存庫類型** – Git。
   + **儲存庫 URL**–`git://github.com/amazonwebservices/opsworks-example-cookbooks.git`。
   + **自訂 Chef JSON** – 新增下列 JSON：

     ```
     {
       "tomcat": {
         "base_version": 7,
         "java_opts": "-Djava.awt.headless=true -Xmx256m"
       },
       "datasources": {
         "ROOT": "jdbc/mydb"
       }
     }
     ```

   對於剩餘的選項，您可以接受預設值。

   自訂 JSON 會執行下列操作：
   + 覆寫 Tomcat 技術指南的 `['base_version']` 屬性，將 Tomcat 的版本設為 7。預設值為 6。
   + 覆寫 Tomcat 技術指南的 `['java_opts']` 屬性，指定執行個體沒有標題，並將 JVM 最大堆積大小設為 256MB。預設值不會為執行 Amazon Linux 的執行個體設定任何選項。
   + 指定 `['datasources]` 屬性值，指派 JDBC 資源名稱 (jdbc/mydb) 給 web 應用程式內容名稱 (ROOT)，如 [tomcat::context](create-custom-configure.md#create-custom-configure-context) 中所討論。

     這個最後一個屬性沒有任何預設值。您必須使用自訂 JSON 設定它。  
![\[Configuration Management interface showing Chef version options and custom JSON input field.\]](http://docs.aws.amazon.com/zh_tw/opsworks/latest/userguide/images/tom_add_stack.png)

1. 按一下 **Add a layer (新增 layer)**。針對 **Layer type (Layer 類型)**，選取 **MySQL**。然後按一下 **Add Layer (新增 Layer)**。

1. 按一下導覽窗格中的 **Instances (執行個體)**，然後按一下 **Add an instance (新增執行個體)**。按一下 **Add Instance (新增執行個體)** 接受預設值。在執行個體的列上，按一下 **start (啟動)**。

1. 返回 **Layers (Layer)** 頁面然後按一下 **\$1 Layer (\$1Layer)** 以新增 layer。針對 **Layer type (Layer 類型)**，按一下 **Custom (自訂)**。範例使用 **TomCustom** 和 **tomcustom** 分別做為 layer 的名稱和短名。  
![\[Add Layer form with Custom layer type, Name, and Short name fields for creating a customized layer.\]](http://docs.aws.amazon.com/zh_tw/opsworks/latest/userguide/images/tom_add_custom_layer.png)

1. 在 **Layers (Layer)** 頁面上，針對自訂 layer，按一下 **Recipes (配方)** 然後按一下 **Edit (編輯)**。在 **Custom Chef Recipes (自訂 Chef 配方)** 下，將 Tomcat 技術指南配方指派給 layer 的生命週期事件，如下所示：
   + 針對 **Setup (安裝)**，輸入 **tomcat::setup** 然後按一下 **\$1**。
   + 針對 **Configure (設定)**，輸入 **tomcat::configure** 然後按一下 **\$1**。
   + 針對 **Deploy (部署)**，輸入 **tomcat::deploy** 然後按一下 **\$1**。然後按一下 **Save (儲存)**。

     .  
![\[Custom Chef Recipes interface showing setup, configure, and deploy steps with options.\]](http://docs.aws.amazon.com/zh_tw/opsworks/latest/userguide/images/tom_events.png)

1. 按一下導覽窗格中的 **Apps (應用程式)**，然後按一下 **Add an app (新增應用程式)**。指定下列選項，然後按一下 **Add App (新增應用程式)**：
   + **名稱** – 應用程式的名稱；範例使用 SimpleJSP，而 Stacks OpsWorks 產生的簡短名稱將是 simplejsp。
   + **應用程式類型** – 將此選項設定為**其他**。

     OpsWorks Stacks 會自動將標準應用程式類型部署至相關聯的伺服器執行個體。若您將 **App type (應用程式類型)** 設為「其他」， OpsWorks Stacks 便只會執行部署配方，並讓它們處理部署。
   + **文件根** – 將此選項設定為 **ROOT**。

     **Document root (文件根)** 的值指定內容名稱。
   + **儲存庫類型** – 將此選項設定為 **S3 Archive**。
   + **儲存庫 URL** – 將此設定為您先前建立的應用程式 Amazon S3 URL。

   其他選項請使用預設設定。  
![\[Application settings form with fields for name, app type, document root, and source details.\]](http://docs.aws.amazon.com/zh_tw/opsworks/latest/userguide/images/tom_app.png)

1. 使用**執行個體**頁面將執行個體新增至 TomCustom 層並啟動。安裝配方完成後， OpsWorks Stacks 會自動在新執行個體上執行部署配方，因此啟動執行個體也會部署 SimpleJSP。

1. 當 TomCustom 執行個體上線時，在 **Instances (執行個體)** 頁面上按一下執行個體名稱以查看詳細資訊。複製公有 IP 地址。然後建構 URL 如下：http://*publicIP*/tc/*appname.jsp*。例如，此 URL 看起來會像這樣：**http://50.218.191.172/tc/simplejsp.jsp**。
**注意**  
轉遞請求至 Tomcat 的 Apache URL 已設為預設 `['tomcat']['apache_tomcat_bind_path']` 屬性，`/tc/`。SimpleJSP 文件根已設為 `ROOT`，為解析至 `/` 的特殊值。URL 因此為 ".../tc/simplejsp.jsp"。

1. 將先前步驟中的 URL 於您的瀏覽器內貼上。請查看下列事項：

   ```
   Databases found:
   information_schema
   simplejsp
   test
   ```
**注意**  
如果您的堆疊有 MySQL 執行個體， OpsWorks Stacks 會自動為每個應用程式建立資料庫，以應用程式的簡短名稱命名。

# 堆疊組態及部署屬性
<a name="workingcookbook-json"></a>

**重要**  
 AWS OpsWorks Stacks 此服務已於 2024 年 5 月 26 日終止，並已針對新客戶和現有客戶停用。我們強烈建議客戶盡快將其工作負載遷移至其他解決方案。如果您對遷移有任何疑問，請透過 [AWS re：Post](https://repost.aws/) 或透過 [AWS Premium Support](https://aws.amazon.com/support) 聯絡 AWS 支援 團隊。

當 OpsWorks Stacks 在執行個體上執行命令時，例如，回應部署生命週期事件的部署命令，它會將一組屬性新增至描述堆疊目前組態的執行個體節點物件。對於部署事件和[執行配方堆疊命令](workingstacks-commands.md)， OpsWorks Stacks 會安裝部署屬性，以提供一些額外的部署資訊。如需節點物件的詳細資訊，請參閱[覆寫屬性](workingcookbook-attributes.md)。如需常用堆疊組態及部署屬性的清單 (包含完整的節點名稱)，請參閱[堆疊組態及部署屬性：Linux](attributes-json-linux.md) 和[內建技術指南屬性](attributes-recipes.md)。

**注意**  
在 Linux 堆疊上，您可以透過使用代理程式 CLI 的 [get\$1json 命令](agent-json.md)取得這些屬性的完整清單，其格式為 JSON 物件。

下列各節顯示與設定事件關聯的屬性，以及一個簡易堆疊的部署事件，由下列項目組成：
+ 具有兩個執行個體的 PHP App Server layer
+ 具有一個執行個體的 HAProxy layer

這些範例來自其中一個 PHP App Server 執行個體 **php-app1**。為了方便，屬性已格式化為 JSON 物件。物件的結構會映射到屬性的完整名稱。例如，`node[:opsworks][:ruby_version]` 屬性會在 JSON 表示中以下列方式呈現。

```
{
  "opsworks": {
    ...
    "ruby_version": "1.8.7",
    ...
  }
}
```

**Topics**
+ [設定屬性](#workingcookbook-json-configure)
+ [部署屬性](#workingcookbook-json-deploy)

## 設定屬性
<a name="workingcookbook-json-configure"></a>

下列 JSON 物件顯示設定事件的屬性，其會在執行個體上線或離線時，在堆疊中的每個執行個體上發生，屬性包含內建堆疊組態屬性和任何在事件之前為堆疊定義的[自訂 JSON 屬性](workingstacks-json.md) (在此範例中則無)。它已針對長度進行編輯。如需各種屬性的詳細描述，請參閱[堆疊組態及部署屬性：Linux](attributes-json-linux.md) 和[內建技術指南屬性](attributes-recipes.md)。

```
{
  "opsworks": {
    "layers": {
      "php-app": {
        "id": "4a2a56c8-f909-4b39-81f8-556536d20648",
        "instances": {
          "php-app2": {
            "elastic_ip": null,
            "region": "us-west-2",
            "booted_at": "2013-02-26T20:41:10+00:00",
            "ip": "192.0.2.0",
            "aws_instance_id": "i-34037f06",
            "availability_zone": "us-west-2a",
            "instance_type": "c1.medium",
            "private_dns_name": "ip-10-252-0-203.us-west-2.compute.internal",
            "private_ip": "10.252.0.203",
            "created_at": "2013-02-26T20:39:39+00:00",
            "status": "online",
            "backends": 8,
            "public_dns_name": "ec2-192-0-2-0.us-west-2.compute.amazonaws.com"
          },
          "php-app1": {
            ...
          }
        },
        "name": "PHP Application Server"
      },
      "lb": {
        "id": "15c86142-d836-4191-860f-f4d310440f14",
        "instances": {
          "lb1": {
           ...
          }
        },
        "name": "Load Balancer"
      }
    },
    "agent_version": "104",
    "applications": [

    ],
    "stack": {
      "name": "MyStack"
    },
    "ruby_version": "1.8.7",
    "sent_at": 1361911623,
    "ruby_stack": "ruby_enterprise",
    "instance": {
      "layers": [
        "php-app"
      ],
      "region": "us-west-2",
      "ip": "192.0.2.0",
      "id": "45ef378d-b87c-42be-a1b9-b67c48edafd4",
      "aws_instance_id": "i-32037f00",
      "availability_zone": "us-west-2a",
      "private_dns_name": "ip-10-252-84-253.us-west-2.compute.internal",
      "instance_type": "c1.medium",
      "hostname": "php-app1",
      "private_ip": "10.252.84.253",
      "backends": 8,
      "architecture": "i386",
      "public_dns_name": "ec2-192-0-2-0.us-west-2.compute.amazonaws.com"
    },
    "activity": "configure",
    "rails_stack": {
      "name": null
    },
    "deployment": null,
    "valid_client_activities": [
      "reboot",
      "stop",
      "setup",
      "configure",
      "update_dependencies",
      "install_dependencies",
      "update_custom_cookbooks",
      "execute_recipes"
    ]
  },
  "opsworks_custom_cookbooks": {
    "recipes": [

    ],
    "enabled": false
  },
  "recipes": [
    "opsworks_custom_cookbooks::load",
    "opsworks_ganglia::configure-client",
    "ssh_users",
    "agent_version",
    "mod_php5_apache2::php",
    "php::configure",
    "opsworks_stack_state_sync",
    "opsworks_custom_cookbooks::execute",
    "test_suite",
    "opsworks_cleanup"
  ],
  "opsworks_rubygems": {
    "version": "1.8.24"
  },
  "ssh_users": {
  },
  "opsworks_bundler": {
    "manage_package": null,
    "version": "1.0.10"
  },
  "deploy": {
  }
}
```

大多數的資訊都位於 `opsworks` 屬性下方，通常其名為命名空間。以下清單說明關鍵屬性：
+ `layers` 屬性 – 一組屬性，每個屬性都會描述其中一個堆疊層的組態。

  這些 layer 會根據其短名識別，此範例中為 `php-app` 和 `lb`。如需其他 layer 之短名的詳細資訊，請參閱 [OpsWorks Stacks Layer 參考](layers.md)。
+ `instances` 屬性 – 每個 layer 都有 `instances`元素，其中包含每個 layer 線上執行個體的屬性，以執行個體的簡短名稱命名。

  PHP App Server layer 有兩個執行個體 `php-app1`和 `php-app2`。HAProxy layer 有一個執行個體 `lb1`。
**注意**  
`instances` 元素只包含那些在建立特定堆疊及部署屬性時處於線上狀態的執行個體。
+ 執行個體屬性 – 每個執行個體屬性都包含一組屬性來描述執行個體，例如執行個體的私有 IP 地址和私有 DNS 名稱。為了簡化，此範例只顯示 `php-app2` 屬性的詳細資訊。其他的也包含相似的資訊。
+ `applications` – 部署的應用程式清單，未用於此範例。
+ `stack` – 堆疊名稱；在此範例中`MyStack`為 。
+ `instance` – 已安裝這些屬性的執行個體；在此範例中`php-app1`為 。配方可使用此屬性取得執行中執行個體的資訊，例如執行個體的公有 IP 地址。
+ `activity` – 產生屬性的活動；在此範例中為設定事件。
+ `rails_stack` – 包含 Rails App Server layer 之堆疊的 Rails 堆疊。
+ `deployment` – 這些屬性是否與部署相關聯。此範例中已設為 `null`，因為他們是與設定事件關聯。
+ `valid_client_activities` – 有效用戶端活動的清單。

`opsworks` 屬性其後跟隨幾個其他最上層屬性，包含下列項目：
+ `opsworks_custom_cookbooks` – 是否啟用自訂技術指南。若為是，則屬性會包含自訂配方的清單。
+ `recipes` – 此活動執行的配方。
+ `opsworks_rubygems` – 執行個體的 RubyGems 版本。
+ `ssh_users` – SSH 使用者清單；此範例中沒有。
+ `opsworks_bundler` – 綁定器版本及其是否已啟用。
+ `deploy` – 部署活動的相關資訊；此範例中沒有。

## 部署屬性
<a name="workingcookbook-json-deploy"></a>

部署事件或[執行配方堆疊命令](workingstacks-commands.md)的屬性由內建的堆疊組態及部署屬性，以及任何自訂堆疊或部署屬性組成 (此範例中則無)。下列 JSON 物件顯示與部署事件關聯之 **php-app1** 的屬性。該事件會將 SimplePHP 應用程式部署到堆疊的 PHP 執行個體。物件的大部分都是由與先前章節中說明的設定事件屬性相似的堆疊組態屬性組成，因此範例主要會聚焦在部署限定的屬性。如需各種屬性的詳細描述，請參閱[堆疊組態及部署屬性：Linux](attributes-json-linux.md) 和[內建技術指南屬性](attributes-recipes.md)。

```
{
   ...
  "opsworks": {
    ...
    "activity": "deploy",
    "applications": [
      {
        "slug_name": "simplephp",
        "name": "SimplePHP",
        "application_type": "php"
      }
    ],
    "deployment": "5e6242d7-8111-40ee-bddb-00de064ab18f",
    ...
  },
  ...
{
  "ssh_users": {
  },
  "deploy": {
    "simplephpapp": {
      "application": "simplephpapp",
      "application_type": "php",
      "environment_variables": {
        "USER_ID": "168424",
        "USER_KEY": "somepassword"
      },
      "auto_bundle_on_deploy": true,
      "deploy_to": "/srv/www/simplephpapp",
      "deploying_user": "arn:aws:iam::123456789012:user/guysm",
      "document_root": null,
      "domains": [
        "simplephpapp"
      ],
      "migrate": false,
      "mounted_at": null,
      "rails_env": null,
      "restart_command": "echo 'restarting app'",
      "sleep_before_restart": 0,
      "ssl_support": false,
      "ssl_certificate": null,
      "ssl_certificate_key": null,
      "ssl_certificate_ca": null,
      "scm": {
        "scm_type": "git",
        "repository": "git://github.com/amazonwebservices/opsworks-demo-php-simple-app.git",
        "revision": "version1",
        "ssh_key": null,
        "user": null,
        "password": null
      },
      "symlink_before_migrate": {
        "config/opsworks.php": "opsworks.php"
      },
      "symlinks": {
      },
      "database": {
      },
      "memcached": {
        "host": null,
        "port": 11211
      },
      "stack": {
        "needs_reload": false
      }
    }
  },
}
```

`opsworks` 屬性大致上與先前章節中的範例相同。以下區段是與部署最為相關的部分：
+ `activity` – 與這些屬性相關聯的事件；此範例中的部署事件。
+ `applications` – 包含每個應用程式一組屬性，提供應用程式的名稱、slug 名稱和類型。

  slug 名稱是應用程式的簡短名稱，由 OpsWorks Stacks 從應用程式名稱產生。SimplePHP 的動態資料欄位名稱為 simplephp。
+ `deployment` – 部署 ID，可唯一識別部署。

`deploy` 屬性包含正在部署之應用程式的相關資訊。例如，內建的部署配方會使用 `deploy` 屬性中的資料，來在適當的目錄中安裝檔案及建立資料庫連線檔案。`deploy` 屬性包含每個部署應用程式的一個屬性，以應用程式的短名命名。每個應用程式的屬性都包含以下屬性：
+ `environment_variables` – 包含您已為應用程式定義的任何環境變數。如需詳細資訊，請參閱[環境變數](workingapps-creating.md#workingapps-creating-environment)。
+ `domains` – 根據預設，網域是應用程式的簡短名稱，在此範例中為 simplephpapp。若您已指派自訂網域，他們也會出現在這裡。如需詳細資訊，請參閱[使用自訂網域](workingapps-domains.md)。
+ `application` – 應用程式的簡短名稱。
+ `scm` – 此元素包含從其儲存庫下載應用程式檔案所需的資訊；在此範例中為 Git 儲存庫。
+ `database` – 資料庫資訊，如果堆疊包含資料庫層。
+ `document_root` – 文件根，`null`在此範例中設定為 ，表示根為公有。
+ `ssl_certificate_ca`、`ssl_support`、 `ssl_certificate_key` – 指出應用程式是否支援 SSL。若有的話，`ssl_certificate_key` 和 `ssl_certificate_ca` 屬性會設為對應的憑證。
+ `deploy_to` – 應用程式根目錄。