我正在使用ffmpeg和subrocess构建实时多视频流监控。 我目前拥有以下代码,受"Async and await with subprocesses" post启发。
问题是在一段时间后输出停止打印并且进程进入僵尸模式。我猜这个问题与PIPE的过载或死锁有关。需要帮助。
"""Async and await example using subprocesses
Note:
Requires Python 3.6.
"""
import os
import sys
import time
import platform
import asyncio
async def run_command_shell(command):
"""Run command in subprocess (shell)
Note:
This can be used if you wish to execute e.g. "copy"
on Windows, which can only be executed in the shell.
"""
# Create subprocess
process = await asyncio.create_subprocess_shell(
command,
stderr=asyncio.subprocess.PIPE)
# Status
print('Started:', command, '(pid = ' + str(process.pid) + ')')
# Wait for the subprocess to finish
stdout, stderr = await process.communicate()
# Progress
if process.returncode == 0:
print('Done:', command, '(pid = ' + str(process.pid) + ')')
else:
print('Failed:', command, '(pid = ' + str(process.pid) + ')')
# Result
result = stderr.decode().strip()
# Real time print
print(result)
# Return stdout
return result
def make_chunks(l, n):
"""Yield successive n-sized chunks from l.
Note:
Taken from https://stackoverflow.com/a/312464
"""
if sys.version_info.major == 2:
for i in xrange(0, len(l), n):
yield l[i:i + n]
else:
# Assume Python 3
for i in range(0, len(l), n):
yield l[i:i + n]
def run_asyncio_commands(tasks, max_concurrent_tasks=0):
"""Run tasks asynchronously using asyncio and return results
If max_concurrent_tasks are set to 0, no limit is applied.
Note:
By default, Windows uses SelectorEventLoop, which does not support
subprocesses. Therefore ProactorEventLoop is used on Windows.
https://docs.python.org/3/library/asyncio-eventloops.html#windows
"""
all_results = []
if max_concurrent_tasks == 0:
chunks = [tasks]
else:
chunks = make_chunks(l=tasks, n=max_concurrent_tasks)
for tasks_in_chunk in chunks:
if platform.system() == 'Windows':
loop = asyncio.ProactorEventLoop()
asyncio.set_event_loop(loop)
else:
loop = asyncio.get_event_loop()
commands = asyncio.gather(*tasks_in_chunk) # Unpack list using *
results = loop.run_until_complete(commands)
all_results += results
loop.close()
return all_results
if __name__ == '__main__':
start = time.time()
if platform.system() == 'Windows':
# Commands to be executed on Windows
commands = [
['hostname']
]
else:
# Commands to be executed on Unix
commands = [
['du', '-sh', '/var/tmp'],
['hostname'],
]
cmds = [["ffmpeg -y -i udp://xxx.xx.xx.xxx:xxxx -f null -"],
["ffmpeg -y -i udp://xxx.xx.xx.xxx:xxxx -f null -"],
["ffmpeg -y -i udp://xxx.xx.xx.xxx:xxxx -f null -"],
["ffmpeg -y -i udp://xxx.xx.xx.xxx:xxxx -f null -"],
["ffmpeg -y -i udp://xxx.xx.xx.xxx:xxxx -f null -"],
["ffmpeg -y -i udp://xxx.xx.xx.xxx:xxxx -f null -"],
["ffmpeg -y -i udp://xxx.xx.xx.xxx:xxxx -f null -"],
["ffmpeg -y -i udp://xxx.xx.xx.xxx:xxxx -f null -"],
["ffmpeg -y -i udp://xxx.xx.xx.xxx:xxxx -f null -"],
["ffmpeg -y -i udp://xxx.xx.xx.xxx:xxxx -f null -"],
["ffmpeg -y -i udp://xxx.xx.xx.xxx:xxxx -f null -"],
["ffmpeg -y -i udp://xxx.xx.xx.xxx:xxxx -f null -"]]
tasks = []
for command in cmds:
tasks.append(run_command_shell(*command))
# # Shell execution example
# tasks = [run_command_shell('copy c:/somefile d:/new_file')]
# # List comprehension example
# tasks = [
# run_command(*command, get_project_path(project))
# for project in accessible_projects(all_projects)
# ]
results = run_asyncio_commands(tasks, max_concurrent_tasks=20) # At most 20 parallel tasks
print('Results:', results)
end = time.time()
rounded_end = ('{0:.4f}'.format(round(end-start,4)))
print('Script ran in about', str(rounded_end), 'seconds')
答案 0 :(得分:0)
事实证明,问题可能与多线程, asyncio 等的代码优化无关。
原因可能是服务器限制,例如打开文件/文件描述符(FD)的最大数量,防火墙,其他配置文件。
Htop是一个用于Linux / Unix系统的交互式实时进程监控应用程序,也是top
命令的便捷替代方案,它是在所有Linux上预装的默认进程监视工具操作系统。
这可能有助于澄清原因。
正如jfs所说,我需要Minimal, Complete, and Verifiable example。所以我们从一个非常小的开始:测试一个过程。
ffmpeg -y -i udp://224.10.0.123:1234 -f null -
在我的情况下,事实证明任何多播将在2:10 - 2:20挂起 分钟。处于活动状态但处于僵尸模式。这很奇怪, 因为几天前一切都很完美。
Multicat的最新官方版本编号为2.2,可用here。
获取它并且不要忘记,biTStream需要在构建时安装。
使用命令检查流以记录流中的视频:
timeout 10 multicat -uU @224.10.0.123:1234 test.ts
在我的情况下,同样的事情发生在第二分钟。该命令不会停止执行,但文件已停止记录。
使用以下命令命令显示最大打开文件描述符数:
cat /proc/sys/fs/file-max
要查看硬值和软值,请按以下步骤发出命令:
ulimit -Hn
ulimit -Sn
在执行我的一个python脚本的某个时刻,我看到了类似的错误,但是这个参数的增加并没有帮助我。
所以问题与我脚本的并行执行无关。另一台虚拟机的验证成功。我联系了设置这个虚拟机的人并向他解释过去几天发生了什么事情,这表明问题出在防火墙上。他说他没有触及任何东西。但在此之后,一切都开始完美。 (我几乎可以肯定他打破了它):D
GL大家!