Bash script passed to AWS EC2 Instance as User Data file fails to load on initial boot

本秂侑毒 提交于 2019-12-12 04:58:30

问题


I have a simple bash script I'm trying to pass to an AWS EC2 ubuntu instance via a Powershell script using the AWS Library.

#!/bin/bash

apt-get update
apt-get upgrade

Heres the powershell script that encodes the file contents in base64 and calls the cmdlet that starts the EC2 instance:

$fileContent = Get-Content $UserDataTarget
$fileContentBytes = [System.Text.Encoding]::UTF8.GetBytes($fileContent)
$fileContentEncoded = [System.Convert]::ToBase64String($fileContentBytes)
$MasterInstance = New-EC2Instance -ImageId ami-4c7a3924 -MinCount 1 -MaxCount 1 -KeyName AWSKey -SecurityGroups $SecurityGroup -InstanceType "t1.micro" -UserData $fileContentEncoded

This is a snippet from the cloud init log:

Cloud-init v. 0.7.5 running 'modules:final' at Fri, 02 Oct 2015 21:05:24 +0000. Up 33.88 seconds.
/bin/bash: apt-get update apt-get upgrade: No such file or directory
2015-10-02 21:05:24,294 - util.py[WARNING]: Failed running /var/lib/cloud/instance/scripts/part-001 [127]
2015-10-02 21:05:24,298 - cc_scripts_user.py[WARNING]: Failed to run module scripts-user (scripts in /var/lib/cloud/instance/scripts)
2015-10-02 21:05:24,298 - util.py[WARNING]: Running scripts-user (<module 'cloudinit.config.cc_scripts_user' from '/usr/lib/python2.7/dist-packages/cloudinit/config/cc_scripts_user.pyc'>) failed

Here's a snippet of the loaded user data script on the ubuntu instance at /var/lib/cloud/instance/scripts/part-001:

#!/bin/bash  apt-get update apt-get upgrade

I have tried converting the windows file to linux using 010 Editor and Cygwin. I've tried replacing the CRLF bytes with LF bytes. The result is the same: the entire bash script is condensed to 1 line, all line breaks are removed, and user data script fails to load on initial boot.

UPDATE: I've included both code snippets I've used to do the line break conversion. Both were vetted from peer sources (SO). For some reason, the script still shows up in the linux instance without the line break characters.

Snippet 1

function ConvertTo-LinuxLineEndings($path) {
        $oldBytes = [io.file]::ReadAllBytes($path)
        if (!$oldBytes.Length) {
            return;
        }
        [byte[]]$newBytes = @()
        [byte[]]::Resize([ref]$newBytes, $oldBytes.Length)
        $newLength = 0
        for ($i = 0; $i -lt $oldBytes.Length - 1; $i++) {
            if (($oldBytes[$i] -eq [byte][char]"`r") -and ($oldBytes[$i + 1] -eq [byte][char]"`n")) {
                continue;
            }
            $newBytes[$newLength++] = $oldBytes[$i]
        }
        $newBytes[$newLength++] = $oldBytes[$oldBytes.Length - 1]
        [byte[]]::Resize([ref]$newBytes, $newLength)
        [io.file]::WriteAllBytes($path, $newBytes)
    }

    ConvertTo-LinuxLineEndings($UserDataTarget)

Snippet 2

try{

    # get the contents and replace line breaks by U+000A
    $contents = [IO.File]::ReadAllText($UserDataSource) -replace "`r`n", "`n"
    # create UTF-8 encoding without signature
    $utf8 = New-Object System.Text.UTF8Encoding $false
    # write the text back
    [IO.File]::WriteAllText($UserDataTarget, $contents, $utf8)
}
catch [Exception]
{
    echo $_.Exception|format-list -force
}

回答1:


I can't give you an answer on what your Powershell code needs to look like, but in case it helps I can tell you what the output from your Powershell script needs to look like, so you need to confirm that this is what you're ending up with in the UserData when it goes in the template:

"UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [
            "#!/bin/bash\n\n",
            "apt-get update\n",
            "apt-get upgrade\n"
        ]]}}


来源:https://stackoverflow.com/questions/32916167/bash-script-passed-to-aws-ec2-instance-as-user-data-file-fails-to-load-on-initia

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!