Public/EB/Get-ATEBInstanceLogs.ps1
function Get-ATEBInstanceLogs { <# .SYNOPSIS Retrieve CloudFormation Init and Elastic Beanstalk instance logs from one or more instances. .DESCRIPTION Retrieve CloudFormation Init and Elastic Beanstalk instance logs from one or more instances, and place them into a directory structure containing the logs for each selected instance. .PARAMETER InstanceId One or more instance Ids. .PARAMETER EnvironmentId ID of an Elastic Beanstalk environment. All running instances will be queried. .PARAMETER EnvironmentName Name of an Elastic Beanstalk environment. All running instances will be queried. .PARAMETER OutputFolder Name of folder to write logs to. If omitted a folder EB-Logs will be created in the current folder. .NOTES For this to succeed, your instances must have the SSM agent installed (generally the default with recent AMIs), and they must have a profile which includes AmazonEC2RoleforSSM managed policy, or sufficient individual rights to run the SSM command and write to S3. .EXAMPLE Get-ATEBInstanceLogs -InstanceId i-00000000,i-00000001 Get Elastic Beanstalk logs from given instances and write to EB-Logs folder in current location .EXAMPLE Get-ATEBInstanceLogs -EnvironmentId e-a4d34fd -OutputFolder C:\Temp\EB-Logs Get Elastic Beanstalk logs from instances in given EB environment by enviromnent ID and write to specified folder. .EXAMPLE Get-ATEBInstanceLogs -EnvironmentName my-enviromn -OutputFolder C:\Temp\EB-Logs Get Elastic Beanstalk logs from instances in given EB environment by name and write to specified folder. #> [CmdletBinding(DefaultParameterSetName = 'ByEnvName')] param ( [Parameter(ParameterSetName = 'ByInstance')] [string[]]$InstanceId, [Parameter(ParameterSetName = 'ByEnvId')] [string]$EnvironmentId, [Parameter(ParameterSetName = 'ByEnvName', Position = 0)] [string]$EnvironmentName, [string]$OutputFolder ) # Get the instances we will query $instances = $( switch ($PSCmdlet.ParameterSetName) { 'ByInstance' { $InstanceId } 'ByEnvId' { (Get-ATEBEnvironmentResourceList -EnvironmentId $EnvironmentId).Instances.InstanceId } 'ByEnvName' { (Get-ATEBEnvironmentResourceList -EnvironmentName $EnvironmentName).Instances.InstanceId } } ) $instanceTypes = Get-SSMEnabledInstances -InstanceId $instances if (-not $instanceTypes.Windows) { Write-Warning "No instances found that are Windows, running, passed status checks, SSM enabled and ready." return } if ($instanceTypes.NotReady) { Write-Warning "Instances not running/not passed ststus checks`n: $($instanceTypes.NotReady -join ', ')" } if ($instanceTypes.NonSSM) { Write-Warning "Instances not SSM capaable or SSM not readys`n: $($instanceTypes.NonSSM -join ', ')" } if ($instanceTypes.NonWindows) { Write-Warning "Non-Windows instances currently not supported`n: $($instanceTypes.NonWindows -join ', ')" } # Send SSM commands to get all the logs $results = Invoke-ATSSMPowerShellScript -InstanceId $instanceTypes.Windows -UseS3 -ScriptBlock { # EB and CFN logs ("C:\Program Files\Amazon\ElasticBeanstalk\Logs", "C:\cfn\log") | Where-Object { Test-Path -Path $_ -PathType Container } | ForEach-Object { Get-ChildItem $_ | Foreach-Object { Write-Host "---#LOG# $($_.Name)" Get-Content -Raw $_.FullName } } # IIS Logs try { Import-Module WebAdministration (Get-ChildItem IIS:\Sites) | Foreach-Object { $site = Get-Item $_.FullName Get-ChildItem (Join-Path ([Environment]::ExpandEnvironmentVariables($site.logfile.directory), "W3SVC$($site.id)")) | Foreach-Object { Write-Host "---#LOG# IIS_$($site.Name.Replace(' ', '_'))_$($_.Name)" Get-Content -Raw $_.FullName } } } catch { Write-Host "---#LOG# IISLogRetrievalFailed.log" Write-Host $_.Exception.Message } # Event logs ('Application', 'System') | Foreach-Object { Write-Host = "---#LOG# EventLog.$($_).csv" Get-EventLog -LogName $_ -After ( [DateTime]::Now - [timespan]::FromMinutes(60) ) | Select-Object Index, TimeGenerated, EntryType, Source, InstanceId, Message | ConvertTo-Csv -NoTypeInformation } } if (-not $OutputFolder) { $OutputFolder = Join-Path (Get-Location).Path 'EB-Logs' } # SSM writes outout to S3 in Unix text $lf = [string]([char]10) # Write out logs $results | Foreach-Object { $thisInstance = $_.InstanceId $instanceFolder = Join-Path $OutputFolder $thisInstance Write-Host "Downloading logs for $thisInstance" if (Test-Path -Path $instanceFolder -PathType Container) { # Clean out any previous results Remove-Item $instanceFolder -Recurse -Force } New-Item -Path $instanceFolder -ItemType Directory -Force | Out-Null $currentFile = $null $_.Stdout -split $lf | ForEach-Object { if ($_ -match '^---\#LOG\#\s+(?<filename>.*)') { Write-Host " -" $Matches.filename $currentFile = Join-Path $instanceFolder $Matches.filename } elseif ($null -ne $currentFile) { $_ | Out-File -Append -FilePath $currentFile } } if (-not ([string]::IsNullOrEmpty($_.Stderr))) { # Write SSM STDERR output to it's own file Write-Warning "Instance $($thisInstance): Errors were output by the commands run in SSM" $_.Stderr -split $lf | Out-File (Join-Path $instanceFolder "ssm-errors.log") } } } |