我可以传递一个函数并在 PSJobs 脚本块中调用它,并接收一个 return 值吗?
Can I pass a function and call it in a PSJobs scriptblock, and receive a return value?
当我 运行 找到工作 | receive-job -keep 我没有得到任何结果,也无法验证我的函数是否已通过并正常工作。我可以将这样的函数传递给 psjob 吗?之后如何捕获 return 值?
$servers = @("xxxx", "xxxx")
$jobs = New-Object System.Collections.ArrayList;
foreach ($server in $servers)
{
$jobName = $server + "_job";
$scriptBlock =
{
param($server)
param($portNumber)
Function testPort ($server, $portNumber)
{
$testPort = New-Object System.Net.Sockets.TCPClient # -ArgumentList $server, 3389;
$testPort.SendTimeout = 3;
try
{
$testPort.Connect($server, 3389);
}
catch
{
#do nothing;
}
$result = $testPort.Connected;
$testPort.Close();
return $result;
}
testPort -server $server -portNumber 3389; sleep 10;
}
$portNumber = "3389";
#Start-Job -Name $jobName -ScriptBlock {$scriptBlock} -ArgumentList $server, $portNumber;
$jobs.Add((Start-Job -Name $jobName -ScriptBlock {$scriptBlock} -ArgumentList $server, $portNumber | Out-Null));
}
$jobsReturnValues = New-Object System.Collections.ArrayList;
foreach ($job in $jobs)
{
$jobsReturnValues.Add(($job | Wait-Job | Receive-Job | Out-Null));
}
如果您转到 docs,您会看到有一系列可与 Jobs 一起使用的 cmdlet。
$job = Start-Job...
$data = $job | Wait-Job | Receive-Job
Wait-Job
等待作业,直到它不处于 Running
状态。
Receive-Job
returns 作业的输出。
更新
更新代码后,我可以说以下内容:
Start-Job -Name $jobName -ScriptBlock {$scriptBlock} -ArgumentList $server, $portNumber | Out-Null
为什么要将它导入 Out-Null
?这使得 Start-Job
的输出消失,并且您仅将空值附加到 $job
中。取出管道进入Out-Null
。 Start-Job
returns 一个 System.Management.Automation.PSRemotingJob
对象,您需要它以便稍后引用它。
另外,你在这里做同样的事情:$job | Wait-Job | Receive-Job | Out-Null
。这会使作业的输出消失。
Start-Job -Name $jobName -ScriptBlock {$scriptBlock}
需要
Start-Job -Name $jobName -ScriptBlock $scriptBlock
基本上,您使用第一种方法将脚本块放入脚本块中。
我认为您应该首先使用一些基本示例进行测试,直到您掌握作业的工作原理。
代码几乎没问题,你没有太多错误。主要问题是 Out-Null
的使用,-ScriptBlock {$scriptBlock}
上的 { }
和 param( )
块在您的函数中定义了 2 次。我也对你的功能做了一点修改:)
$servers = @('google.com','twitter.com')
$jobs = New-Object System.Collections.ArrayList;
$testPort = 80
foreach ($server in $servers)
{
$jobName = $server + "_job";
$scriptBlock = {
param(
[string]$server,
[int]$portNumber
)
Function testPort ($server, $portNumber)
{
$testPort = New-Object System.Net.Sockets.TCPClient # -ArgumentList $server, 3389;
$testPort.SendTimeout = 3;
try
{
$testPort.Connect($server, $portNumber);
}
catch
{
#do nothing;
}
$result = $testPort.Connected;
$testPort.Close();
[pscustomobject]@{
ServerName = $server
Port = $portNumber
TestConnection = $result
}
}
testPort -server $server -portNumber $portNumber
}
$jobs.Add((Start-Job -Name $jobName -ScriptBlock $scriptBlock -ArgumentList $server, $testPort)) > $null;
}
$jobsReturnValues = New-Object System.Collections.ArrayList;
foreach ($job in $jobs)
{
$jobsReturnValues.Add(($job | Receive-Job -Wait -AutoRemoveJob)) > $null;
}
看起来像这样:
PS C:\> $jobsReturnValues|select * -ExcludeProperty RunspaceID|ft
ServerName Port TestConnection
---------- ---- --------------
google.com 80 True
twitter.com 80 True
当我 运行 找到工作 | receive-job -keep 我没有得到任何结果,也无法验证我的函数是否已通过并正常工作。我可以将这样的函数传递给 psjob 吗?之后如何捕获 return 值?
$servers = @("xxxx", "xxxx")
$jobs = New-Object System.Collections.ArrayList;
foreach ($server in $servers)
{
$jobName = $server + "_job";
$scriptBlock =
{
param($server)
param($portNumber)
Function testPort ($server, $portNumber)
{
$testPort = New-Object System.Net.Sockets.TCPClient # -ArgumentList $server, 3389;
$testPort.SendTimeout = 3;
try
{
$testPort.Connect($server, 3389);
}
catch
{
#do nothing;
}
$result = $testPort.Connected;
$testPort.Close();
return $result;
}
testPort -server $server -portNumber 3389; sleep 10;
}
$portNumber = "3389";
#Start-Job -Name $jobName -ScriptBlock {$scriptBlock} -ArgumentList $server, $portNumber;
$jobs.Add((Start-Job -Name $jobName -ScriptBlock {$scriptBlock} -ArgumentList $server, $portNumber | Out-Null));
}
$jobsReturnValues = New-Object System.Collections.ArrayList;
foreach ($job in $jobs)
{
$jobsReturnValues.Add(($job | Wait-Job | Receive-Job | Out-Null));
}
如果您转到 docs,您会看到有一系列可与 Jobs 一起使用的 cmdlet。
$job = Start-Job...
$data = $job | Wait-Job | Receive-Job
Wait-Job
等待作业,直到它不处于 Running
状态。
Receive-Job
returns 作业的输出。
更新
更新代码后,我可以说以下内容:
Start-Job -Name $jobName -ScriptBlock {$scriptBlock} -ArgumentList $server, $portNumber | Out-Null
为什么要将它导入 Out-Null
?这使得 Start-Job
的输出消失,并且您仅将空值附加到 $job
中。取出管道进入Out-Null
。 Start-Job
returns 一个 System.Management.Automation.PSRemotingJob
对象,您需要它以便稍后引用它。
另外,你在这里做同样的事情:$job | Wait-Job | Receive-Job | Out-Null
。这会使作业的输出消失。
Start-Job -Name $jobName -ScriptBlock {$scriptBlock}
需要
Start-Job -Name $jobName -ScriptBlock $scriptBlock
基本上,您使用第一种方法将脚本块放入脚本块中。
我认为您应该首先使用一些基本示例进行测试,直到您掌握作业的工作原理。
代码几乎没问题,你没有太多错误。主要问题是 Out-Null
的使用,-ScriptBlock {$scriptBlock}
上的 { }
和 param( )
块在您的函数中定义了 2 次。我也对你的功能做了一点修改:)
$servers = @('google.com','twitter.com')
$jobs = New-Object System.Collections.ArrayList;
$testPort = 80
foreach ($server in $servers)
{
$jobName = $server + "_job";
$scriptBlock = {
param(
[string]$server,
[int]$portNumber
)
Function testPort ($server, $portNumber)
{
$testPort = New-Object System.Net.Sockets.TCPClient # -ArgumentList $server, 3389;
$testPort.SendTimeout = 3;
try
{
$testPort.Connect($server, $portNumber);
}
catch
{
#do nothing;
}
$result = $testPort.Connected;
$testPort.Close();
[pscustomobject]@{
ServerName = $server
Port = $portNumber
TestConnection = $result
}
}
testPort -server $server -portNumber $portNumber
}
$jobs.Add((Start-Job -Name $jobName -ScriptBlock $scriptBlock -ArgumentList $server, $testPort)) > $null;
}
$jobsReturnValues = New-Object System.Collections.ArrayList;
foreach ($job in $jobs)
{
$jobsReturnValues.Add(($job | Receive-Job -Wait -AutoRemoveJob)) > $null;
}
看起来像这样:
PS C:\> $jobsReturnValues|select * -ExcludeProperty RunspaceID|ft
ServerName Port TestConnection
---------- ---- --------------
google.com 80 True
twitter.com 80 True