【问题标题】:Powershell - How to call two functions using Start-Job within a function and pass a list of computer names?Powershell - 如何在函数中使用 Start-Job 调用两个函数并传递计算机名称列表?
【发布时间】:2020-04-14 20:12:13
【问题描述】:

我有一个导入模块 \path\to\functions.psm1 的主脚本, 我在主脚本中调用了一个名为:Run_Scans $ServerList 的函数,它来自functions.psm1, 从 Run_Scans 我尝试使用 Start-Job 调用另外两个函数(Scan1、Scan2),但无法让服务器变量传递给其他函数。我尝试了几种不同的方法,无论是作业失败还是完成,但服务器列表确实通过了。任何帮助将不胜感激。

#This is from the main script#
Import-Module "path\to\Functions.psm1"
Run_Scans $ServerList

#This is from functions.psm1#
Function Run_Scans ($Servers){
#Start-Job -Name 'Scan1' -ScriptBlock {Run_Scan1 $using:Servers}
#Start-Job -Name 'Scan2' -ScriptBlock {Run_Scan2 $using:Servers}

$Scan = {
    param ($Servers)
    Run_Scan1 $Servers
    Run_Scan2 $Servers
}
Start-Job -ScriptBlock $Scan -ArgumentList $Servers
}

Function Run_Scan1 ($Servers){
    scan code
}
Function Run_Scan2 ($Servers){
    scan code
}

更新:

我能够做到以下几点:

$ServerList = "Serv1","Serv2","Serv3"
Start-Job -InitializationScript $Initialization -ScriptBlock {param($servers) echo $servers} -args (,$servers)

Receive-Job 

输出:

Serv1

Serv2

Serv3

但是当我尝试合并调用函数时:

$Initialization = [scriptblock]::Create("Import-Module -Name 'Pathto\Functions.psm1'")
Start-Job -InitializationScript $Initialization -ScriptBlock {param($servers) Run_Scan1 $servers} -args (,$servers)

我收到以下错误:

术语“Run_Scan1”未被识别为 cmdlet、函数、脚本文件或可运行程序的名称。

无法索引到空数组。

最终解决方案:

Start-Job -InitializationScript {Import-Module "Pathto\Functions.ps1"}  -ScriptBlock { param($Servers) Run_Scan1 $Servers } -ArgumentList (,$servers)

【问题讨论】:

  • 后台作业在一个独立的 PowerShell 子进程 的会话中运行,该进程对调用者的状态一无所知,因此 Run_Scan1 和 Run_Scan2 函数不会'不能在那里。除此之外,如果 $Servers 是一个数组,您必须将其作为 -ArgumentList (, $Servers) 传递,如 js2010 的答案所示。
  • 如果您使用 -InitializationScript 导入模块不会使该功能可用吗?
  • 是的,应该可以;请注意,在 PS 6 中,后台作业在 $HOME\Documents 中运行,而不是在调用者的当前目录中,因此请务必在 Pathto\Functions.psm1 中考虑这一点 - 请参阅 this answer。
  • 感谢您的帮助

标签: function powershell start-job


【解决方案1】:

对于数组,我推荐使用范围。作业不能很好地处理数组参数。如果有,请使用 start-threadjob。

$servers = echo server1 server2

start-job { param($servers) $servers } -args $servers | receive-job -wait -auto

server1


start-job { $using:servers } | receive-job -wait -auto          

server1
server2

或者有这个荒谬的 (, ) 解决方法:

start-job { param($servers) $servers } -args (,$servers) | receive-job -wait -auto

server1
server2

【讨论】:

  • 很好(尽管 OP 的更大问题是后台作业中的功能不可用)。但是请注意,这种行为 - 尽管令人惊讶并且需要一个模糊的解决方法 - 是设计使然,并且适用于通过数组值 -ArgumentList 参数接受传递参数的所有 cmdlet - 请参阅 this answer。
  • 也许您也可以将解决方案的另一部分添加到您的答案中,即需要导入具有在作业中调用的功能的模块;克里斯已将其编辑到他的问题中,但最好将其作为答案的一部分:Start-Job -InitializationScript {Import-Module "Pathto\Functions.ps1"} -ScriptBlock { param($Servers) Run_Scan1 $Servers } -ArgumentList (,$servers)
猜你喜欢
  • 2012-03-12
  • 2014-06-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-30
  • 1970-01-01
  • 2020-01-05
  • 2023-03-21
  • 2017-10-08
相关资源
最近更新 更多