【问题标题】:Running powershell scripts from Python without reimporting modules on every run从 Python 运行 powershell 脚本,而无需在每次运行时重新导入模块
【发布时间】:2015-07-22 06:13:09
【问题描述】:

我正在创建一个 Python 脚本,它调用需要导入 Active-Directory 模块的 Powershell 脚本script.ps1。但是,每次我使用 check_output('powershell.exe -File script.ps1') 它需要为每次运行 script.ps1 重新导入活动目录模块,这使得运行时间比它需要的时间长约 3 秒。

我当时想知道,是否有办法保持 Powershell 模块的导入(就好像它是直接从 Powershell 运行,而不是从 Python 运行一样),以便我可以使用类似

if(-not(Get-Module -name ActiveDirectory)){
  Import-Module ActiveDirectory
}

加快执行时间。

【问题讨论】:

  • 什么版本的 PowerShell?
  • 你可以让“主机配置文件”在加载 powershell 时加载它
  • @Luke 不会节省任何时间,这就是这样做的既定目的。您只需更改 where 每次导入模块。
  • Python 在做什么?你能把它全部转换成 Powershell 吗?
  • @Luke Python 正在托管一个 Flask Web 应用程序,用于为用户搜索活动目录信息。因为我当前的解决方案需要在每次运行时重新导入 ActiveDirectory 模块,所以搜索速度非常慢。

标签: python powershell subprocess powershell-2.0


【解决方案1】:

此解决方案使用 PowerShell 远程处理,并且要求您远程连接的机器具有 ActiveDirectory 模块,并且要求进行远程连接的机器(客户端)是 PowerShell 版本 3 或更高版本。

在本例中,机器远程访问自身。

这将是您的 script.ps1 文件:

#requires -Version 3.0

$ExistingSession = Get-PSSession -ComputerName . | Select-Object -First 1

if ($ExistingSession) {
    Write-Verbose "Using existing session" -Verbose
    $ExistingSession | Connect-PSSession | Out-Null
} else {
    Write-Verbose "Creating new session." -Verbose
    $ExistingSession = New-PSSession -ComputerName . -ErrorAction Stop
    Invoke-Command -Session $ExistingSession -ScriptBlock { Import-Module ActiveDirectory }
}

Invoke-Command -Session $ExistingSession -ScriptBlock {
    # do all your stuff here
}

$ExistingSession | Disconnect-PSSession | Out-Null

它利用了 PowerShell 对断开连接会话的支持。每次使用 PowerShell.exe 时,您最终都会连接到已加载 ActiveDirectory 模块的现有会话。

完成所有调用后,您应该销毁会话:

Get-PSSession -ComputerName . | Remove-PSSession

这是在每次运行时使用单独的 powershell.exe 调用进行测试的。

我确实想知道您延迟的原因是否实际上是因为加载了 ActiveDirectory 模块,或者是否至少有很大一部分延迟仅仅是由于必须加载 PowerShell.exe 本身造成的。

【讨论】:

  • 刚刚编辑的最后一行代码错过了我的原始副本/粘贴;这很重要!如果您不断开会话,那么它将在本地会话关闭时被删除。
  • 很好的横向思维。 +1
  • 遗憾的是,这不适用于 Powershell v2,但它是一个很好的解决方案。我想知道是否可以通过使用 Python a la pexpect 重新连接到现有的 Powershell 会话来在 Python 中做类似的事情(遗憾的是,这在 Windows 上不起作用)
  • 谢谢gymbrall。 @LukeD,我认为在python中没有办法做到这一点。由于您要使用 powershell,因此您的选择是有限的。我不知道这个脚本有多重要,也不知道它在您的组织中有多大的一部分,但我可能会考虑在 ASP.NET 中编写一个 Web 服务,它公开特定的 REST API 调用并在幕后与 AD 对话(即使它通过运行空间使用 PowerShell 这样做)。此时,您可以使用 python( 或其他任何东西)直接使用 REST API。听起来可能有点矫枉过正,但它有优势。
  • 我也许可以做一些类似你所拥有的事情,但通过 ssh 重新连接到会话。同时,我会将此标记为答案,因为我的情况有点极端。
猜你喜欢
  • 2017-12-28
  • 1970-01-01
  • 2022-01-24
  • 1970-01-01
  • 1970-01-01
  • 2021-12-29
  • 2011-12-19
  • 1970-01-01
相关资源
最近更新 更多