Powershell构建步骤,火灾和忘记?

问题描述 投票:1回答:4

我在使用TFS 2018的构建步骤中运行以下powershell命令。

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

由于我不希望脚本影响构建步骤,因此它应该只是触发并忘记脚本。因此我使用Start-Job。但似乎一旦完成该步骤,该过程就会被杀死。有没有办法维护进程生命周期,即使构建步骤已完成或构建过程已完成?

其他信息...... powershell脚本应该在远程服务器上运行。脚本本身会触发带参数的.exe。

powershell tfs azure-devops jobs
4个回答
2
投票

要简单地触发并忘记,请使用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.
  • 这应该以异步方式远程启动脚本,并在本地会话中创建作业以监视其执行。 警告:使用Start-Sleep - 可能需要更长的等待时间 - 似乎是必要的,以便在调用脚本退出之前创建远程进程,但这样的解决方案可能不完全健壮,因为没有保证的时间。
  • 由于您不打算监视远程执行,因此本地会话终止 - 以及监视作业 - 应该不重要。

1
投票

您希望何时停止运行脚本?您可以使用do-while循环并提出满足您需求的<condition>

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

或者,您可以使用条件$true,以便它永远执行。当您不再需要时,您将不得不在脚本中稍后停止该作业。

$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

我添加了一个Start-Sleep 2,因此它不会锁定你的CPU,因为不知道脚本在做什么 - 如果不需要则删除。


1
投票

为什么不是这样的:

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)

1
投票

@doorman - PowerShell本身就是一个单线程应用程序。几乎在所有情况下,这都是一个巨大的好处。即使强制多线程,您也可以看到子线程始终依赖于主线程。如果不是这种情况,那么创建内存泄漏将非常容易。这几乎总是一件好事,因为当您关闭主线程时,.Net将清理您可能忘记的所有其他线程。你碰巧碰到了这种行为对你的情况不利的情况。

有几种方法可以解决这个问题,但最简单的方法可能是使用良好的命令提示符启动一个完全不基于原始脚本的独立新实例。为此,您可以将invoke-expression与'cmd / c'结合使用。见下文:

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++
        }
    }
}
'

这将启动一个新会话,运行您想要的脚本,不显示窗口,并在脚本运行时不使用您的powershell配置文件。您将能够看到即使您终止原始PowerShell会话,这个会继续运行。关闭主PowerShell窗口后,您可以通过查看IndependentSessionTest.txt文件来验证这一点,并查看该文件是否持续获取更新的数字。

希望这能指出你正确的方向。

这是一些源链接:

PowerShell launch script in new instance

How to run a PowerShell script without displaying a window?

© www.soinside.com 2019 - 2024. All rights reserved.