场景描述:最近使用 fastapi 框架搭建 web 服务,有这样一个场景,我需要某个接口先返回数据,再去处理业务,所以就使用到了 celery 来做异步处理。
task 中是封装的业务代码,在此中有一个公共方法的功能是使用 scrcpy 录制手机屏幕,在结束录屏的时候,我遇到了 bug!
话不多说上代码:
task 任务:
srd = ScreenRecording(devicename, uid) # 开启录屏,并存放在 uid 中
srd.run()
sleep(10)
srd.stop()
ScreenRecording 录屏工具类:
import subprocess
from loguru import logger
class ScreenRecording():
def init(self, devicename, uid):
self.devicename = devicename
self.uid = uid
logger.debug(f"创建录屏实例化对象!属性为:devicename={devicename}&uid={uid}")
def run(self):
cmd = f"scrcpy -s {self.devicename} -Nr ./report/{self.uid}/report/{self.uid}.mp4"
self.p = subprocess.Popen(cmd, shell=True)
logger.debug(f"设备{self.devicename}已开始录屏!")
def stop(self):
# 方案一----------------------------------------------
# self.p.send_signal(signal.CTRL_C_EVENT) # 不能使用发送 ctrl+c 信号,会导致 celery 服务停止!
# 方案二-------------------------------------------------
# os.kill(self.p.pid, signal.CTRL_C_EVENT) # 方法可行,但是会造成 celery 队列卡死
# self.p.wait() # 加了 wait 与方案一效果一致
# sleep(2) # 加了延迟也与方案一一致
# 方案三----------------------------------------------------
# self.p.send_signal(signal.SIGTERM) # 无法终止录屏
# 方案四-----------------------------------------------
# self.p.terminate() # 无法终止录屏
# 方案五---------------------------------------------
# os.kill(self.p.pid, signal.CTRL_C_EVENT) # 无效
# sleep(0.01)
# self.p.wait()
# 方案六-----------------------------------------
# p = psutil.Process(pid=self.p) # 无效
# print(self.p)
# print(p)
# p.send_signal(signal.CTRL_C_EVENT)
# 方案七-------------------------------------
# os.system(f'taskkill /t /pid {self.p.pid}') # 无效
# 方案八-------------------------------------
# os.killpg(os.getpgid(self.p.pid), 2) # 无效
# self.p.wait()
logger.debug(f"设备{self.devicename}已结束录屏!")
额外补充:在此期间我尝试了各种 kill 信号,包括-2,-9 信号。总结就是,要么结束不掉 popen 管道进程,要么连着 celery 服务一起 ctrl+c 结束了!
求助求助