简体   繁体   中英

Powershell build step, fire and forget?

I am running the following powershell command in a build step using TFS 2018.

Start-Job -ScriptBlock {
    Invoke-Command -FilePath \\MyServer\run.ps1 -ComputerName MyServer -ArgumentList arg1, arg2
}

Since I don't want the script to affect the build step it should simply fire and forget the script. Hence I am using Start-Job . But it seems that once the step is done the process is killed. Is there a way to maintain the process lifetime even though the build step is done or the build process is finished?

Additional information... the powershell script should run on the remote server. The script itself triggers an .exe with parameters.

To simply fire and forget , invoke the script with Invoke-Command -AsJob :

Invoke-Command -AsJob -FilePath \\MyServer\run.ps1 -ComputerName MyServer -Args arg1, arg2
Start-Sleep 1 # !! Seemingly, this is necessary, as @doorman has discovered.
  • This should kick off the script remotely, asynchronously , with a job getting created in the local session to monitor its execution.

    • Caveat : The use of Start-Sleep - possibly with a longer wait time - is seemingly necessary in order for the remote process to be created before the calling script exits, but such a solution may not be fully robust , as there is no guaranteed timing.
  • Since you're not planning to monitor the remote execution, the local session terminating - and along with it the monitoring job - should't matter.

When do you want the script to stop running? You could use a do-while loop and come up with a <condition> that meets your needs.

Start-Job -ScriptBlock {
    do{
        Invoke-Command -FilePath \\MyServer\run.ps1 -ComputerName MyServer -ArgumentList arg1, arg2
        Start-Sleep 2
    }while(<condition>)
}

Alternatively, you could use the condition $true so it executes forever. You will have to stop the job later in the script when you no longer need it.

$job = Start-Job -ScriptBlock {
    do{
        Invoke-Command -FilePath \\MyServer\run.ps1 -ComputerName MyServer -ArgumentList arg1, arg2
        Start-Sleep 2
    }while($true)
}

Stop-Job $job
Remove-Job $job

I've added a Start-Sleep 2 so it doesn't lock up your CPU as no idea what the script is doing - remove if not required.

Why not something like this:

Invoke-Command -Filepath \\MyServer\Run.ps1 -Computername MyServer -Argumentlist Arg1,Arg2 -AsJob
$JobCount = (get-job).Count
Do
{
    Start-Sleep -Seconds 1
    $totalJobCompleted = (get-job | Where-Object {$_.state -eq "Completed"} | Where-Object {$_.Command -like "NAMEOFCOMMAND*"}).count
}
Until($totalJobCompleted -ge $JobCount)

@doorman - PowerShell is natively a single threaded application. In almost all cases, this is a huge benefit. Even forcing multiple threads, you can see the child threads are always dependent on the main thread. If this wasn't the case, it would be very easy to create memory leaks. This is almost always a good thing as when you close the main thread, .Net will clean up all the other threads you may have forgotten about for you. You just happened to run across a case where this behaviour is not beneficial to your situation.

There are a few ways to tackle the issue, but the easiest is probably to use the good ol' command prompt to launch an independent new instance not based at all on your original script. To do this, you can use invoke-expression in conjunction with 'cmd /c'. See Below:

invoke-expression 'cmd /c start powershell -NoProfile -windowstyle hidden -Command {
    $i = 0
    while ($true) {
        if($i -gt 30) {
            break
        }
        else {
            $i | Out-File C:\Temp\IndependentSessionTest.txt -Append
            Start-Sleep -Seconds 1
            $i++
        }
    }
}
'

This will start a new session, run the script you want, not show a window and not use your powershell profile when the script gets run. You will be able to see that even if you kill the original PowerShell session, this one will keep running. You can verify this by looking at the IndependentSessionTest.txt file after you close the main powershell window and see that the file keeps getting updated numbers.

Hopefully this points you in the right direction.

Here's some source links:

PowerShell launch script in new instance

How to run a PowerShell script without displaying a window?

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