如何在重启后检测Windows服务器是否可用?

问题描述:

我想使用任务计划程序或类似工具来远程重启服务器并等待服务器重新启动,从而自动执行Windows 2000+服务器重启过程。我可以发出shutdownpsshutdown来远程重新启动,但我希望比sleep更好的等待它回来。我需要确认它在n分钟内恢复在线或发生错误。通过'回到线上',我想验证更多的不仅仅是它可以ping通,但也许它的RFC服务正在响应或一些其他确定的重要标志。如何在重启后检测Windows服务器是否可用?

我更喜欢NT脚本的方法,但我不排除编写自定义工具来做到这一点。

任何想法?

您的远程重启脚本可能启动服务器,等待n分钟,然后查询您的RFC服务。你也可以在服务器上有一个本地脚本来做同样的事情。

您可以使用psservice来查询RFC或后台打印程序服务的状态。后台打印程序通常是最后一个启动的服务之一。您可以使用如下语法:

psservice \\someothermachine query spooler 

一旦服务运行,就会返回类似这样的内容。

 
SERVICE_NAME: Spooler                    
DISPLAY_NAME: Print Spooler                  
Manages all local and network print queues and controls all printing jobs. If this service is stop 
ped, printing on the local machine will be unavailable. If this service is disabled, any services 
that explicitly depend on it will fail to start.             
     GROUP    : SpoolerGroup               
     TYPE    : 110 WIN32_OWN_PROCESS INTERACTIVE_PROCESS        
     STATE    : 4 RUNNING                
           (STOPPABLE,NOT_PAUSABLE,ACCEPTS_SHUTDOWN)       
     WIN32_EXIT_CODE : 0 (0x0)                
     SERVICE_EXIT_CODE : 0 (0x0)                
     CHECKPOINT  : 0x0                 
     WAIT_HINT   : 0x0                

如果其他机器没有准备好,你就会得到这样

Unable to connect to \\someothermachine:                 
The RPC server is unavailable.

您可以查询一些核心服务,看它是否已经启动:

sc "\\server_name" query EventSystem 

使用nmap获取机器上的开放服务列表并解析结果以确保您需要的是活动的。确保不需要需要的是而不是有效。

这里的关键是我需要编写脚本。是否有更简洁的方式从psservice/sc query中提取服务状态?我可以将它输入到findstr "RUNNING",但是有一个更好的方法。

使用VBScript(WSH),您可以使用.state属性对其进行检查。此脚本显示,在不同的应用中使用的财产,但应有助于说明这个思想:

http://www.robvanderwoude.com/vbstech_proc_service.html

这方面的工作了一段时间后,我想出了下面的VBScript。随意评论/改进。

' 
' Remotely reboot a server and 
' wait for server to come back up. 
' 
' Usage: cscript /nologo /E:VBScript RebootWait.vbs <Server Name> 
' 
' Shawn Poulson, 2008.09.11 
' 

' 
' Get server name from command line 
' 
If WScript.Arguments.Count <> 1 Then 
    ShowUsage() 
    WScript.Quit(1) 
End If 

ServerName = WScript.Arguments(0) 

' 
' Verify server is currently up 
' 
WScript.StdOut.WriteLine Now & ": Verify server '" & ServerName & "' is currently up..." 
If Not IsAvailable(ServerName) Then 
    WScript.StdOut.WriteLine "Error: Server is down. Reboot aborted!" 
    WScript.Quit(1) 
End If 
WScript.StdOut.WriteLine Now & ": Server is up." 

' 
' Reboot server 
' 
WScript.StdOut.WriteLine Now & ": Rebooting server '" & ServerName & "'..." 
RebootStatus = RebootServer(ServerName) 
If RebootStatus < 0 Then 
    WScript.StdOut.WriteLine "Error: Reboot returned error " & RebootStatus 
    WScript.Quit(1) 
End If 
WScript.StdOut.WriteLine Now & ": Reboot command was successful" 

' 
' Wait for server to come down 
' 
WScript.StdOut.Write Now & ": Waiting for server '" & ServerName & "' to go down..." 
WaitCount = 0 
Do While IsAvailable(ServerName) 
    WaitCount = WaitCount + 1 
    If WaitCount > 60 Then ' 5 min timeout 
     WScript.StdOut.WriteLine "Error: Timeout waiting for server to come down!" 
     WScript.Quit(1) 
    End If 
    WScript.StdOut.Write(".") 
    WScript.Sleep(5000) 
Loop 
WScript.StdOut.WriteLine "Success!" 
WScript.StdOut.WriteLine Now & ": Server is down." 

' 
' Wait for server to come back up 
' 
WScript.StdOut.Write Now & ": Waiting for server '" & ServerName & "' to come back up..." 
WaitCount = 0 
Do While Not IsAvailable(ServerName) 
    WaitCount = WaitCount + 1 
    If WaitCount > 240 Then ' 20 min timeout 
     WScript.StdOut.WriteLine "Error: Timeout waiting for server to come back up!" 
     WScript.Quit(1) 
    End If 
    WScript.StdOut.Write(".") 
    WScript.Sleep(5000) 
Loop 
WScript.StdOut.WriteLine "Success!" 
WScript.StdOut.WriteLine Now & ": Server is back up after reboot." 

' 
' Success! 
' 
WScript.Quit(0) 


Sub ShowUsage() 
    WScript.Echo "Usage: " & WScript.ScriptName & " <Server name>" 
End Sub 

' Returns: 
' 1 = Successfully issued reboot command 
' -2 = Could not reach server 
' -3 = Reboot command failed 
Function RebootServer(ServerName) 
    Dim OpSystem 
    On Error Resume Next 
    For Each OpSystem in GetObject("winmgmts:{(Shutdown)}!\\" & ServerName & "\root\CIMV2").ExecQuery("select * from Win32_OperatingSystem where Primary=true") 
     On Error GoTo 0 

     If IsObject(OpSystem) Then 
     ' Invoke forced reboot 
     If OpSystem.Win32Shutdown(6, 0) = 0 Then 
      ' Success 
      RebootServer = 1 
     Else 
      ' Command failed 
      RebootServer = -3 
     End If 

     Else 
     RebootServer = -2 

     End If 
    Next 
End Function 

' Return True if available 
Function IsAvailable(ServerName) 
    ' Use Windows RPC service state as vital sign 
    IsAvailable = (GetServiceState(ServerName, "RpcSs") = "Running") 
End Function 

' Return one of: 
' Stopped, Start Pending, Stop Pending, 
' Running, Continue Pending, Pause Pending, 
' Paused, Unknown 
Function GetServiceState(ServerName, ServiceName) 
    Dim Service 
    On Error Resume Next 
    Set Service = GetObject("winmgmts:\\" & ServerName & "\root\CIMV2:Win32_Service='" & ServiceName & "'") 
    On Error GoTo 0 
    If IsObject(Service) Then GetServiceState = Service.State 
End Function 
+0

不错!我测试了这一点,它可以像广告一样工作。您需要使用在远程服务器上拥有管理权限的帐户运行;提供这种信用的能力会很好。 – quux 2008-11-03 19:56:34