简体   繁体   English

Windows EC2 用户数据未执行

[英]Windows EC2 User Data Not Executing

The problem:问题:

We need to execute a Powershell script using Userdata on a Windows AWS EC2 instance so that we can join and unjoin our domain's activity directory.我们需要在 Windows AWS EC2 实例上使用用户数据执行 Powershell 脚本,以便我们可以加入和取消加入我们域的活动目录。 The EC2 Userdata log shows the instance being stuck at: EC2 用户数据日志显示实例被卡在:

Ec2HandleUserData :  is currently executing. To end it kill the process with id:
 

We have tried adding lines of code documented here but no luck . 我们尝试添加此处记录的代码行,但没有成功 Can anyone see what is being done wrong?任何人都可以看到做错了什么吗? Note we have commented out logging because we don't currently have CloudWatch setup.请注意,我们已注释掉日志记录,因为我们目前没有 CloudWatch 设置。 Script we are using is below and thank you for your help!我们正在使用的脚本如下,感谢您的帮助!

<powershell>
$file = $env:SystemRoot + "\Temp\" + (Get-Date).ToString("MM-dd-yy-hh-mm")
New-Item $file -ItemType file
# Script parameters
[string]$SecretAD = "prod/AD"
#class Logger {
#   #----------------------------------------------
#   [string] hidden  $cwlGroup
#   [string] hidden  $cwlStream
#   [string] hidden  $sequenceToken
#   #----------------------------------------------
#   # Log Initialization
#   #----------------------------------------------
#   Logger([string] $Action) {
#       $this.cwlGroup = "/ps/boot/configuration/"
#       $this.cwlStream = "{0}/{1}/{2}" -f $env:COMPUTERNAME, $Action,
#       (Get-Date -UFormat "%Y-%m-%d_%H.%M.%S")
#       $this.sequenceToken = ""
#       #------------------------------------------
#       if ( !(Get-CWLLogGroup -LogGroupNamePrefix $this.cwlGroup) ) {
#           New-CWLLogGroup -LogGroupName $this.cwlGroup
#           Write-CWLRetentionPolicy -LogGroupName $this.cwlGroup -RetentionInDays 3
#       }
#       if ( !(Get-CWLLogStream -LogGroupName $this.cwlGroup -LogStreamNamePrefix $this.cwlStream) ) {
#           New-CWLLogStream -LogGroupName $this.cwlGroup -LogStreamName $this.cwlStream
#       }
#   }
#   #----------------------------------------
#   [void] WriteLine([string] $msg) {
#       #$logEntry = New-Object -TypeName "Amazon.CloudWatchLogs.Model.InputLogEvent"
#       #-----------------------------------------------------------
#       #$logEntry.Message = $msg
#       #$logEntry.Timestamp = (Get-Date).ToUniversalTime()
#       if ("" -eq $this.sequenceToken) {
#           # First write into empty log...
#           $this.sequenceToken = Write-CWLLogEvent -LogGroupName $this.cwlGroup `
#               -LogStreamName $this.cwlStream `
#               -LogEvent #$logEntry
#       }
#       else {
#           # Subsequent write into the log...
#           $this.sequenceToken = Write-CWLLogEvent -LogGroupName $this.cwlGroup `
#               -LogStreamName $this.cwlStream `
#               -SequenceToken $this.sequenceToken `
#               -LogEvent #$logEntry
#       }
#   }
#}
#[Logger]#$log = [Logger]::new("UserData")
#$log.WriteLine("------------------------------")
#$log.WriteLine("Log Started - V4.0")
$RunUser = 'TrustedInstaller'

Write-Output "I set the run user"

#$log.WriteLine("PowerShell session user: $RunUser")
class SDManager {
    #-------------------------------------------------------------------
    #[Logger] hidden $SDLog
    [string] hidden $GPScrShd_0_0 = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Group Policy\Scripts\Shutdown\0\0"
    [string] hidden $GPMScrShd_0_0 = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Group Policy\State\Machine\Scripts\Shutdown\0\0"
    #-------------------------------------------------------------------
    SDManager([string]$RegFilePath, [string]$SecretName) {
        #$this.SDLog = #$log
        #----------------------------------------------------------------
        [string] $SecretLine = '[string]$SecretAD    = "' + $SecretName + '"'
        #--------------- Local Variables -------------
        [string] $GPRootPath = "C:\Windows\System32\GroupPolicy"
        [string] $GPMcnPath = "C:\Windows\System32\GroupPolicy\Machine"
        [string] $GPScrPath = "C:\Windows\System32\GroupPolicy\Machine\Scripts"
        [string] $GPSShdPath = "C:\Windows\System32\GroupPolicy\Machine\Scripts\Shutdown"
        [string] $ScriptFile = [System.IO.Path]::Combine($GPSShdPath, "Shutdown-UnJoin.ps1")
        #region Shutdown script (scheduled through Local Policy)
        $ScriptBody =
        @(
            'param([string]$cntrl = "NotSet")',
            $SecretLine,
            '[string]$MachineName = $env:COMPUTERNAME',
            '#class Logger {    ',
            '#    #----------------------------------------------    ',
            '#    [string] hidden  $cwlGroup    ',
            '#    [string] hidden  $cwlStream    ',
            '#    [string] hidden  $sequenceToken    ',
            '#    #----------------------------------------------    ',
            '#    # Log Initialization    ',
            '#    #----------------------------------------------    ',
            '#    Logger([string] $Action) {    ',
            '#        $this.cwlGroup = "/ps/boot/configuration/"    ',
            '#        $this.cwlStream = "{0}/{1}/{2}" -f $env:COMPUTERNAME, $Action,    ',
            '#                                           (Get-Date -UFormat "%Y-%m-%d_%H.%M.%S")    ',
            '#        $this.sequenceToken = ""    ',
            '#        #------------------------------------------    ',
            '#        if ( !(Get-CWLLogGroup -LogGroupNamePrefix $this.cwlGroup) ) {    ',
            '#            New-CWLLogGroup -LogGroupName $this.cwlGroup    ',
            '#            Write-CWLRetentionPolicy -LogGroupName $this.cwlGroup -RetentionInDays 3    ',
            '#        }    ',
            '#        if ( !(Get-CWLLogStream -LogGroupName $this.cwlGroup -LogStreamNamePrefix $this.cwlStream) ) {    ',
            '#            New-CWLLogStream -LogGroupName $this.cwlGroup -LogStreamName $this.cwlStream    ',
            '#        }    ',
            '#    }    ',
            '#    #----------------------------------------    ',
            '#    [void] WriteLine([string] $msg) {    ',
            '#        #$logEntry = New-Object -TypeName "Amazon.CloudWatchLogs.Model.InputLogEvent"    ',
            '#        #-----------------------------------------------------------    ',
            '#        #$logEntry.Message = $msg    ',
            '#        #$logEntry.Timestamp = (Get-Date).ToUniversalTime()    ',
            '#        if ("" -eq $this.sequenceToken) {    ',
            '#            # First write into empty log...    ',
            '#            $this.sequenceToken = Write-CWLLogEvent -LogGroupName $this.cwlGroup `',
            '#                -LogStreamName $this.cwlStream `',
            '#                -LogEvent #$logEntry    ',
            '#        }    ',
            '#        else {    ',
            '#            # Subsequent write into the log...    ',
            '#            $this.sequenceToken = Write-CWLLogEvent -LogGroupName $this.cwlGroup `',
            '#                -LogStreamName $this.cwlStream `',
            '#                -SequenceToken $this.sequenceToken `',
            '#                -LogEvent #$logEntry    ',
            '#        }    ',
            '#    }    ',
            '#}    ',
            '#[Logger]#$log = [Logger]::new("UnJoin")',
            '#$log.WriteLine("-----------------------------------------")',
            '#$log.WriteLine("Log Started")',
            'if ($cntrl -ne "run") ',
            '    { ',
            '    #$log.WriteLine("Script param <" + $cntrl + "> not set to <run> - script terminated") ',
            '    return',
            '    }',
            '$compSys = Get-WmiObject -Class Win32_ComputerSystem',
            'if ( -Not ($compSys.PartOfDomain))',
            '    {',
            '    #$log.WriteLine("Not member of a domain - terminating script")',
            '    return',
            '    }',
            '$RSAT = (Get-WindowsFeature RSAT-AD-PowerShell)',
            'if ( $RSAT -eq $null -or (-Not $RSAT.Installed) )',
            '    {',
            '    #$log.WriteLine("<RSAT-AD-PowerShell> feature not found - terminating script")',
            '    return',
            '    }',
            '#$log.WriteLine("Removing machine <" +$MachineName + "> from Domain <" + $compSys.Domain + ">")',
            '#$log.WriteLine("Reading Secret <" + $SecretAD + ">")',
            #'Import-Module AWSPowerShell',
            #'try { $SecretObj = (Get-SECSecretValue -SecretId $SecretAD) }',
            #'catch ',
            #'    { ',
            #'    #$log.WriteLine("Could not load secret <" + $SecretAD + "> - terminating execution")',
            #'    return ',
            #'    }',
            #'[PSCustomObject]$Secret = ($SecretObj.SecretString  | ConvertFrom-Json)',
            '$password   = "<password>"',
            '$username   = "<username>"',
            '$credential = New-Object System.Management.Automation.PSCredential($username,$password)',
            'import-module ActiveDirectory',
            '$DCHostName = (Get-ADDomainController -Discover).HostName',
            '#$log.WriteLine("Using Account <" + $username + ">")',
            '#$log.WriteLine("Using Domain Controller <" + $DCHostName + ">")',
            'Remove-Computer -WorkgroupName "WORKGROUP" -UnjoinDomainCredential $credential -Force -Confirm:$false ',
            'Remove-ADComputer -Identity $MachineName -Credential $credential -Server "$DCHostName" -Confirm:$false ',
            '#$log.WriteLine("Machine <" +$MachineName + "> removed from Domain <" + $compSys.Domain + ">")'
        )
        #$this.SDLog.WriteLine("Constracting artifacts required for domain UnJoin")
        #----------------------------------------------------------------
    Write-Output "I created SDManager class"

        try {
            if (!(Test-Path -Path $GPRootPath -pathType container))
            { New-Item -ItemType directory -Path $GPRootPath }
            if (!(Test-Path -Path $GPMcnPath -pathType container))
            { New-Item -ItemType directory -Path $GPMcnPath }
            if (!(Test-Path -Path $GPScrPath -pathType container))
            { New-Item -ItemType directory -Path $GPScrPath }
            if (!(Test-Path -Path $GPSShdPath -pathType container))
            { New-Item -ItemType directory -Path $GPSShdPath }
        }
        catch {
            #$this.SDLog.WriteLine("Failure creating UnJoin script directory!" )
            #$this.SDLog.WriteLine($_)
            Write-Output  "hello"
        }
        #----------------------------------------
        try {
            Set-Content $ScriptFile -Value $ScriptBody
        }
        catch {
            #$this.SDLog.WriteLine("Failure saving UnJoin script!" )
            #$this.SDLog.WriteLine($_)
            Write-Output  "hello"
        }
        #----------------------------------------
        
# UPDATE WINDOWS REGISTRY AND CREATE A SHUTDOWN TASK        
        
        $RegistryScript =
        @(
            'Windows Registry Editor Version 5.00',
            '[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Group Policy\Scripts]',
            '[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Group Policy\Scripts\Shutdown]',
            '[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Group Policy\Scripts\Shutdown\0]',
            '"GPO-ID"="LocalGPO"',
            '"SOM-ID"="Local"',
            '"FileSysPath"="C:\\Windows\\System32\\GroupPolicy\\Machine"',
            '"DisplayName"="Local Group Policy"',
            '"GPOName"="Local Group Policy"',
            '"PSScriptOrder"=dword:00000001',
            '[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Group Policy\Scripts\Shutdown\0\0]',
            '"Script"="Shutdown-UnJoin.ps1"',
            '"Parameters"=""',
            '"IsPowershell"=dword:00000001',
            '"ExecTime"=hex(b):00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00',
            '[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Group Policy\Scripts\Startup]',
            '[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Group Policy\State\Machine\Scripts]',
            '[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Group Policy\State\Machine\Scripts\Shutdown]',
            '[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Group Policy\State\Machine\Scripts\Shutdown\0]',
            '"GPO-ID"="LocalGPO"',
            '"SOM-ID"="Local"',
            '"FileSysPath"="C:\\Windows\\System32\\GroupPolicy\\Machine"',
            '"DisplayName"="Local Group Policy"',
            '"GPOName"="Local Group Policy"',
            '"PSScriptOrder"=dword:00000001',
            '[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Group Policy\State\Machine\Scripts\Shutdown\0\0]',
            '"Script"="Shutdown-UnJoin.ps1"',
            '"Parameters"=""',
            '"ExecTime"=hex(b):00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00',
            '[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Group Policy\State\Machine\Scripts\Startup]'
        )
        Write-Output "I created the registry script."

        try {
            [string] $RegistryFile = [System.IO.Path]::Combine($RegFilePath, "OnShutdown.reg")
            Set-Content $RegistryFile -Value $RegistryScript
            &regedit.exe /S "$RegistryFile"
        }
        catch {
            #$this.SDLog.WriteLine("Failure creating policy entry in Registry!" )
            #$this.SDLog.WriteLine($_)
            Write-Output "hello"
        }
    }

#DISABLE UNJOIN AND ENABLE JOIN FOR THE FIRST RUN
    
    #----------------------------------------
    [void] DisableUnJoin() {
        try {
            Set-ItemProperty -Path $this.GPScrShd_0_0  -Name "Parameters" -Value "ignore"
            Set-ItemProperty -Path $this.GPMScrShd_0_0 -Name "Parameters" -Value "ignore"
            &gpupdate /Target:computer /Wait:0
        }
        catch {
            #$this.SDLog.WriteLine("Failure in <DisableUnjoin> function!" )
            #$this.SDLog.WriteLine($_)
            Write-Output  "hello"
        }
    }
    #----------------------------------------
    [void] EnableUnJoin() {
        try {
            Set-ItemProperty -Path $this.GPScrShd_0_0  -Name "Parameters" -Value "run"
            Set-ItemProperty -Path $this.GPMScrShd_0_0 -Name "Parameters" -Value "run"
            &gpupdate /Target:computer /Wait:0
        }
        catch {
            #$this.SDLog.WriteLine("Failure in <EnableUnjoin> function!" )
            #$this.SDLog.WriteLine($_)
            Write-Output "hello"
        }
    }
}
Write-Output "I created the the join and unjoin functions"
# GET SECRETS

#[SDManager]$sdm = [SDManager]::new(#$log, "C:\ProgramData\Amazon\EC2-Windows\Launch\Scripts", $SecretAD)
##$log.WriteLine("Loading Secret <" + $SecretAD + ">")
#Import-Module AWSPowerShell
#try { $SecretObj = (Get-SECSecretValue -SecretId $SecretAD) }
#catch {
#   #$log.WriteLine("Could not load secret <" + $SecretAD + "> - terminating execution")
#   return
#}
#[PSCustomObject]$Secret = ($SecretObj.SecretString  | ConvertFrom-Json)
##$log.WriteLine("Domain (from Secret): <" + $domain + ">")



# Verify domain membership

#IF ALREADY MEMBER OF DOMAIN 

$compSys = Get-WmiObject -Class Win32_ComputerSystem
#------------------------------------------------------------------------------
if ( ($compSys.PartOfDomain) -and ($compSys.Domain -eq $domain)) {
    #$log.WriteLine("Already member of: <" + $compSys.Domain + "> - Verifying RSAT Status")
    
    #CHECK IF RSTAT IS INSTALLED
    
    $RSAT = (Get-WindowsFeature RSAT-AD-PowerShell)
    if ($null -eq $RSAT) {
        #$log.WriteLine("<RSAT-AD-PowerShell> feature not found - terminating script")
        return
    }
    
    #ENABLE ON SHUT DOWN & INSTALL RSTAT
    
    #$log.WriteLine("Enable OnShutdown task to un-join Domain")
    $sdm.EnableUnJoin()
    if ( (-Not $RSAT.Installed) -and ($RSAT.InstallState -eq "Available") ) {
        #$log.WriteLine("Installing <RSAT-AD-PowerShell> feature")
        Install-WindowsFeature RSAT-AD-PowerShell
    }
    #$log.WriteLine("Terminating script - ")
    return
}

# IF NOT MEMBER OF DOMAIN THEN JOIN AND RESTART

# Performing Domain Join
#$log.WriteLine("Domain Join required")
#$log.WriteLine("Disable OnShutdown task to avoid reboot loop")
$sdm.DisableUnJoin()
$password = "<password>"
$username = "<username>"
$domain = "<domain>"
$credential = New-Object System.Management.Automation.PSCredential($username, $password)
#$log.WriteLine("Attempting to join domain <" + $domain + ">")
Add-Computer -DomainName $domain -Credential $credential -Restart -Force
#$log.WriteLine("Requesting restart...")

Write-Output "I joined or unjoined the domain friends."
#------------------------------------------------------------------------------
</powershell>
<persist>true</persist>

Did you find an answer?你找到答案了吗? I believe your inline script is too long to be executed in userdata.我相信您的内联脚本太长而无法在用户数据中执行。 You're likely running into the issue here: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instancedata-add-user-data.html您可能会在这里遇到问题: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instancedata-add-user-data.html

When I run into this, I find it best to upload the script to S3, allow the EC2 instance RO access to the S3 bucket via the EC2 instance profile, then pull from the bucket and run the script in the userdata.当我遇到这个问题时,我发现最好将脚本上传到 S3,允许 EC2 实例 RO 通过 EC2 实例配置文件访问 S3 存储桶,然后从存储桶中提取并在用户数据中运行脚本。

HTH!喂!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM