Powershell 作业内存消耗问题
Powershell Job Memory Consumption Issue
我已经为此苦苦挣扎了一个星期,并且用尽了我在网上找到的所有方法和选项。我希望这里有人能够帮助我解决这个问题。
我正在使用 powershell 启动 8 个作业,每个作业 运行 FFmpeg 将一个 7 分钟的文件流式传输到远程 RTMP 服务器。这是从磁盘上的文件中提取的,每个作业使用不同的文件。该命令处于 do while 循环中,因此它会不断重新流式传输。
这导致 shell 我从中启动作业以积累大量内存,尽其所能。在 24 小时内,它消耗了我服务器 32 GB 中的 30 GB。
这是我的启动代码,如有任何帮助,我们将不胜感激。
start-job -Name v6 -scriptblock {
do { $d = $true; $f = Invoke-Expression -Command "ffmpeg -re -i `"C:\Shares\Matthew0p_3000k.mp4`" -vcodec copy -acodec copy -f flv -y rtmp://<ip>/<appName>/<streamName>"; $f = $null }
while ($d = $true)
}
我尝试接收作业并将其通过管道传输到 out-null,我尝试在开始 do while 循环之前将 $f 设置为 $null,以及我在网上找到的其他一些东西但无济于事。感谢大家的抽空!
调用 PowerShell 脚本或表达式的方法有很多种。
我的最爱之一是使用 RunspacePool。在 RunspacePool 中,每个任务都从一个新的运行空间开始。当任务完成时,运行空间被释放。这应该使内存消耗保持相当稳定。这不是让您了解情况的最简单方法,但这里有一个可能适合您的简单示例。
$Throttle = 10 # Maximum jobs that can run simultaneously in a runpool
$maxjobs = 8 # Maximum jobs that will run simultaneously
[System.Collections.ArrayList]$jobs = @()
$script:currentjobs = 0
$jobindex = 0
$jobaction = "ffmpeg -re -i `"C:\Shares\Matthew0p_3000k.mp4`" -vcodec copy -acodec copy -f flv -y rtmp://<ip>/<appName>/<streamName>"
$sessionstate = [system.management.automation.runspaces.initialsessionstate]::CreateDefault()
$runspace = [runspacefactory]::CreateRunspacePool(1, $Throttle, $sessionstate, $Host)
$runspace.Open()
function QueueJob{
param($jobindex)
$job = "" | Select-Object JobID,Script,Errors,PS,Runspace,Handle
$job.JobID = $jobindex
$job.Script = $jobaction
$job.PS = [System.Management.Automation.PowerShell]::create()
$job.PS.RunspacePool = $runspace
[void]$job.PS.AddScript($job.Script)
$job.Runspace = $job.PS.BeginInvoke()
$job.Handle = $job.Runspace.AsyncWaitHandle
Write-Host "----------------- Starting Job: $("{0:D4}" -f $job.JobID) --------------------" -ForegroundColor Blue
$jobs.add($job)
$script:currentjobs++
}
Function ServiceJobs{
foreach($job in $Jobs){
If ($job.Runspace.isCompleted) {
$result = $job.PS.EndInvoke($job.Runspace)
$job.PS.dispose()
$job.Runspace = $null
$job.PS = $null
$script:currentjobs--
Write-Host "----------------- Job Completed: $("{0:D4}" -f $job.JobID) --------------------" -ForegroundColor Yellow
Write-Host $result
$Jobs.Remove($job)
return
}
}
}
while ($true) {
While ($script:currentjobs -le $maxjobs){
QueueJob $jobindex
$jobindex++
}
ServiceJobs
Start-Sleep 1
}
$runspace.Close()
[gc]::Collect()
它使用了一个没有正确终止的无限循环,并且缺少任何类型的错误检查,但希望它足以证明该技术。
我想迟到总比不到好。当 运行 ffmpeg 在 Powershell 作业中时,我遇到了同样的巨大内存消耗问题。问题的核心是 Powershell 作业会将 any/all 输出存储到内存中,而 ffmpeg 非常乐意将输出记录到标准 output 和标准 错误 流。
我的解决方案是将参数“-loglevel quiet”添加到 ffmpeg。或者,您可以将标准流和错误流都重定向到 null(仅重定向标准流是不够的)。有关如何重定向标准流的更多信息,请参阅此问题:Redirection of standard and error output appending to the same log-file
我已经为此苦苦挣扎了一个星期,并且用尽了我在网上找到的所有方法和选项。我希望这里有人能够帮助我解决这个问题。
我正在使用 powershell 启动 8 个作业,每个作业 运行 FFmpeg 将一个 7 分钟的文件流式传输到远程 RTMP 服务器。这是从磁盘上的文件中提取的,每个作业使用不同的文件。该命令处于 do while 循环中,因此它会不断重新流式传输。
这导致 shell 我从中启动作业以积累大量内存,尽其所能。在 24 小时内,它消耗了我服务器 32 GB 中的 30 GB。
这是我的启动代码,如有任何帮助,我们将不胜感激。
start-job -Name v6 -scriptblock {
do { $d = $true; $f = Invoke-Expression -Command "ffmpeg -re -i `"C:\Shares\Matthew0p_3000k.mp4`" -vcodec copy -acodec copy -f flv -y rtmp://<ip>/<appName>/<streamName>"; $f = $null }
while ($d = $true)
}
我尝试接收作业并将其通过管道传输到 out-null,我尝试在开始 do while 循环之前将 $f 设置为 $null,以及我在网上找到的其他一些东西但无济于事。感谢大家的抽空!
调用 PowerShell 脚本或表达式的方法有很多种。
我的最爱之一是使用 RunspacePool。在 RunspacePool 中,每个任务都从一个新的运行空间开始。当任务完成时,运行空间被释放。这应该使内存消耗保持相当稳定。这不是让您了解情况的最简单方法,但这里有一个可能适合您的简单示例。
$Throttle = 10 # Maximum jobs that can run simultaneously in a runpool
$maxjobs = 8 # Maximum jobs that will run simultaneously
[System.Collections.ArrayList]$jobs = @()
$script:currentjobs = 0
$jobindex = 0
$jobaction = "ffmpeg -re -i `"C:\Shares\Matthew0p_3000k.mp4`" -vcodec copy -acodec copy -f flv -y rtmp://<ip>/<appName>/<streamName>"
$sessionstate = [system.management.automation.runspaces.initialsessionstate]::CreateDefault()
$runspace = [runspacefactory]::CreateRunspacePool(1, $Throttle, $sessionstate, $Host)
$runspace.Open()
function QueueJob{
param($jobindex)
$job = "" | Select-Object JobID,Script,Errors,PS,Runspace,Handle
$job.JobID = $jobindex
$job.Script = $jobaction
$job.PS = [System.Management.Automation.PowerShell]::create()
$job.PS.RunspacePool = $runspace
[void]$job.PS.AddScript($job.Script)
$job.Runspace = $job.PS.BeginInvoke()
$job.Handle = $job.Runspace.AsyncWaitHandle
Write-Host "----------------- Starting Job: $("{0:D4}" -f $job.JobID) --------------------" -ForegroundColor Blue
$jobs.add($job)
$script:currentjobs++
}
Function ServiceJobs{
foreach($job in $Jobs){
If ($job.Runspace.isCompleted) {
$result = $job.PS.EndInvoke($job.Runspace)
$job.PS.dispose()
$job.Runspace = $null
$job.PS = $null
$script:currentjobs--
Write-Host "----------------- Job Completed: $("{0:D4}" -f $job.JobID) --------------------" -ForegroundColor Yellow
Write-Host $result
$Jobs.Remove($job)
return
}
}
}
while ($true) {
While ($script:currentjobs -le $maxjobs){
QueueJob $jobindex
$jobindex++
}
ServiceJobs
Start-Sleep 1
}
$runspace.Close()
[gc]::Collect()
它使用了一个没有正确终止的无限循环,并且缺少任何类型的错误检查,但希望它足以证明该技术。
我想迟到总比不到好。当 运行 ffmpeg 在 Powershell 作业中时,我遇到了同样的巨大内存消耗问题。问题的核心是 Powershell 作业会将 any/all 输出存储到内存中,而 ffmpeg 非常乐意将输出记录到标准 output 和标准 错误 流。
我的解决方案是将参数“-loglevel quiet”添加到 ffmpeg。或者,您可以将标准流和错误流都重定向到 null(仅重定向标准流是不够的)。有关如何重定向标准流的更多信息,请参阅此问题:Redirection of standard and error output appending to the same log-file