长时间运行的 Powershell 脚本冻结

发布于 2024-09-08 12:12:55 字数 156 浏览 4 评论 0原文

我们正在使用长时间运行的 PowerShell 脚本来执行许多可能需要极长时间的小操作。大约 30 分钟后,脚本冻结了。我们能够通过按 Ctrl-C 使脚本重新开始运行,这会导致脚本恢复执行而不是终止进程。

是否存在某种脚本超时或机制可以防止 PowerShell 中长时间运行脚本?

We are using a long running PowerShell script to perform a lot of small operations that can take an extremely long amount of time. After about 30 minutes the scripts froze. We were able to get the scripts to start running again by pressing Ctrl-C which caused the scripts to resume execution instead of killing the process.

Is there some sort of script timeout or mechanism that prevents long running scripts within PowerShell?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

情绪少女 2024-09-15 12:12:55

由于我的坏习惯,我遇到了这个问题。如果您在控制台 powershell 中选择一点文本,脚本日志将冻结。确保启动大脚本后没有选择任何内容:)

I had this problem due to a bad habit I have. If you select a little bit of text inside a console powershell, scripts logs freeze. Make sure nothing is selected after launching a big script :)

寒尘 2024-09-15 12:12:55

如前所述,当在 powershell 控制台中单击/选择文本时,脚本会停止。您可以像这样禁用此行为:

  • 右键单击标题栏

  • 选择属性

  • 选择选项

  • 编辑选项下,禁用快速编辑模式

注意:您将无法再从 powershell 窗口中选择文本。

Like mentioned, when clicking/selecting text in powershell console, the script stops. You can disable this behaviour like this:

  • Right-click the title bar

  • Select Properties

  • Select Options

  • Under Edit Options, disable QuickEdit Mode

Note: You won't be able to select text from powershell window anymore.

真心难拥有 2024-09-15 12:12:55

试试我的终止计时器脚本。只需将 $ScriptLocation 变量更改为您要运行的脚本即可。然后,该脚本将作为后台作业运行,同时当前窗口跟踪计时器。时间到期后,当前窗口将终止后台作业并将其全部写入日志。

    Start-Transcript C:\Transcriptlog-Cleanup.txt #write log to this location
$p = Get-Process  -Id $pid | select -Expand id  # -Expand selects the string from the object id out of the current process.
Write-Host $p
$BJName = "Clean-up-script"   #Define Background job name

$startTime = (Get-Date) # set start time
$startTime
$expiration = (Get-Date).AddMinutes(2)#program expires at this time
# you could change the expiration time by changing (Get-Date).AddSeconds(20) to (Get-Date).AddMinutes(10)or to hours or whatever you like


#-----------------
#Timer update function setup
function UpdateTime
   {
    $LeftMinutes =   ($expiration) - (Get-Date) | Select -Expand minutes  # sets minutes left to left time
    $LeftSeconds =   ($expiration) - (Get-Date) | Select -Expand seconds  # sets seconds left to left time


    #Write time to console
    Write-Host "------------------------------------------------------------------" 
    Write-Host "Timer started at     :  "  $startTime
    Write-Host "Current time         :  "  (Get-Date)
    Write-Host "Timer ends at        :  "  $expiration
    Write-Host "Time on expire timer :  "  $LeftMinutes "Minutes" $LeftSeconds "Seconds"
    Write-Host "------------------------------------------------------------------" 
    }

    #get background job info and remove the it afterwards + print info
function BJManager   
    {
       Receive-Job -Name $BJName  #recive background job results
       Remove-Job -Name $BJName -Force #remove job
       Write-Host "Retrieving Background-Job info and Removing Job..."
    }
#-----------------
$ScriptLocation = "C:\\Local-scripts\Windows-Server-CleanUp-Script-V2.4(Beta).ps1"  #change this Var for different kind of script locations

Start-Job -Name $BJName -FilePath $ScriptLocation #start this script as background job
# dont start job in the loop.
do{   #start loop

   Write-Host "Working"#start doing other script stuff
   Start-Sleep -Milliseconds 5000  #add delay to reduce spam and processing power
   UpdateTime #call upadate function to print time

   Get-Job -Name $BJName  | select Id, State ,Location , Name
        if((Get-Job).State -eq "Failed")
            {
                BJManager
            }
        elseif((Get-Job).State -eq "Completed")
            {
                BJManager
            }

 }
until ($p.HasExited -or (Get-Date) -gt $expiration) #check exit time

Write-Host "Timer Script Finished"
Get-Job -Name $BJName  | select Id, State ,Location , Name
UpdateTime

BJManager

Start-Sleep -Milliseconds 5000 #give it some time to write to log
Stop-Transcript
Start-Sleep -Milliseconds 5000 #give it some time to stop the logging before killing process
if (-not $p.HasExited) { Stop-Process -ID $p -PassThru } # kill process after time expires

Try my kill timer script. Just change the $ScriptLocation variable to the script you want to run. That script will then run as a background job while the current windows keeps track of the timer. After the time expires the current window will kill the background job and write it all to logs.

    Start-Transcript C:\Transcriptlog-Cleanup.txt #write log to this location
$p = Get-Process  -Id $pid | select -Expand id  # -Expand selects the string from the object id out of the current process.
Write-Host $p
$BJName = "Clean-up-script"   #Define Background job name

$startTime = (Get-Date) # set start time
$startTime
$expiration = (Get-Date).AddMinutes(2)#program expires at this time
# you could change the expiration time by changing (Get-Date).AddSeconds(20) to (Get-Date).AddMinutes(10)or to hours or whatever you like


#-----------------
#Timer update function setup
function UpdateTime
   {
    $LeftMinutes =   ($expiration) - (Get-Date) | Select -Expand minutes  # sets minutes left to left time
    $LeftSeconds =   ($expiration) - (Get-Date) | Select -Expand seconds  # sets seconds left to left time


    #Write time to console
    Write-Host "------------------------------------------------------------------" 
    Write-Host "Timer started at     :  "  $startTime
    Write-Host "Current time         :  "  (Get-Date)
    Write-Host "Timer ends at        :  "  $expiration
    Write-Host "Time on expire timer :  "  $LeftMinutes "Minutes" $LeftSeconds "Seconds"
    Write-Host "------------------------------------------------------------------" 
    }

    #get background job info and remove the it afterwards + print info
function BJManager   
    {
       Receive-Job -Name $BJName  #recive background job results
       Remove-Job -Name $BJName -Force #remove job
       Write-Host "Retrieving Background-Job info and Removing Job..."
    }
#-----------------
$ScriptLocation = "C:\\Local-scripts\Windows-Server-CleanUp-Script-V2.4(Beta).ps1"  #change this Var for different kind of script locations

Start-Job -Name $BJName -FilePath $ScriptLocation #start this script as background job
# dont start job in the loop.
do{   #start loop

   Write-Host "Working"#start doing other script stuff
   Start-Sleep -Milliseconds 5000  #add delay to reduce spam and processing power
   UpdateTime #call upadate function to print time

   Get-Job -Name $BJName  | select Id, State ,Location , Name
        if((Get-Job).State -eq "Failed")
            {
                BJManager
            }
        elseif((Get-Job).State -eq "Completed")
            {
                BJManager
            }

 }
until ($p.HasExited -or (Get-Date) -gt $expiration) #check exit time

Write-Host "Timer Script Finished"
Get-Job -Name $BJName  | select Id, State ,Location , Name
UpdateTime

BJManager

Start-Sleep -Milliseconds 5000 #give it some time to write to log
Stop-Transcript
Start-Sleep -Milliseconds 5000 #give it some time to stop the logging before killing process
if (-not $p.HasExited) { Stop-Process -ID $p -PassThru } # kill process after time expires
只是一片海 2024-09-15 12:12:55

尝试在脚本中添加百分比计算..这样您就可以确定完成需要多少时间...

try to add percentage calculation in your script.. so you can identity that how much time it would take to complete...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文