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' { Write-Host "Getting EB environment details..." (Get-ATEBEnvironmentResourceList -EnvironmentId $EnvironmentId).Instances.InstanceId } 'ByEnvName' { Write-Host "Getting EB environment details..." (Get-ATEBEnvironmentResourceList -EnvironmentName $EnvironmentName).Instances.InstanceId } } ) Write-Host "Checking instances for SSM..." $instanceTypes = Get-SSMEnabledInstances -InstanceId $instances if ($instanceTypes.NotReady) { Write-Warning "Instances not running/not passed status checks`n: $($instanceTypes.NotReady -join ', ')" } if ($instanceTypes.NonSSM) { Write-Warning "Instance is not SSM capable or SSM is not ready`n: $($instanceTypes.NonSSM -join ', ')" } # Send SSM commands to get all the logs $results = $( if ($instanceTypes.Windows) { 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 ($instanceTypes.NonWindows) { $shellScript = @" for f in `$(ls /var/log/eb*.log) do echo "---#LOG# `$(basename `$f)" cat `$f done for f in `$(ls /var/log/cfn-*.log) do echo "---#LOG# `$(basename `$f)" cat `$f done for f in `$(ls /var/log/cloud-*.log) do echo "---#LOG# `$(basename `$f)" cat `$f done if [ -d /var/log/nginx ] then for f in /var/log/nginx/access.log /var/log/nginx/error.log do echo "---#LOG# `$(basename `$f)" cat `$f done fi "@ Invoke-ATSSMShellScript -InstanceId $instanceTypes.NonWindows -UseS3 -CommandText $shellScript } ) 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") } } } |