如何通过python程序脚本运行终端命令行命令?
常见方法:
-
1、subprocess模块
-
subprocess.Popen() 方法【异步非阻塞】
- 典型示例
import subprocess def run_with_timeout(command, timeout=5): """ 执行命令并监控超时,返回是否成功退出(True=成功,False=超时或失败) 参数: command (list): 要执行的命令(如 ["ffmpeg", "-i", "input.mp3"]) timeout (int): 允许命令运行的最大秒数(默认5秒) 返回: bool: True=进程正常退出且返回码为0,False=超时或进程异常退出 逻辑流程: 1. 启动子进程 2. 等待进程结束(带超时) 3. 若超时,先尝试SIGTERM优雅终止 4. 若仍不退出,用SIGKILL强制终止 5. 确保资源回收,避免僵尸进程 """ # 启动子进程(不捕获输出以节省资源) process = subprocess.Popen( command, stdout=subprocess.DEVNULL, # 丢弃stdout stderr=subprocess.DEVNULL, # 丢弃stderr ) try: # 阻塞等待进程结束(主超时) exit_code = process.wait(timeout=timeout) # 返回是否成功退出(0表示成功) return exit_code == 0 except subprocess.TimeoutExpired: # --- 第一阶段终止:尝试优雅终止(SIGTERM)--- process.terminate() try: # 给进程2秒时间处理SIGTERM exit_code = process.wait(timeout=2) return False # 进程已终止,但属于超时后终止,返回失败 except subprocess.TimeoutExpired: # --- 第二阶段终止:强制杀死(SIGKILL)--- process.kill() # 此处wait()会立即返回,因为SIGKILL是同步的 process.wait() return False # 注:不需要finally关闭流,因为未使用stdout/stderr管道
- wait(timeout)阻塞等待示例--超时会抛异常
import subprocess cmd = 'python test.py' process = subprocess.Popen(cmd) # 开始异步执行 ### 主进程处理别的事情 try: # 尝试优雅关闭 process.terminate() exit_code = process.wait(timeout=3) print(f"子进程已退出,返回码: {exit_code}") except subprocess.TimeoutExpired: print("关闭超时,强制杀死进程...") process.kill() # 强制杀死 exit_code = process.wait() print(f"警告:子进程被强制终止,返回码: {exit_code}") except Exception as e: print(f"关闭进程时出错: {e}")
- poll()非阻塞等待示例
import subprocess import time cmd = 'python test.py' process = subprocess.Popen(cmd) # 开始异步执行 ### 主进程处理别的事情 print("主进程正在处理其他任务...") # 尝试优雅关闭 process.terminate() max_wait_time = 3 # 最大等待时间 check_interval = 0.1 # 检查间隔 start_time = time.time() while True: # 非阻塞检查进程状态 exit_code = process.poll() if exit_code is not None: # 进程已经结束 if exit_code == 0: print(f"子进程正常退出,返回码: {exit_code}") else: print(f"子进程异常退出,返回码: {exit_code}") break # 检查是否超时 if time.time() - start_time > max_wait_time: print("关闭超时,强制杀死进程...") process.kill() # 强制杀死 # 等待确认进程结束 final_exit_code = process.wait() print(f"子进程被强制终止,返回码: {final_exit_code}") break # 等待一小段时间再次检查 time.sleep(check_interval) print("主进程继续执行...")
poll()会立即返回,进程运行时返回
None,结束时返回退出码 - 不需要交互形式(比如frida执行时按q退出,这个q就是交互参数)
import subprocess import time # ==================== 启动子进程 ==================== # 注意:这里故意不启用任何管道(stdin/stdout/stderr) process = subprocess.Popen(["python", "test2.py"]) # ==================== 主程序逻辑 ==================== time.sleep(2) # 模拟主程序执行其他任务 # ==================== 终止子进程 ==================== # 1. 温和终止尝试 process.terminate() # 发送SIGTERM print("已发送终止信号(SIGTERM),等待子进程退出...") # 2. 超时控制 try: exit_code = process.wait(timeout=5) # 最多等5秒 print(f"子进程已退出,返回码: {exit_code}") except subprocess.TimeoutExpired: # 3. 强制终止 process.kill() # 发送SIGKILL exit_code = process.wait() # 立即返回 print(f"警告:子进程被强制终止,返回码: {exit_code}") # ==================== 状态验证 ==================== if exit_code == 0: print("子进程正常结束") else: print(f"子进程异常结束(代码 {exit_code})")
- 常见信号说明
- SIGINT 交互式中断 Ctrl+C os.kill(pid, signal.SIGINT)
- SIGTERM 优雅终止 kill <PID> process.terminate()
- SIGKILL 强制终止 kill -9 process.kill()
- 常见信号说明
- 交互式退出
import subprocess # 启动FFmpeg录制(立即进入等待指令状态) process = subprocess.Popen( ["ffmpeg", "-f", "pulse", "-i", "default", "output.mp3"], # windows则用["ffmpeg", "-f", "dshow", "-i", "audio=麦克风名称","output.mp3"] stdin=subprocess.PIPE, # 必须启用输入管道 universal_newlines=True ) # 通过communicate发送终止指令 try: # 发送'q'指令及响应总时间,最多等待5秒 _, _ = process.communicate(input="q\n", timeout=5) except subprocess.TimeoutExpired: # 双重保险:先尝试SIGTERM process.terminate() try: exit_code = process.wait(timeout=5) except subprocess.TimeoutExpired: process.kill() # 终极手段 exit_code = process.wait() # 立即返回 if exit_code == 0: print("子进程正常结束") else: print(f"子进程异常结束(代码 {exit_code})")
-
示例1
import subprocess, os import time # 启动子进程(异步非阻塞) # process = subprocess.Popen("python test2.py") process = subprocess.Popen(["python", "test2.py"]) time.sleep(2) # 模拟执行其它任务 # 以下两行命令能保证子进程被完全终止 # 终止子进程 process.terminate() # 或者使用 process.kill() # 等待子进程终止 process.wait() # 没有获取交互结果的能力 # stdinput, stderr = process.communicate() 用于与子进程进行交互,并等待子进程完成,同时能够获取子进程的标准输出和标准错误输出 # print(stdinput) # print(stderr) # 判断子进程终止状态 if process.returncode is not None: print("子进程已终止,返回码: ", process.returncode) else: print("无法确定子进程的终止状态")
-
示例2
import subprocess command = 'adb -s 127.0.0.1:62001 shell "su ; cd /data/local/tmp ; ls"' process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) output, error = process.communicate() if process.returncode == 0: print("Command executed successfully.") print("Output:\n", output.decode()) else: print("Command execution failed.") print("Error:\n", error.decode())
- 典型示例
-
subprocess.run() 方法 【同步阻塞】
- 返回CompletedProcess对象,其中包含有关命令执行的信息,如返回码、标准输出和标准错误输出。
import subprocess # 执行外部命令 result = subprocess.run(["python", "test2.py"], capture_output=True, text=True) # 获取返回码 print(f"返回码:{result.returncode}") # 获取标准输出 print(f"标准输出:{result.stdout}") # 获取标准错误输出 print(f"标准错误输出:{result.stderr}")
- 返回CompletedProcess对象,其中包含有关命令执行的信息,如返回码、标准输出和标准错误输出。
-
subprocess.getoutput() 方法 【同步阻塞】
- 返回标准输出字符串
import subprocess # 执行外部命令 output = subprocess.getoutput("python test2.py") # 打印标准输出 print(output)
- 返回标准输出字符串
-
subprocess.check_output()方法【同步阻塞】
- 返回标准输出字节
import subprocess cmd = 'java -jar unidbg-0.9.7.jar' result = subprocess.check_output(cmd, shell=True, cwd='unidbg_0_9_7_jar') # cwd参数表示进入某个目录执行的命令 print(result.strip().decode().splitlines()[0])
- 返回标准输出字节
-
-
2、os模块
-
os.system() 方法【同步阻塞】
import os os.system('pip3 show crawlab-sdk') # 查看版本 # os.system('pip3 uninstall crawlab-sdk -y') # 卸载 os.system('pip3 install crawlab-sdk==0.3.3 --force-reinstall') # 指定版本强制重新安装
-

浙公网安备 33010602011771号