VBS: Kontrollierter Reboot v. Windows-Systemen

Die meisten Anwender an den 105 Workstations, die zu administrieren ich bei uns im Klinikum die Ehre habe, gehen nicht gerade pfleglich mit dem System um. Dazu gehört auch ein kontrollierter täglicher Reboot bei Windows-Systemen, einfach um viele Klippen zu umschiffen. Ich habe mittlerweile schon die krudesten Fehler gesehen, die daraus resultieren, daß ein System einfach eine Woche durchgelaufen ist (und in der Zeit exzessiv damit gearbeitet wurde). Die Ursachen müssen in den meisten Fällen nicht einmal Memory Holes im Windows-OS sein. Beispielsweise werden im Rahmen von Softwareverteilungen viele Updates bei Anwendungen durch Reboots bzw. bei Neuanmeldung eines Benutzers am System ausgelöst. Und wenn ein System niemals rebootet, bekommt es auch niemals Updates.

Aus diesem Grund habe ich mir ein kleines VBS gebastelt, welches folgende Aufgabe erledigt: Prüfe die aktuelle Uhrzeit des Systems und die Uptime. Liegt ersteres zwischen 00 und 06 Uhr und ist letzteres bei größer als 24 Stunden, so frage den Anwender, ob rebootet werden darf. Klickt der Anwender auf ‘Nein’ (weil er z.B. gerade bei einem sehr wichtigen Arbeitsschritt ist), so nerve frage ihn in Abständen von zehn Minuten immer wieder (auch wenn inzwischen 12 Uhr sein sollte). Sollte der Anwender die Dialogbox für 15 Minuten nicht beantworten, so reboote eigenständig.
Ist der Zeitpunkt oder die Uptime nicht wie oben angegeben, so soll natürlich nichts gemacht werden.
Die Reboot-Vorgang macht dasselbe wie ein “forced” Reboot, wie er z.B. nach Windows-Updates ausgelöst wird, wenn man sagt “Jetzt neu starten”. Ein “unforced” Reboot hängt sich sehr oft noch an offenen Programmen auf.

Ich habe vorher im Netz geschaut, ob es schon vorhandene Scripts zu diesem Thema gibt, aber scheinbar wird dieses Problem immer durch Zusatzprogramme, die sich in die TrayBar legen, gelöst. Für mich ist jede zusätzliche Anwendung ein zusätzlicher Fehlerfall, darum vermeide ich dies am liebsten. Außerdem wird auf diesem Weg kein Speicher benötigt.
Apropos Speicher: Die regelmäßige Überprüfung geschieht aus Speicherspargründen per Cronjob Scheduled Task. Den Befehl, um diesen Taks zu erstellen, hänge ich unten mit an. Man kann natürlich auch dem Script eine Endlosschleife verpassen, und die Überprüfung auch so abfackeln. Aber bei meinem Arbeitsrechner benötigt die wscript-Umgebung 7 MB im Speicher, und bei einer Workstation mit 4 GB Memory sogar satte 100 MB (Warum?!).
VBS-Script:

Const quitProgram = 0
Const wshYes = 6
Const wshNo = 7
Const wshYesNoDialog = 4
Const wshQuestionMark = 32
strComputer = “.”

Function ConvertTime(seconds)
ConvSec = seconds Mod 60
ConvMin = (seconds Mod 3600) \ 60
ConvHour = (seconds Mod (3600 * 24)) \ 3600
ConvDays = seconds \ (3600 * 24)
ConvertTime = ConvDays & ” days ” & ConvHour & ” hours ” & ConvMin & ” minutes ” & ConvSec & ” seconds ”
End Function

Set objShell = CreateObject(“Wscript.Shell”)

On Error Resume Next

‘ Systemzeit ermitteln, Reboot soll nur in den Nachtstunden ausgelöst werden können!
Set objWMIService = GetObject(“winmgmts:\\” & strComputer & “\root\cimv2”)
Set colItems = objWMIService.ExecQuery(“Select * From Win32_LocalTime”)

For Each objItem in colItems
actHour = objItem.Hour
Next

If actHour < 6 Then ' Uptime des Systems ermitteln, ist Reboot schon notwendig? strQuery = "select * from Win32_PerfRawData_PerfOS_System" Set colObjects = objWMIService.ExecQuery(strQuery) For Each objWmiObject In colObjects intPerfTimeStamp = objWmiObject.Timestamp_Object intPerfTimeFreq = objWmiObject.Frequency_Object intCounter = objWmiObject.SystemUpTime Next ' Calculation in seconds: iUptimeInSec = (intPerfTimeStamp - intCounter)/intPerfTimeFreq 'WScript.Echo "Uptime in seconds: " & iUptimeInSec \ 1 ' convert the seconds 'sUptime = ConvertTime(iUptimeInSec) 'WScript.Echo "Uptime: " & sUptime ' Uptime ist groesser als 24 Stunden! Meldung aufpoppen lassen. If iUptimeInSec > 86400 Then

intReturn = wshNo
Do Until intReturn = wshYes
intReturn = objShell.Popup(“Aus Wartungsgründen ist ein Neustart erforderlich. Kann dieser Neustart jetzt durchgeführt werden? Achtung: Wird diese Dialogbox nicht innerhalb von 10 Minuten mit ‘Nein’ geschlossen, wird der Neustart automatisch ausgelöst!”, _
600, “Neustart aus Wartungsgründen”, wshYesNoDialog + wshQuestionMark)

If intReturn = wshYes Then
Set OpSysSet = GetObject(“winmgmts:{(Shutdown)}!\\” & strComputer & “\root\cimv2”).ExecQuery _
(“select * from Win32_OperatingSystem where Primary=true”)

for each OpSys in OpSysSet
OpSys.Win32Shutdown(6) ‘ Forced Reboot
next
ElseIf intReturn = wshNo Then
Wscript.Echo “Neustart verzögert. Diese Abfrage wird in zehn Minuten erneut erscheinen.”
Wscript.sleep(600000)
Else
Set OpSysSet = GetObject(“winmgmts:{(Shutdown)}!\\” & strComputer & “\root\cimv2”).ExecQuery _
(“select * from Win32_OperatingSystem where Primary=true”)

for each OpSys in OpSysSet
OpSys.Win32Shutdown(6) ‘ Forced Reboot
next
End If

Loop

End If

End If

Befehl für Einrichtung des Task:

schtasks /Create /tn “Wartungsreboot” /tr “[PathToScript]” /sc STÜNDLICH /sd 19/05/2009 /st 12:06:00 /ru SYSTEM

Keine Kommentare

Schreibe einen Kommentar

Deine E-Mail-Adresse wird niemals weitergegeben.Erforderliche Felder sind mit einem * markiert.