

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

# AWS IoT 使用 AWS IoT 裝置用戶端在 中建立和執行任務
<a name="iot-dc-runjobs-prepare-define"></a>

本節中的程序會建立任務文件和 AWS IoT 任務資源。建立任務資源後， 會將任務文件 AWS IoT 傳送至任務代理程式將任務文件套用至裝置或用戶端的指定任務目標。

**Topics**
+ [建立和存放 IoT 任務的任務文件](#iot-dc-runjobs-prepare-define-jobdoc)
+ [AWS IoT 在一個 IoT 裝置的 中執行任務](#iot-dc-runjobs-prepare-define-job)

## 建立和存放 IoT 任務的任務文件
<a name="iot-dc-runjobs-prepare-define-jobdoc"></a>

此程序會建立簡單的任務文件，以包含在 AWS IoT 任務資源中。此任務文件會在任務目標上 顯示 "Hello world\$1"。

**若要建立和儲存任務文件：**

1. 選取要儲存任務文件的 Amazon S3 儲存貯體。如果沒有可使用的現有 Amazon S3 儲存貯體，就需要建立一個。如需如何建立 Amazon S3 儲存貯體的詳細資訊，請參閱 [Amazon S3 入門](https://docs.aws.amazon.com//AmazonS3/latest/userguide/GetStartedWithS3.html)中的主題。

1. 建立並儲存此任務的任務文件

   1. 在本機主機電腦上，開啟文字編輯器。

   1. 將此文字複製並貼入編輯器中。

      ```
      {
          "operation": "echo",
          "args": ["Hello world!"]
      }
      ```

   1. 在本機主機電腦上，將編輯器的內容儲存至名為 **hello-world-job.json** 的檔案。

   1. 請確認檔案已正確儲存。某些文字編輯器會在儲存文字檔案時自動附加 `.txt` 至檔案名稱。如果編輯器附加了 `.txt` 至檔案名稱，請更正檔案名稱後再繼續。

1. 使用 **hello-world-job.json** 路徑來取代 *path\$1to\$1file*；如果該路徑不在當前目錄中，則使用所選儲存貯體的 Amazon S3 儲存貯體路徑取代 *s3\$1bucket\$1name*，然後執行此命令將任務文件放入 Amazon S3 儲存貯體中。

   ```
   aws s3api put-object \
   --key hello-world-job.json \
   --body path_to_file/hello-world-job.json --bucket s3_bucket_name
   ```

   識別儲存在 Amazon S3 中的任務文件的任務文件 URL 是透過取代以下 URL 中 *s3\$1bucket\$1name* 和 *AWS\$1region* 來決定。記錄產生的 URL 以便稍後使用為 *job\$1document\$1path*

   ```
   https://s3_bucket_name.s3.AWS_Region.amazonaws.com/hello-world-job.json
   ```
**注意**  
AWS 安全性可防止您在 外部開啟此 URL AWS 帳戶，例如使用瀏覽器。根據預設，具有 檔案存取權 AWS IoT 的任務引擎會使用 URL。在生產環境中，您需要確保 AWS IoT 服務具有存取儲存在 Amazon S3 中任務文件的許可。

在儲存任務文件的 URL 之後，請繼續進行 [AWS IoT 在一個 IoT 裝置的 中執行任務](#iot-dc-runjobs-prepare-define-job)。

## AWS IoT 在一個 IoT 裝置的 中執行任務
<a name="iot-dc-runjobs-prepare-define-job"></a>

本節中的程序會啟動 Raspberry Pi 上的 AWS IoT Device Client，以在裝置上執行任務代理程式，以等待任務執行。它也會在 中建立任務資源 AWS IoT，將任務傳送至 IoT 裝置並在其上執行。

**注意**  
此程序只會在單一裝置上執行任務。

**若要啟動 Raspberry Pi 任務代理程式：**

1. 在本機主機電腦上連線至 Raspberry Pi 的終端機視窗中，執行此命令來啟動 AWS IoT 裝置用戶端。

   ```
   cd ~/aws-iot-device-client/build
   ./aws-iot-device-client --config-file ~/dc-configs/dc-jobs-config.json
   ```

1. 在終端機視窗中，確認 AWS IoT 裝置用戶端並顯示這些訊息

   ```
   2021-11-15T18:45:56.708Z [INFO]  {Main.cpp}: Jobs is enabled
                         .
                         .
                         .
   2021-11-15T18:45:56.708Z [INFO]  {Main.cpp}: Client base has been notified that Jobs has started
   2021-11-15T18:45:56.708Z [INFO]  {JobsFeature.cpp}: Running Jobs!
   2021-11-15T18:45:56.708Z [DEBUG] {JobsFeature.cpp}: Attempting to subscribe to startNextPendingJobExecution accepted and rejected
   2021-11-15T18:45:56.708Z [DEBUG] {JobsFeature.cpp}: Attempting to subscribe to nextJobChanged events
   2021-11-15T18:45:56.708Z [DEBUG] {JobsFeature.cpp}: Attempting to subscribe to updateJobExecutionStatusAccepted for jobId +
   2021-11-15T18:45:56.738Z [DEBUG] {JobsFeature.cpp}: Ack received for SubscribeToUpdateJobExecutionAccepted with code {0}
   2021-11-15T18:45:56.739Z [DEBUG] {JobsFeature.cpp}: Attempting to subscribe to updateJobExecutionStatusRejected for jobId +
   2021-11-15T18:45:56.753Z [DEBUG] {JobsFeature.cpp}: Ack received for SubscribeToNextJobChanged with code {0}
   2021-11-15T18:45:56.760Z [DEBUG] {JobsFeature.cpp}: Ack received for SubscribeToStartNextJobRejected with code {0}
   2021-11-15T18:45:56.776Z [DEBUG] {JobsFeature.cpp}: Ack received for SubscribeToStartNextJobAccepted with code {0}
   2021-11-15T18:45:56.776Z [DEBUG] {JobsFeature.cpp}: Ack received for SubscribeToUpdateJobExecutionRejected with code {0}
   2021-11-15T18:45:56.777Z [DEBUG] {JobsFeature.cpp}: Publishing startNextPendingJobExecutionRequest
   2021-11-15T18:45:56.785Z [DEBUG] {JobsFeature.cpp}: Ack received for StartNextPendingJobPub with code {0}
   2021-11-15T18:45:56.785Z [INFO]  {JobsFeature.cpp}: No pending jobs are scheduled, waiting for the next incoming job
   ```

1. 在終端機視窗中看到此訊息之後，請繼續執行下一個程序並建立任務資源。請注意，它可能不是清單中的最後一個項目。

   ```
   2021-11-15T18:45:56.785Z [INFO]  {JobsFeature.cpp}: No pending jobs are scheduled, waiting for the next incoming job
   ```

**建立 AWS IoT 任務資源**

1. 在本機主機電腦上：

   1. 使用來自 [建立和存放 IoT 任務的任務文件](#iot-dc-runjobs-prepare-define-jobdoc) 的任務文件 URL 來取代 *job\$1document\$1url*。

   1. 使用為裝置建立的物件資源 ARN 來取代 *thing\$1arn*，然後執行此命令。

      ```
      aws iot create-job \
      --job-id hello-world-job-1 \
      --document-source "job_document_url" \
      --targets "thing_arn" \
      --target-selection SNAPSHOT
      ```

      如果成功，命令會傳回類似以下的結果。

      ```
      {
        "jobArn": "arn:aws:iot:us-west-2:57EXAMPLE833:job/hello-world-job-1",
        "jobId": "hello-world-job-1"
      }
      ```

1. 在終端機視窗中，您應該會看到來自 AWS IoT Device Client 的輸出，如下所示。

   ```
   2021-11-15T18:02:26.688Z [INFO]  {JobsFeature.cpp}: No pending jobs are scheduled, waiting for the next incoming job
   2021-11-15T18:10:24.890Z [DEBUG] {JobsFeature.cpp}: Job ids differ
   2021-11-15T18:10:24.890Z [INFO]  {JobsFeature.cpp}: Executing job: hello-world-job-1
   2021-11-15T18:10:24.890Z [DEBUG] {JobsFeature.cpp}: Attempting to update job execution status!
   2021-11-15T18:10:24.890Z [DEBUG] {JobsFeature.cpp}: Not including stdout with the status details
   2021-11-15T18:10:24.890Z [DEBUG] {JobsFeature.cpp}: Not including stderr with the status details
   2021-11-15T18:10:24.890Z [DEBUG] {JobsFeature.cpp}: Assuming executable is in PATH
   2021-11-15T18:10:24.890Z [INFO]  {JobsFeature.cpp}: About to execute: echo Hello world!
   2021-11-15T18:10:24.890Z [DEBUG] {Retry.cpp}: Retryable function starting, it will retry until success
   2021-11-15T18:10:24.890Z [DEBUG] {JobsFeature.cpp}: Created EphermalPromise for ClientToken 3TEWba9Xj6 in the updateJobExecution promises map
   2021-11-15T18:10:24.890Z [DEBUG] {JobEngine.cpp}: Child process now running
   2021-11-15T18:10:24.890Z [DEBUG] {JobEngine.cpp}: Child process about to call execvp
   2021-11-15T18:10:24.890Z [DEBUG] {JobEngine.cpp}: Parent process now running, child PID is 16737
   2021-11-15T18:10:24.891Z [DEBUG] {16737}: Hello world!
   2021-11-15T18:10:24.891Z [DEBUG] {JobEngine.cpp}: JobEngine finished waiting for child process, returning 0
   2021-11-15T18:10:24.891Z [INFO]  {JobsFeature.cpp}: Job exited with status: 0
   2021-11-15T18:10:24.891Z [INFO]  {JobsFeature.cpp}: Job executed successfully!
   2021-11-15T18:10:24.891Z [DEBUG] {JobsFeature.cpp}: Attempting to update job execution status!
   2021-11-15T18:10:24.891Z [DEBUG] {JobsFeature.cpp}: Not including stdout with the status details
   2021-11-15T18:10:24.891Z [DEBUG] {JobsFeature.cpp}: Not including stderr with the status details
   2021-11-15T18:10:24.892Z [DEBUG] {Retry.cpp}: Retryable function starting, it will retry until success
   2021-11-15T18:10:24.892Z [DEBUG] {JobsFeature.cpp}: Created EphermalPromise for ClientToken GmQ0HTzWGg in the updateJobExecution promises map
   2021-11-15T18:10:24.905Z [DEBUG] {JobsFeature.cpp}: Ack received for PublishUpdateJobExecutionStatus with code {0}
   2021-11-15T18:10:24.905Z [DEBUG] {JobsFeature.cpp}: Removing ClientToken 3TEWba9Xj6 from the updateJobExecution promises map
   2021-11-15T18:10:24.905Z [DEBUG] {JobsFeature.cpp}: Success response after UpdateJobExecution for job hello-world-job-1
   2021-11-15T18:10:24.917Z [DEBUG] {JobsFeature.cpp}: Ack received for PublishUpdateJobExecutionStatus with code {0}
   2021-11-15T18:10:24.918Z [DEBUG] {JobsFeature.cpp}: Removing ClientToken GmQ0HTzWGg from the updateJobExecution promises map
   2021-11-15T18:10:24.918Z [DEBUG] {JobsFeature.cpp}: Success response after UpdateJobExecution for job hello-world-job-1
   2021-11-15T18:10:25.861Z [INFO]  {JobsFeature.cpp}: No pending jobs are scheduled, waiting for the next incoming job
   ```

1. 當 AWS IoT 裝置用戶端正在執行並等待任務時，您可以透過變更 `job-id`值，並從**create-job**步驟 1 重新執行 來提交另一個任務。

當您完成執行任務時，請在終端機視窗中輸入 ^C(control-C) 以停止 AWS IoT 裝置用戶端。