【问题标题】:How to set Environment Variables on EC2 instance via User Data如何通过用户数据在 EC2 实例上设置环境变量
【发布时间】:2016-03-16 07:17:01
【问题描述】:

我正在尝试使用 EC2 的用户数据设置环境变量,但我所做的一切似乎都不起作用

这是我尝试过的用户数据脚本

#!/bin/bash
echo "export HOST_URL=checkEmai-LoadBala-ICHJ82KG5C7P-23235232.us-east-1.elb.amazonaws.com" >> /env.sh 
source /env.sh

还有一个:

#!/bin/bash
echo "#!/bin/bash" >> /env.sh
echo "export HOST_URL=checkEmai-LoadBala-ICHJ82KG5C7P-67323523.us-east-1.elb.amazonaws.com" >> /env.sh 
chmod +x /env.sh
/env.sh

他们都没有做任何事情,如果我登录并发出命令source /env.sh/env.sh 它可以工作。所以这一定是我正在尝试做的被禁止的事情。

这是 /var/log/cloud-init-output.log 使用 -e -x 的输出

+ echo 'export HOST_URL=checkEmai-LoadBala-ICHJ82KG5C7P-2141709021.us-east-1.elb.amazonaws.com'
+ source /env.sh
++ export HOST_URL=checkEmai-LoadBala-ICHJ82KG5C7P-2141709022.us-east-1.elb.amazonaws.com
++ HOST_URL=checkEmai-LoadBala-ICHJ82KG5C7P-2141709022.us-east-1.elb.amazonaws.com

不过,echo $HOST_URL 是空的

根据要求,完整的 UserData 脚本

#!/bin/bash
set -e -x 
echo "export HOST_URL=checkEmai-LoadBala-ICHJ82KG5C7P-2141709021.us-east-1.elb.amazonaws.com" >> /env.sh 
source /env.sh
/startup.sh staging 2649

【问题讨论】:

  • 您是想为稍后在用户数据中运行的脚本设置环境变量,还是希望在通过 SSH 登录服务器时这些变量可用?另外,您确定您使用的 AMI 支持用户数据脚本吗?
  • 1:我正在尝试将用户数据设置为在该脚本之后运行的应用程序。 2:是的,用户数据脚本可以工作,这只是对在该脚本之后运行的脚本的补充
  • 明确地说,您希望变量可用的脚本也在您的用户数据脚本中被调用?
  • 是的,sn-p 是从 ec2 实例用户数据中复制粘贴
  • 你能显示整个用户数据脚本吗?你在哪里跑echo $HOST_URL

标签: linux bash amazon-web-services amazon-ec2


【解决方案1】:

最简单的方法肯定是使用 AWS Elastic Beanstalk,它可以为您创建所需的一切,并且只需很少的努力,并且在整个 AWS 生态系统中拥有最简单的方法来设置您的环境变量。

检查一下,还有一些基于不同语言的详尽教程 https://docs.aws.amazon.com/elastic-beanstalk/index.html

【讨论】:

  • 这个答案与问题无关。您可以在评论中添加建议,但这不是答案。
【解决方案2】:

this Medium.com article,您可以在UserData 中放置一个脚本,该脚本将写入/etc/profile.d 中的一个文件,该文件将在运行新shell 时自动运行。

这是一个例子cloudformation.yaml

Parameters:
  SomeOtherResourceData:
    default: Fn::ImportValue: !Sub "SomeExportName"
Resources:
  WebApi:
    Type: AWS::EC2::Instance
    Properties:
      # ...
      UserData:
        Fn::Base64: !Sub
          - |
            #!/bin/bash

            cat > /etc/profile.d/load_env.sh << 'EOF'

            export ACCOUNT_ID=${AWS::AccountId}
            export REGION=${AWS::Region}
            export SOME_OTHER_RESOURCE_DATA=${SomeOtherResourceData}

            EOF
            chmod a+x /etc/profile.d/load_env.sh

还有一个导出东西的 YAML

# ...
Outputs:
  SomeExportName:
    Value: !Sub "${WebDb.Endpoint.Address}"
    Export:
      Name: SomeExportName

【讨论】:

    【解决方案3】:

    EC2 上的用户数据脚本在启动后执行在它自己的进程中。环境变量在该进程中设置并在进程退出时消失。您不会在其他进程中看到环境变量,即登录 shell 或其他程序。

    您必须想办法将这些环境变量放入需要查看它们的任何程序中。

    您需要这些变量在哪里可用?在/startup.sh staging 2649?

    编辑

    试试这个:

    #!/bin/bash
    set -e -x 
    export HOST_URL="checkEmai-LoadBala-ICHJ82KG5C7P-2141709021.us-east-1.elb.amazonaws.com"
    /startup.sh staging 2649
    

    然后编辑/startup.sh,将下面一行放在最上面:

    echo $HOST_URL > /tmp/var
    

    启动实例,然后在此处粘贴/tmp/var

    【讨论】:

    • startup.sh 运行一个 rails 应用程序,在该 rails 应用程序内部使用了那个 env 变量
    【解决方案4】:

    为 EC2 实例定义环境变量的一种更可配置的方法是使用Systems Manager Parameter Store。这种方法将使管理大量 EC2 实例的不同参数变得更加容易,无论是使用AWS KMS 加密还是纯文本加密。它还允许通过对 EC2 实例级别的最小更改来更改参数值。步骤如下。

    • EC2 Systems Manager Parameter Store 中定义字符串参数(使用 KMS 加密或未加密)。
    • 在 EC2 担任的 IAM 角色中,授予访问参数存储所需的权限。
    • 使用 EC2 System Manager 的 AWS CLI 命令,根据需要使用 Get-ParameterGet-Parameters AWS CLI 命令和 controlling command output 读取参数并导出到用户数据部分中的环境变量。

    例如使用Get-Parameter 命令检索db_connection_string 参数(未加密)。

    export DB_CONNECTION=$(aws --region=us-east-2 ssm get-parameter --name 'db_connection' --query 'Value')
    

    注意:有关设置 AWS KMS 密钥、定义加密字符串、管理 IAM 策略等的更多详细信息,请参阅以下文章。

    【讨论】:

    • 上面的脚本给了我null。以下为我工作export DB_CONNECTION=$(aws --region=ap-southeast-1 ssm get-parameters --names 'db_connection' --query "Parameters[0].Value")
    • 类似于上述评论--query 'Parameter.Value' 对我有用。如果你在没有--query 的情况下运行命令,你应该会看到参数结构,并且通过它你应该能够弄清楚你到底需要查询什么。
    • 另外,如果您存储了例如数据库 URL 作为带有 KMS 的SecureString,然后将--with-decryption 附加到上面的aws ssm 命令以解密该值。
    • 您还需要修剪掉" 字符,除非您在应用程序代码中处理它。将该命令传递给tr -d \" 对我来说是成功的。
    【解决方案5】:

    这可能不是对 OP 问题的确切答案,但类似。我想分享这个,因为我浪费了足够多的时间来寻找答案并最终弄明白了。

    假设示例 - AWS EC2 运行 ubuntu

    如果您需要定义环境变量并在同一个 bash 会话(相同的用户数据进程)中使用它,那么您可以将变量添加到 /etc/profile/etc/environment 或 @ 987654324@ 文件。我还没有尝试过/home/ubuntu/.profile 文件顺便说一句。

    假设添加到.zshrc文件,

    sudo su ubuntu -c "$(cat << EOF 
        echo 'export PATH="/tmp:\$PATH"' >> /home/ubuntu/.zshrc
        echo 'export ABC="XYZ"' >> /home/ubuntu/.zshrc
        echo 'export PY_VERSION=3.8.1' >> /home/ubuntu/.zshrc
        source /home/ubuntu/.zshrc
        echo printenv > /tmp/envvars  # To test
    EOF
    )"
    

    用户数据运行完成后,您可以看到您在脚本中添加的环境变量已回显到envvars 文件中。使用 source /home/ubuntu/.zshrc 重新加载 bash 使新添加的变量在 bash 会话中可用。

    (附加信息)如何安装zshoh-my-zsh

    sudo apt-get install -y zsh
    sudo su ubuntu -c "$(cat << EOF 
        ssh-keyscan -H github.com >> /home/ubuntu/.ssh/known_hosts
        git clone https://github.com/robbyrussell/oh-my-zsh.git /home/ubuntu/.oh-my-zsh
        cp /home/ubuntu/.oh-my-zsh/templates/zshrc.zsh-template /home/ubuntu/.zshrc
        echo DISABLE_AUTO_UPDATE="true" >> /home/ubuntu/.zshrc
        cp /home/ubuntu/.oh-my-zsh/themes/robbyrussell.zsh-theme /home/ubuntu/.oh-my-zsh/custom
    EOF
    )"
    sudo chsh -s /bin/zsh ubuntu
    

    想知道为什么我没有在.bashrc 中添加环境变量吗?我上面提到的场景(在同一个用户数据会话中使用环境变量)添加到.bashrc 将不起作用。 .bashrc 仅用于交互式 Bash shell,因此不需要 .bashrc 检查它是否在交互式 shell 中运行。所以就像上面一样,

    source /home/ubuntu/.bashrc
    

    不会重新加载 bash。您可以在.bashrc 文件的开头查看此内容,

    # If not running interactively, don't do anything
    case $- in
        *i*) ;;
          *) return;;
    esac
    

    【讨论】:

      【解决方案6】:

      将此添加到节点的初始化脚本将在启动时添加环境变量。它们不会出现在节点配置页面中,但它们将能够用于任何工作。

      #!/bin/bash
      echo 'JAVA_HOME="/usr/lib/jvm/java-8-oracle/"' | sudo tee -a /etc/profile#
      

      这个答案与 hamx0r 提出的类似,但是 jenkins 无权回显到 /etc/profiles 使用或不使用 sudo。

      【讨论】:

        【解决方案7】:

        你可以使用这个脚本:

        #!/bin/bash
        echo HOST_URL=\"checkEmai-LoadBala-ICHJ82KG5C7P-23235232.us-east-1.elb.amazonaws.com\" >> /etc/environment
        

        我使用 Amazon Linux AMI 2018.03.0 创建了一个 EC2 实例,并将此用户数据添加到其中,它工作正常。

        详情请参阅this answer

        【讨论】:

        • 根据askubuntu.com/a/58828/615301,这似乎是唯一考虑到export 不应该在/etc/environment 中的答案(也可能是/etc/profile
        【解决方案8】:

        您可以在/etc/profile.d/yourscript.sh 中添加另一个shell 脚本,其中将包含您要添加的一组环境变量。

        此脚本将在每次启动时运行,您的变量将可供所有用户使用。

        #!/bin/sh
        echo 'export AWS_DEFAULT_REGION=ap-southeast-2' > ~/myconfiguration.sh
        chmod +x ~/myconfiguration.sh
        sudo cp ~/myconfiguration.sh /etc/profile.d/myconfiguration.sh
        

        上面的代码创建了一个shell脚本来为aws默认区域设置环境变量并将其复制到profile.d

         

        【讨论】:

        • 添加后刷新bash shell,命令:source /etc/profile
        【解决方案9】:

        我发现这是为使用用户数据的所有用户设置环境变量的一种非常简单的方法。它允许我配置应用程序,以便同一个 AMI 可以用于多种场景:

        #!/bin/bash
        echo export DB_CONNECTION="some DB connection" >> /etc/profile
        echo export DB_USERNAME="my user" >> /etc/profile
        echo export DB_PASSWORD="my password" >> /etc/profile
        

        现在,所有用户都将 DB_CONNECTION、DB_USERNAME 和 DB_PASSWORD 设置为环境变量。

        【讨论】:

        • 对我不起作用。我得到了错误:-bash: /etc/profile: Permission denied。 PS:我也尝试使用 sudo。
        • 好方法...我发现在引号中回显的内容的更简洁的语法效果很好。 echo "export GOROOT=/usr/local/go" &gt;&gt; /etc/profile
        • @DiegoSomar echo 不适用于 sudo。改用 tee:echo export DB_CONNECTION="some DB connection" | sudo tee -a /etc/profile
        【解决方案10】:

        完成用户数据脚本中的内容后,进程退出。 因此,您导出的任何环境变量都不会出现在下一个过程中。一种方法是将导出文件放在 .bashrc 文件中,以便它在下一个会话中也可用。

            echo "export HOST_URL=checkEmai-LoadBala-ICHJ82KG5C7P-23235232.us-east-1.elb.amazonaws.com" >> ~/.bashrc
        

        【讨论】:

        猜你喜欢
        • 2021-04-26
        • 2017-10-18
        • 1970-01-01
        • 2020-11-04
        • 2015-04-22
        • 2016-01-26
        • 1970-01-01
        • 2018-11-13
        • 1970-01-01
        相关资源
        最近更新 更多