在Powershell中,我想学习将变量调用到启动作业的最佳方法,这样我就不必编辑每个服务器的脚本,因为它将根据我放置脚本的客户端而具体。
$Servername = 'Server1'
$pingblock = {
pathping $servername | Out-File C:clientPSServerPing.TXT
}
start-job $pingblock
当我运行上面的代码时,我只是得到一个带有帮助的文件,就好像我忘记了指定$servername一样。
为了用PSv3+替代方案补充Keith Hill的有用答案:
$using:
作用域修饰符可用于引用传递给 Start-Job
的脚本块内调用方作用域中的变量值,作为传递参数的替代方法(默认情况下,作为后台作业执行的脚本块看不到调用方的任何变量或其他定义):
$Servername = 'Server1'
Start-Job { "Target: " + $using:ServerName } | Receive-Job -Wait -AutoRemoveJob
以上结果:
Target: Server1
注意:
相同的技术可用于:
远程执行
Invoke-Command
- 请参阅此问题。Start-ThreadJob
,默认情况下在 PowerShell (Core) v6+ 中可用,可在 Windows PowerShell 中按需安装。ForEach-Object -Parallel
,仅在 PowerShell (Core) v7+ 中可用。
请注意,与
-ArgumentList
(-Args
)一样,传递的只是变量值,而不是变量本身;也就是说,您不能修改调用方的变量。[1]
[1] 但是,基于线程的并发功能 - Start-ThreadJob
和 ForEach-Object Parallel
- 允许间接修改,即如果手头的变量值恰好是(可变).NET 引用类型的实例,例如哈希表,在这种情况下,可以修改变量"指向"的对象(如果它是可变的)。请注意,利用这一点需要额外的、非平凡的努力来使并发修改线程安全,例如通过使用并发(同步)集合 - 请参阅此答案 - 和/或显式锁定单个对象 - 请参阅此答案。
在Start-Job
上使用 -ArgumentList
参数,例如:
Start-Job -Scriptblock {param($p) "`$p is $p"} -Arg 'Server1'
在您的情况下:
$pingblock = {param($servername) pathping $servername | Out-File C:...ServerPing.txt}
Start-Job $pingblock -Arg Server1
其他一些方式,$args和$input。 这也适用于调用命令,我认为它使用相同的机制。 $input方法以意想不到的方式处理数组。
start-job { $args[0] } -args hi | receive-job -wait -auto
hi
echo hi | start-job { $input } | receive-job -wait -auto
hi
echo hi there | start-job { $input.gettype() } | receive-job -wait -auto
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
False False <GetReadEnumerator>d__20 System.Object
对于数组,最好使用 foreach-object (%) 循环,这样它就可以在每个数组项上并行运行。 另请参阅 powershell 7 中的 start-threadjob 或 foreach-object -parallel 。 实际上没有 -throttlelimit 选项来启动作业,因此请谨慎使用。
echo yahoo.com facebook.com |
% { $_ | start-job { test-netconnection $input } } |
receive-job -wait -auto | select * -exclude runspaceid,pssourcejob* | ft
ComputerName RemoteAddress ResolvedAddresses PingSucce
eded
------------ ------------- ----------------- ---------
yahoo.com 74.6.143.25 {74.6.143.25,...} True
facebook.com 31.13.71.36 {31.13.71.36} True