简体   繁体   中英

Powershell pass variable to start-job

within powershell I'd like to learn the best way to call a variable to a start job so I don't have to edit the script for each server as it will be specific based on the client I've placed my script on.

$Servername = 'Server1'
    $pingblock = {
      pathping $servername | Out-File C:\client\PS\ServerPing.TXT
    }
    start-job $pingblock

when I run my code above I just get a file with the help as if I forgot the specify the $servername.

Use the -ArgumentList parameter on Start-Job eg:

Start-Job -Scriptblock {param($p) "`$p is $p"} -Arg 'Server1'

In your case:

$pingblock = {param($servername) pathping $servername | Out-File C:\...\ServerPing.txt}
Start-Job $pingblock -Arg Server1

To complement Keith Hill's helpful answer with a PSv3+ alternative :

The $using: scope modifier can be used to reference the values of variables in the caller's scope inside the script block passed to Start-Job , as an alternative to passing arguments (by default, a script block executed as a background job does not see any of the caller's variables or other definitions):

$Servername = 'Server1'
Start-Job { "Target: " + $using:ServerName } | Receive-Job -Wait -AutoRemoveJob

The above yields:

Target: Server1

Note:

  • The same technique can be used with:

  • Note that, as with -ArgumentList , it is only variable values that are being passed, not the variables themselves ; that is, you cannot modify the caller's variables that way. [1]


[1] However, the thread -based concurrency features - Start-ThreadJob and ForEach-Object Parallel - permit indirect modification, namely if the variable value at hand happens to be an instance of a (mutable) .NET reference type , such as a hashtable. Note that taking advantage of that may require additional, nontrivial effort to make the concurrent modifications thread-safe .

Some other ways, $args and $input. This goes for invoke-command too, which I think uses the same mechanism. The $input method works in an unexpected way with arrays.

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

For arrays, it's probably better to use a foreach-object (%) loop instead, so it runs on each array item in parallel. See also start-threadjob or foreach-object -parallel in powershell 7. There's actually no -throttlelimit option to start-job, so use with care.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM