-
Notifications
You must be signed in to change notification settings - Fork 0
/
CheckForRestartsAndUptime.ps1
170 lines (154 loc) · 5.72 KB
/
CheckForRestartsAndUptime.ps1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
#Checks for shutdown events and uptime
#Reference
#Event Log ID | Meaning
#41 | The system has rebooted without cleanly shutting down first
#1074 | The system has been shutdown properly by a user or process
#1076 | Follows after EventLog.Id ID 6008 and means that the first user with shutdown privileges logged on to the server after an unexpected restart or shutdown and specified the cause
#6005 | The EventLog.Id Log service was started. Indicates the system startup
#6006 | The EventLog.Id Log service was stopped. Indicates the proper system shutdown
#6008 | The previous system shutdown was unexpected
#6009 | The operating system version detected at the system startup
#6013 | The system uptime in seconds
[int32]$WarningUptime = $args[0] #Uptime in total hours. Example, if you want 3 days enter 72
[int32]$CriticalUptime = $args[1] #Uptime in total hours.
[int32]$MaxEventAge = $args[2] #Uptime in total hours. Don't look back more than X hours in the event log
#-----------------
#Validate input
if ($Error.Count -gt 0) {
$LASTEXITCODE = 3
Clear-Host
Write-Output 'UNKNOWN: Use only Int32 numbers for the arguments'
exit $LASTEXITCODE
}
#Reboot & Shutdown EventLog.Id IDs
$EventIDs = @(41,1074,1076,6005,6006,6008)
#Measure Uptime
$CurrentTime = Get-Date
$LastBoot = (Get-CimInstance -ClassName Win32_OperatingSystem | Select-Object -Property LastBootUpTime).LastBootUpTime
$ActualUptime = $CurrentTime - $LastBoot
[int32]$ActualUptime = $ActualUptime.TotalHours
#$ActualUptime = (Get-Uptime).TotalHours #If PS7
$UptimeMessage = "Server has been up for $ActualUptime hours"
#Get events
$Events = Get-WinEvent -LogName system -Oldest | Where-Object -Property Id -in $EventIDs
$EventsFiltered = $Events | Where-Object {(($CurrentTime - $_.TimeCreated).TotalHours) -le $MaxEventAge} | Select-Object -Property *
#Reformat event info
$EventsReformat = foreach ($EventLog in $EventsFiltered) {
$NewEvent = [PSCustomObject]@{
Time = $EventLog.TimeCreated
ID = $EventLog.Id
Level = $EventLog.LevelDisplayName
Container = $EventLog.ContainerLog
ProviderName = $EventLog.ProviderName
Log = $EventLog.LogName
User = $EventLog.UserId.Value
Message = $EventLog.Message
}
#Determine SID type
if ($null -ne $EventLog.UserId) {
$SIDID1 = (($EventLog.UserId.Value.ToString()) -split '-')[3]
$SIDTest1 = $SIDID1 -in 0..20
}
#Test for Get-ADUser abilities. Will reports AD user if able
$PreErrorCheck = $Error.Count
$ADUserAbility = (Get-Command Get-ADUser -ErrorAction SilentlyContinue).count -gt 0
if ($PreErrorCheck -lt 1) {
$Error.Clear()
}
if ($null -eq $EventLog.UserId) {
$NewEvent.User = 'None/Unknown'
} elseif ($SIDTest1 -eq $false) {
if ($ADUserAbility -eq $true) {
$NewEvent.User = (Get-ADUser -identity $EventLog.UserId).SamAccountName
} else {
$NewEvent.User = $NewEvent.User.ToString() + ' (Undetermined AD account)'
}
} else {
if ($EventLog.UserId -eq 'S-1-5-19') {
$NewEvent.User = 'NT Authority (LocalService)'
} elseif ($EventLog.UserId -eq 'S-1-5-18') {
$NewEvent.User = 'System'
} else {
$NewEvent.User = $NewEvent.User.ToString() + ' (Undetermined local account)'
}
}
$NewEvent
}
#Get counts of event level types
$CriticalCount = ($EventsReformat | Where-Object -Property Level -EQ 'Critical')
if (($null -ne $CriticalCount) -and ($null -eq $CriticalCount.Count)) {
$CriticalCount = 1
} else {
$CriticalCount = $CriticalCount.Count
}
$ErrorCount = ($EventsReformat | Where-Object -Property Level -EQ 'Error')
if (($null -ne $ErrorCount) -and ($null -eq $ErrorCount.Count)) {
$ErrorCount = 1
} else {
$ErrorCount = $ErrorCount.Count
}
$WarningCount = ($EventsReformat | Where-Object -Property Level -EQ 'Warning')
if (($null -ne $WarningCount) -and ($null -eq $WarningCount.Count)) {
$WarningCount = 1
} else {
$WarningCount = $WarningCount.Count
}
$InfoCount = ($EventsReformat | Where-Object -Property Level -EQ 'Information')
if (($null -ne $InfoCount) -and ($null -eq $InfoCount.Count)) {
$InfoCount = 1
} else {
$InfoCount = $InfoCount.Count
}
$RebootEventCount = $CriticalCount + $ErrorCount + $WarningCount + $InfoCount
#Set exit depending on types of events found
if (($CriticalCount -gt 0) -or ($ErrorCount -gt 0)) {
$LASTEXITCODE = 2
} elseif ($WarningCount -gt 0) {
$LASTEXITCODE = 1
} elseif ($InfoCount -gt 0) {
$LASTEXITCODE = 0
} elseif ($RebootEventCount -lt 1) {
$LASTEXITCODE = 0
} else {
$LASTEXITCODE = 3
}
#Adjust exit code based on uptime
if ($ActualUptime -lt $WarningUptime) {
$LASTEXITCODE = 1
if (($CriticalCount -gt 0) -or ($Error.Count -gt 0)) {
$LASTEXITCODE = 2
}
if ($ActualUptime -lt $CriticalUptime) {
$LASTEXITCODE = 2
}
} elseif ($ActualUptime -ge $WarningUptime) {
$LASTEXITCODE = $LASTEXITCODE
} else {
$LASTEXITCODE = 3
}
#Output
$UptimeMessage = $UptimeMessage + " with $RebootEventCount reboot events in the past $MaxEventAge hours"
if ($LASTEXITCODE -eq 0) {
'OK: ' + $UptimeMessage
} elseif ($LASTEXITCODE -eq 1) {
'WARNING: ' + $UptimeMessage
} elseif ($LASTEXITCODE -eq 2) {
'CRITICAL: ' + $UptimeMessage
} else {
'UNKNOWN: ' + $UptimeMessage
}
if ($Error.Count -gt 0) {
'UNKNOWN: Some other issue in script'
$LASTEXITCODE = 3
}
Write-Output "Warning trigger: $WarningUptime hours"
Write-Output "Critical trigger: $CriticalUptime hours"
Write-Output "Max event age: $MaxEventAge hours"
if ($Null -ne $EventsReformat) {
Write-Output '
=====
Events
====='
Write-Output $EventsReformat
}
exit $LASTEXITCODE