Bash Cloudformation 中的脚本

Bash script inside Cloudformation

我正在尝试使用 AWS CloudFormation 部署 Sagemaker 生命周期。
生命周期正在将 ipynb notebookss3 存储桶导入到 Sagemaker notebook 实例。
存储桶名称在参数中指定,我想在生命周期的 bash 脚本内的 !Sub 函数中使用它。 问题是 CF 首先在模板上运行并尝试完成自己的功能(如 !Sub),然后脚本作为 bash 脚本上传到生命周期。

这是我的代码:

LifecycleConfig:
  Type: AWS::SageMaker::NotebookInstanceLifecycleConfig
  Properties: 
   NotebookInstanceLifecycleConfigName: !Sub
   - ${NotebookInstanceName}LifecycleConfig
   - NotebookInstanceName: !Ref NotebookInstanceName
   OnStart: 
    - Content:
      Fn::Base64: !Sub 
       - |
        #!/bin/bash -xe
        set -e
        CP_SAMPLES=true
        EXTRACT_CSV=false
        s3region=s3.amazonaws.com
        SRC_NOTEBOOK_DIR=${Consumer2BucketName}/sagemaker-notebooks
        Sagedir=/home/ec2-user/SageMaker
        industry=industry
        notebooks=("notebook1.ipynb" "notebook2.ipynb" "notebook3.ipynb")
        download_files(){
          for notebook in "${notebooks[@]}"
            do
             printf "aws s3 cp s3://${SRC_NOTEBOOK_DIR}/${notebook} ${Sagedir}/${industry}\n"
             aws s3 cp s3://"${SRC_NOTEBOOK_DIR}"/"${notebook}" ${Sagedir}/${industry}
            done
        }
        if [ ${CP_SAMPLES} = true ]; then
          sudo -u ec2-user mkdir -p ${Sagedir}/${industry}
          mkdir -p ${Sagedir}/${industry}
          download_files
          chmod -R 755 ${Sagedir}/${industry}
          chown -R ec2-user:ec2-user ${Sagedir}/${industry}/.
        fi
       - Consumer2BucketName: !Ref Consumer2BucketName

引发了以下错误:

Template error: variable names in Fn::Sub syntax must contain only alphanumeric characters, underscores, periods, and colons

这似乎与 Bash Vars 和 !Sub CF 函数发生冲突。

在下面的模板中,我更改了 Bash 变量并删除了 {}:

LifecycleConfig:
  Type: AWS::SageMaker::NotebookInstanceLifecycleConfig
  Properties: 
   NotebookInstanceLifecycleConfigName: !Sub
   - ${NotebookInstanceName}LifecycleConfig
   - NotebookInstanceName: !Ref NotebookInstanceName
   OnStart: 
    - Content:
      Fn::Base64: 
       !Sub 
        - |
         #!/bin/bash -xe
         set -e
         CP_SAMPLES=true
         EXTRACT_CSV=false
         s3region=s3.amazonaws.com
         SRC_NOTEBOOK_DIR=${Consumer2BucketName}/sagemaker-notebooks
         Sagedir=/home/ec2-user/SageMaker
         industry=industry
         notebooks=("notebook1.ipynb" "notebook2.ipynb" "notebook3.ipynb")
         download_files(){
           for notebook in $notebooks
             do
              printf "aws s3 cp s3://$SRC_NOTEBOOK_DIR/${!notebook} $Sagedir/$industry\n"
              aws s3 cp s3://"$SRC_NOTEBOOK_DIR"/"${!notebook}" $Sagedir/$industry
             done
         }
         if [ $CP_SAMPLES = true ]; then
           sudo -u ec2-user mkdir -p $Sagedir/$industry
           mkdir -p $Sagedir/$industry
           download_files
           chmod -R 755 $Sagedir/$industry
           chown -R ec2-user:ec2-user $Sagedir/$industry/.
         fi
        - Consumer2BucketName: !Ref Consumer2BucketName

这里的问题是 for 循环不是 运行 遍历列表中的所有笔记本,而是只导入第一个。
在完成一些解决方案后,我尝试将 [@] 添加到笔记本中:
for notebook in $notebooks[@]

for notebook in “$notebooks[@]“/”$notebooks[*]“/$notebooks[@]
我得到了同样的错误。

It seems that was a conflict with the Bash Vars and the !Sub CF function.

没错。 bash 和 !Sub 都使用 ${} 进行变量替换。您可以 ${!}。例如:

for notebook in "${!notebooks[@]}"

docs中还提到:

To write a dollar sign and curly braces (${}) literally, add an exclamation point (!) after the open curly brace, such as ${!Literal}. AWS CloudFormation resolves this text as ${Literal}.