我有一个用 Powershell 编写的自定义部署脚本。此脚本需要更新远程计算机上的服务,因此,它首先需要停止该服务才能修改可执行文件。
这似乎是个问题。
要同步停止服务,我可以使用net stop servicename
或stop-service servicename
。问题是这两个命令仅限于本地机器。
要停止远程计算机上的服务,我知道我可以使用该sc.exe
程序:
sc.exe \\computername stop servicename
但这是异步的,所以我实际上不能使用它(嗯,sleep 5
似乎可以做到,但那很肮脏)。
如何使用 Powershell 同步停止远程服务?
答案1
获取服务返回服务控制器对象,然后您可以使用它来操作服务。无论是本地还是远程都没关系。我有以下脚本来停止后台处理程序(打印后台处理程序)服务并等待它停止,最多 5 秒钟。我刚刚将 -Name 参数添加到 Get-Service,我能够在远程服务器上停止后台处理程序。
笔记:就我的情况而言,两台服务器都是 Server 2008 R2。您的情况可能会有所不同。
Set-StrictMode -Version "2.0"
[System.ServiceProcess.ServiceController]$service = Get-Service -Name "Spooler" -ComputerName "remote_server.domain.com"
[int]$waitCount = 5
do
{
$waitCount--
switch($service.Status)
{
{ @(
[System.ServiceProcess.ServiceControllerStatus]::ContinuePending,
[System.ServiceProcess.ServiceControllerStatus]::PausePending,
[System.ServiceProcess.ServiceControllerStatus]::StartPending,
[System.ServiceProcess.ServiceControllerStatus]::StopPending) -contains $_ }
{
# A status change is pending. Do nothing.
break;
}
{ @(
[System.ServiceProcess.ServiceControllerStatus]::Paused,
[System.ServiceProcess.ServiceControllerStatus]::Running) -contains $_ }
{
# The service is paused or running. We need to stop it.
$service.Stop()
break;
}
[System.ServiceProcess.ServiceControllerStatus]::Stopped
{
# This is the service state that we want, so do nothing.
break;
}
}
# Sleep, then refresh the service object.
Sleep -Seconds 1
$service.Refresh()
} while (($service.Status -ne [System.ServiceProcess.ServiceControllerStatus]::Stopped) -and ($waitCount -gt 0))
还有设置服务它将接受计算机名称参数,但如果该服务具有依赖服务,它似乎无法停止该服务。
答案2
PowerShell 2 添加了很多用于访问远程计算机的功能。
以下是一些有用的 cmdlet(来自 PowerShell 的信息get-help
):
Enter-PSSession
:
摘要
开始与远程计算机的交互式会话。描述
Enter-PSSession cmdlet 启动与单个远程计算机的交互式会话。在会话期间,您键入的命令将在远程计算机上运行,就像您直接在远程计算机上键入一样。您一次只能有一个交互式会话。通常,使用 ComputerName 参数指定远程计算机的名称。但是,也可以使用通过 New-PSSession 创建的会话作为交互式会话。
要结束交互式会话并断开与远程计算机的连接,请使用 Exit-PSSession cmdlet,或键入“exit”。
New-PSSession
:
摘要
创建与本地或远程计算机的持久连接。描述
New-PSSession cmdlet 在本地或远程计算机上创建 Windows PowerShell 会话 (PSSession)。创建 PSSession 时,Windows PowerShell 会与远程计算机建立持久连接。使用 PSSession 运行多个共享数据(例如函数或变量值)的命令。要在 PSSession 中运行命令,请使用 Invoke-Command cmdlet。要使用 PSSession 直接与远程计算机交互,请使用 Enter-PSSession cmdlet。有关详细信息,请参阅 about_PSSessions。
Invoke-Command
:
摘要
在本地和远程计算机上运行命令。描述
Invoke-Command cmdlet 在本地或远程计算机上运行命令并返回命令的所有输出,包括错误。使用单个 Invoke-Command 命令,您可以在多台计算机上运行命令。要在远程计算机上运行单个命令,请使用 ComputerName 参数。要运行一系列共享数据的相关命令,请在远程计算机上创建 PSSession(持久连接),然后使用 Invoke-Command 的 Session 参数在 PSSession 中运行命令。
答案3
我会调查类似的事情执行程序。它将net stop
在远程机器上执行,从而获得同步部分,但它可以远程完成(毕竟这是 PsExec 的重点)。