无法终止Python Popen启动的adb logcat及Logger进程,求解决方法
无法终止adb logcat及关联Logger进程的排查与解决
问题背景
以下Python代码可正常拉取安卓设备日志并传入Logger生成目标文本文件,但无法终止两个进程。尝试过terminate()、os.kill(process.pid, signal.SIGKILL)、preexec_fn、os.killpg()等方法后,Logger仍在后台运行。
代码示例
def startLogger(logger_dir): command0 = 'adb logcat -c' command1 = 'adb logcat' command2 = 'python3 '+logger_dir+'main.py' clear_logcat = subprocess.run(command0.split()) logcatHandle = subprocess.Popen(command1.split(),stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=False) loggerHandle = subprocess.Popen(command2.split(),stdin=logcatHandle.stdout,shell=False) return logcatHandle, loggerHandle def closeLogger(logcatInstance, loggerInstance): loggerInstance.kill() #Killing it first so that it doesn't break the input PIPE logcatInstance.kill() return logcatInstance, loggerInstance def main(): logger_dir = '/Users/Desktop/logger/' print("Starting Logger") logcatHandle, loggerHandle = startLogger(logger_dir) time.sleep(10) logcat, logger = closeLogger(logcatHandle, loggerHandle) main()
排查与解决思路
- 子进程脱离父进程控制:你启动的
python3 main.py可能创建了独立子进程,仅杀死父进程的话,子进程会被系统进程接管继续运行。可以用ps aux | grep main.py查看进程树,确认是否存在这类情况。 - 管道未正确关闭导致阻塞:杀死
loggerHandle后,logcatHandle的stdout管道可能未被关闭,导致adb logcat无法正常退出。创建子进程时添加close_fds=True,确保父进程操作时关闭未使用的文件描述符:logcatHandle = subprocess.Popen( command1.split(), stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=False, close_fds=True ) loggerHandle = subprocess.Popen( command2.split(), stdin=logcatHandle.stdout, shell=False, close_fds=True ) - 进程组未整体销毁:如果目标进程启动了进程组,单独杀死单个进程无效。创建子进程时设置
start_new_session=True,让进程成为新会话领头进程,再用os.killpg杀死整个进程组:
修改进程创建代码:
修改关闭逻辑:logcatHandle = subprocess.Popen( command1.split(), stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=False, start_new_session=True ) loggerHandle = subprocess.Popen( command2.split(), stdin=logcatHandle.stdout, shell=False, start_new_session=True )import os import signal def closeLogger(logcatInstance, loggerInstance): try: os.killpg(os.getpgid(loggerInstance.pid), signal.SIGKILL) except ProcessLookupError: pass try: os.killpg(os.getpgid(logcatInstance.pid), signal.SIGKILL) except ProcessLookupError: pass return logcatInstance, loggerInstance - 检查
main.py自身退出逻辑:有可能main.py内部存在忽略SIGKILL信号的逻辑,或者处理输入时陷入无限循环(未正确处理EOF)。可以单独运行python3 /Users/Desktop/logger/main.py,手动输入EOF(Ctrl+D)测试是否能正常退出,排查main.py自身问题。
内容的提问来源于stack exchange,提问作者Priyansh Gupta
相关产品推荐
相关产品推荐

