> ## Documentation Index
> Fetch the complete documentation index at: https://devdocs.xbox.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 在 VM 建立期間執行自訂指令碼 (預覽)

> 使用 VmStartupScript 預覽功能，在 PlayFab 多人遊戲伺服器的 VM 建立期間執行自訂指令碼，以安裝代理程式及路由記錄。

# 在 VM 建立期間執行自訂指令碼 - VmStartupScript (預覽)

## 簡介

<Info>
  此功能處於預覽階段。歡迎您立即開始使用，並提供意見反應給我們。本文結尾提供與我們聯繫的方式。請注意，預覽期間的技術支援有限。
</Info>

VmStartupScript 可讓您在 PlayFab 多人遊戲伺服器 (MPS) 所使用的虛擬機器 (VM) 上執行自訂指令碼。MPS 針對遊戲伺服器裝載進行了最佳化，讓您的遊戲能輕鬆地根據需求動態調整規模。為了在 VM 初始化期間更輕鬆地快速自訂大量伺服器，自訂指令碼可以在裝載遊戲伺服器的每部基礎 VM 上執行。它可用來完成各種工作，例如安裝自訂軟體、修改安全性設定、使用自訂服務記錄遊戲伺服器輸出和計量等。

<Note>
  這是一項進階功能，應極度謹慎地使用。執行中的指令碼會以系統管理員 (root) 權限在虛擬機器 (VM) 層級執行。如果使用不當，可能會中斷執行中遊戲伺服器的正常流程，甚至讓它們完全無法執行。終端使用者須對指令碼的內容負責。
</Note>

<iframe src="https://www.youtube.com/embed/oc-X7rHCwUU" width="100%" height="400" allowFullScreen frameBorder="0" />

## 如何使用 VmStartupScript

若要使用 VmStartupScript 功能，您必須提供自訂指令碼，以及您打算安裝的所有相關軟體 (選用)。指令碼會在虛擬機器初始化時開始執行。此作業會在每部 VM 上的遊戲伺服器啟動之前進行。指令碼成功執行完成後，MPS 服務會繼續完成遊戲伺服器的初始化，並將其交付至 **StandingBy** 狀態。若要深入了解不同的遊戲伺服器狀態，請參閱[多人遊戲伺服器的生命週期](/zh-TW/services/playfab/multiplayer/servers/multiplayer-game-server-lifecycle)。

若要在實際生產環境中使用此功能，請在開始之前參閱[建議的開發人員工作流程](#recommended-development-workflow)。

### 建立指令碼

* 針對 Linux VM 建立名為 **PF\_StartupScript.sh** 的檔案，或針對 Windows VM 建立名為 **PF\_StartupScript.ps1** 的檔案。
* 在檔案中新增設定/執行命令。如有需要，以下是一些您可以在指令碼中使用的常用[環境變數](#environment-variables)。某些動作不受支援，或會導致 VM 無法成功啟動，進而產生不必要的費用。如需詳細資料，請參閱[不支援的項目](#what-is-not-supported)一節。

如需指令碼範例，請參閱 [VmStartupScriptGallery](https://github.com/PlayFab/VmStartupScriptGallery)。

### 建立並上傳壓縮檔

1. 將指令碼打算使用或呼叫的所有相關軟體收集到一個資料夾中。如果您的指令碼會安裝第三方軟體，指令碼可以在執行期間下載它，或將其與指令碼一起打包在壓縮檔中。如果您沒有要安裝任何內容，請略過此步驟。
2. 使用您在先前一節中建立的指令碼 (.sh 或 .ps1)，以及 (如有需要) 您在先前步驟中收集的軟體，建立壓縮檔 (.zip)。指令碼檔案應位於壓縮檔的根目錄，而不是在目錄內。此外，如果您的指令碼檔案未命名為 **PF\_StartupScript.sh** (Linux) 或 **PF\_StartupScript.ps1** (Windows)，它將不會被執行，遊戲伺服器也將無法啟動。
3. 使用下列其中一種方法上傳壓縮檔：

* 使用 [PlayFab Game Manager](/zh-TW/services/playfab/multiplayer/servers/deploy-using-game-manager#assets-for-builds)
* 在 [GetAssetUploadUrl API](https://learn.microsoft.com/en-us/rest/api/playfab/multiplayer/multiplayer-server/get-asset-upload-url) 呼叫所傳回的 URL 上，發出標頭為 \{"x-ms-blob-type": "BlockBlob"} 的 PUT 要求。
* 使用 [PowerShell Cmdlet](/zh-TW/services/playfab/multiplayer/servers/deploy-using-powershell-api#upload-an-asset)。

<Note>
  我們建議將指令碼所需的所有二進位檔和資產都包含在壓縮檔中，因為這樣可以加快執行速度，並縮短 MPS 交付遊戲伺服器的時間。請務必包含遊戲伺服器將執行之相關平台的資產。例如，如果您使用 Linux 伺服器，應包含 "amd64" Debian/Ubuntu 套件。
</Note>

### 將自訂指令碼套用至新組建

上傳 .zip 檔案後，設定 **VmStartupScriptAssetReference** 屬性，然後使用 MPS API 建立新組建。如需指示，請參閱[如何使用 MPS API 建立組建](/zh-TW/services/playfab/multiplayer/servers/deploy-using-powershell-api)。

* 新增 **VmStartupScriptConfiguration.VmStartupScriptAssetReference** 屬性，其中包含對已上傳資產檔案的參考。此屬性是所有 "CreateBuild" 相關 API 的一部分，例如 [CreateBuildWithCustomContainer](https://learn.microsoft.com/en-us/rest/api/playfab/multiplayer/multiplayer-server/create-build-with-custom-container)、[CreateBuildWithManagedContainer](https://learn.microsoft.com/en-us/rest/api/playfab/multiplayer/multiplayer-server/create-build-with-managed-container) 和 [CreateBuildWithProcessBasedServer](https://learn.microsoft.com/en-us/rest/api/playfab/multiplayer/multiplayer-server/create-build-with-process-based-server)。
* 為 **VmStartupScriptAssetReference.FileName** 屬性新增有效的值。此值必須與資產檔案的名稱相同，例如 **vmstartupscriptassets.zip**。
* **VmStartupScriptAssetReference.MountPath** 屬性必須為空白，因為 VmStartupScript 功能不支援此屬性。

<Note>
  如果您為 **MountPath** 屬性設定了值，建立組建作業將會失敗。
</Note>

下列程式碼範例會使用 Linux 容器建立組建，然後使用 **vmstartupscriptassets.zip** 中的指令碼自訂 VM：

```csharp theme={null}
var request = new CreateBuildWithCustomContainerRequest()
{ 
    ContainerImageReference = new ContainerImageReference()
    {
         ImageName= "testimagename",
         Tag= "0.1"
    },
    ContainerFlavor = ContainerFlavor.CustomLinux,
    BuildName = "testbuildwithvmstartupscript",
    VmSize = AzureVmSize.Standard_D2as_v4,
    MultiplayerServerCountPerVm = 3,
    Ports= new List<Port>
    {
        new Port()
        {
            Name= "port",
            Num= 123,
            Protocol = ProtocolType.TCP   
        }
    },
    RegionConfigurations = new List<BuildRegionParams> { new BuildRegionParams()
    {
        Region = "EastUs",
        StandbyServers = 3,
        MaxServers = 6

    } 
    },
    VmStartupScriptConfiguration = new VmStartupScriptParams()
    {
        VmStartupScriptAssetReference = new AssetReferenceParams()
        {
            FileName = "vmstartupscriptassets.zip"
        }
    }
};
var result = await PlayFabMultiplayerAPI.CreateBuildWithCustomContainerAsync(request);
```

VmStartupScript 會在 VM 的 "Propping" 階段執行，且必須成功終止，遊戲伺服器才能啟動。如果失敗 (結束代碼不是 0)，VM 將不會轉換為 "Running" 狀態，您需要透過 RDP/SSH 連線至 VM 進行偵錯。若要深入了解，請參閱[建議的開發人員工作流程](#recommended-development-workflow)。VM 會持續重試執行 VmStartupScript。

## 特殊考量

### 在 Linux 上，我需要將 PF\_StartupScript.sh 檔案標示為可執行嗎？

在 MPS 執行指令碼檔案之前，它會將檔案標示為可執行，然後將所有 Windows 行尾 ("\r\n") 轉換為 Linux 行尾 ("\n")。因此，您不需要擔心這兩件事。

<a id="environment-variables" />

### 環境變數

以下是您可以在啟動指令碼中使用的環境變數。

| 名稱 | 描述 |
| - | - |
| PF\_TITLE\_ID | PlayFab 遊戲識別碼 |
| PF\_BUILD\_ID | PlayFab MPS 組建識別碼 |
| PF\_VM\_ID | MPS 虛擬機器識別碼 |
| PF\_REGION | 裝載 VM 的 Azure 區域 |
| PF\_PUBLIC\_IPV4\_ADDRESS | VM 的公用 IP 位址 |
| PF\_FQDN | 對應至 VM 公用 IP 的完整網域名稱 |
| PF\_SHARED\_CONTENT\_FOLDER\_VM | 包含 VM 全域共用內容的資料夾 |

<a id="what-is-not-supported" />

### 不支援的項目

您不應從指令碼中執行這些動作，因為極有可能會中斷 VM 和遊戲伺服器的生命週期：

* 不要在啟動指令碼執行期間封鎖。指令碼必須成功結束，才能建立遊戲伺服器。如果您需要在背景中執行某些內容，可以在 Linux 上將其安裝為 systemd 服務，或安裝為 Windows 服務。
* 不要使用從 30000 開始的連接埠，因為它們用於遊戲伺服器；也不要使用連接埠 56001，因為它由 VmAgent 處理序 (MPS 遊戲伺服器協調器可執行檔) 使用。
* 不要修改 D: (Windows) 或 /mnt (Linux) 路徑上的任何檔案，因為這些檔案是 VmAgent 運作所必需的 (包含可編輯內容的資料夾除外，例如 `PF_SHARED_CONTENT_FOLDER_VM`)。
* 您不應在 VmStartupScript 或其所啟動的應用程式中使用 [GSDK](https://github.com/PlayFab/gsdk)。GSDK 只應從遊戲伺服器使用。
* 您不應手動重新啟動虛擬機器，因為此作業會在與 MPS 控制平面的通訊中造成問題。

## 連接埠

當您使用 VmStartupScript 功能時，可以要求在每部 VM 上公開一些連接埠。這些連接埠可供指令碼所啟動的任何程式使用，且與 MPS 為遊戲伺服器開啟的連接埠不同。

### 使用方式

您最多可以為每部 VM 要求五個連接埠。對於每個連接埠，您必須指定通訊協定 (TCP 或 UDP) 和名稱。以下是如何要求兩個連接埠的範例：

```csharp theme={null}
VmStartupScriptConfiguration = new VmStartupScriptParams()
{
    VmStartupScriptAssetReference = new AssetReferenceParams()
    {
        FileName = "vmstartupscriptassets.zip"
    },
    PortRequests = new List<VmStartupScriptPortRequest>()
        {
            new VmStartupScriptPortRequest()
            {
                Name = "port0",
                Protocol = ProtocolType.TCP
            },
            new VmStartupScriptPortRequest()
            {
                Name = "port1",
                Protocol = ProtocolType.UDP
            }
        }
}
```

如果您要求了任何連接埠，下列環境變數可供您的指令碼使用，以協助您取得連接埠的相關資訊：

| 名稱 | 描述 |
| - | - |
| PF\_STARTUP\_SCRIPT\_PORT\_COUNT | VmStartupScript 連接埠的數目 |
| PF\_STARTUP\_SCRIPT\_PORT\_NAME\_(index) | 連接埠的名稱，如要求中所述 |
| PF\_STARTUP\_SCRIPT\_PORT\_PROTOCOL\_(index) | 連接埠的通訊協定，如要求中所述 |
| PF\_STARTUP\_SCRIPT\_PORT\_INTERNAL\_(index) | 您的程式應在 VM 中繫結的連接埠 |
| PF\_STARTUP\_SCRIPT\_PORT\_EXTERNAL\_(index) | 在外部端點中開啟的連接埠。外部用戶端應使用此連接埠，連線至繫結到 INTERNAL 連接埠的程式 |

例如，對於上述範例指令碼中要求的兩個連接埠，您應該會在 VmStartupScript 中找到下列環境變數：

```bash theme={null}
PF_STARTUP_SCRIPT_PORT_COUNT

PF_STARTUP_SCRIPT_PORT_INTERNAL_0
PF_STARTUP_SCRIPT_PORT_EXTERNAL_0
PF_STARTUP_SCRIPT_PORT_NAME_0
PF_STARTUP_SCRIPT_PORT_PROTOCOL_0

PF_STARTUP_SCRIPT_PORT_INTERNAL_1
PF_STARTUP_SCRIPT_PORT_EXTERNAL_1
PF_STARTUP_SCRIPT_PORT_NAME_1
PF_STARTUP_SCRIPT_PORT_PROTOCOL_1
```

<Info>
  與我們為遊戲伺服器開啟的連接埠類似，由您負責驗證連線至您連接埠的用戶端。MPS 不會為這些連接埠提供任何驗證機制。
</Info>

<Note>
  客戶會發現所配置的連接埠從 20000 號開始。不過，我們建議您不要在指令碼中以硬式編碼方式撰寫此值，因為它未來可能會變更，請一律使用環境變數取得正確的連接埠資訊。
</Note>

## 開發/偵錯

使用 VmStartupScript 功能之前，建議您查看我們 GitHub 上開放原始碼存放庫 ([VmStartupScriptGallery](https://github.com/PlayFab/VmStartupScriptGallery)) 中的這些範例指令碼。歡迎貢獻！

<a id="recommended-development-workflow" />

### 建議的開發工作流程

一開始，您應該建立具有單一 VM 的測試組建。此 VM 的規格應與您打算部署生產組建的 VM 相似。部署此單一 VM 後，您可以透過 RDP/SSH 連線、複製必要的檔案，並嘗試編輯/執行指令碼，直到成功為止。

此 VM 啟動並執行，且您確認指令碼的行為符合預期後，就可以將指令碼和資產放入 .zip 檔案中。之後，您可以上傳它並嘗試用它建立組建。請再次嘗試建立單一 VM 組建以節省成本，並在確定指令碼可運作後再擴充規模。

如果您在執行指令碼時遇到問題，可以透過 RDP/SSH 登入 VM 進行偵錯，並分別檢查 **PF\_StartupScriptStdOut.txt** 和 **PF\_StartupScriptStdErr.txt** 檔案，以查看指令碼的標準輸出和標準錯誤串流。這些檔案位於 Windows 的 D: 磁碟機或 Linux 的 /mnt 上。

指令碼應具有等冪性，因為它有可能被執行多次。例如，如果指令碼嘗試下載外部資源，但因網路問題而失敗，MPS 會重試整個指令碼的執行。

## 支援

MPS 服務會執行您 VmStartupScript 中的任何內容。不過，小組不會為作為指令碼一部分所安裝/執行的個別動作和可執行檔提供支援。

在預覽期間，請使用 [PlayFab 社群論壇](https://community.playfab.com/)和 [Discord](https://aka.ms/msftgamedevdiscord) 取得支援並提供意見反應。如果您對 VmStartupScriptGallery 存放庫中的任何指令碼有問題，或想要要求新的指令碼，請在 GitHub 上[提出問題](https://github.com/PlayFab/VmStartupScriptGallery/issues)。


## Related topics

- [管理秘密 (預覽)](/zh-TW/services/playfab/multiplayer/servers/manage-secrets.md)
- [指令碼撰寫工具](/zh-TW/tools/tools-console/wdp/script-authoring-tool.md)
- [檢視與操作主機的前面板 (wdpanel.exe)](/zh-TW/tools/tools-console/console_commandlinetools/wdpanel.md)
- [使用 GDKX 建置並執行你的第一個主機遊戲](/zh-TW/home/build-first-title/first-console-title-walkthrough.md)
- [建立和部署 Linux 組建](/zh-TW/services/playfab/multiplayer/servers/deploying-linux-based-builds.md)
