如何跨终端触发命令执行?Python向CLI子进程发送指令
这个需求完全可以实现,macOS Monterey 12.2.1环境不存在系统层面的阻碍,根据你启动进程A的场景不同,可选择对应方案落地。
方案1:可修改进程A启动逻辑时优先选择(稳定性最高)
不要用os.system这类无法接管标准输入输出的接口启动A,改用subprocess搭配管道或伪终端启动,即可直接通过Python向继承了输入句柄的子进程B发送命令。
- 普通管道模式:如果B不需要检测真实终端环境,可以直接用
subprocess.PIPE接管输入输出
import subprocess import time # 启动进程A,配置管道继承 proc_a = subprocess.Popen( ["/path/to/你的进程A启动命令"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, close_fds=False ) # 等待数秒让B完成启动 time.sleep(5) # 向B发送执行命令,末尾必须加\n模拟回车操作 send_cmd = "你要在B中执行的指令\n" proc_a.stdin.write(send_cmd) proc_a.stdin.flush() # 强制刷新缓冲区,避免内容滞留在Python侧
- 伪终端模式(兼容性最好):如果B会检测运行环境是否为真实终端、普通管道下无法进入交互模式,就用pty模块创建伪终端绑定A的输入输出,和手动开终端操作的环境完全一致
import pty import os import subprocess import time master_fd, slave_fd = pty.openpty() proc_a = subprocess.Popen( ["/path/to/你的进程A启动命令"], stdin=slave_fd, stdout=slave_fd, stderr=slave_fd, close_fds=True ) os.close(slave_fd) time.sleep(5) # 向伪终端写入指令,内容会直接送达B的输入 os.write(master_fd, b"你要在B中执行的指令\n")
如果需要根据B的返回结果判断指令执行状态,可以循环读取管道/伪终端主端的输出内容做逻辑判断,不建议用固定sleep等待,避免时序偏差导致指令发送失败。
方案2:进程A/B已经启动、无法修改启动逻辑时使用
如果进程已经在运行,可以先定位到进程B的PID,再向B绑定的终端设备写入指令实现输入注入。
- 定位B的PID:可以通过psutil库遍历A的子进程快速匹配,也可以手动执行
pgrep -P <A的PID>查找A的子进程
import psutil a_pid = 12345 # 替换成你实际的进程A的PID b_pid = None for child in psutil.Process(a_pid).children(recursive=True): if child.name() == "进程B的可执行文件名": b_pid = child.pid break
- 查找B绑定的tty路径:执行
ps -o tty= -p <B的PID>可以拿到B对应的终端号,比如返回ttys001,对应的设备文件路径为/dev/ttys001 - 向终端设备写入指令即可送达B:
tty_path = "/dev/ttys001" # 替换成实际查到的tty路径 with open(tty_path, "w") as f: f.write("你要在B中执行的指令\n")
该方案有两个限制:一是B必须绑定在可写的tty设备上,如果A是后台守护进程模式启动、没有给B分配终端,这个方法无法生效;二是如果B以高于当前Python脚本的权限(比如sudo)运行,需要给Python脚本提权才能写入tty。
通用注意事项
- 所有发送给B的指令末尾必须加换行符
\n,和手动在终端输完命令按回车的逻辑一致,不加换行B会持续等待输入结束,不会执行指令。 - 不管用哪种方式写入指令,都要做刷新操作(
stdin.flush()/直接调用系统write接口),避免内容卡在缓冲区没有实际发送。
内容的提问来源于stack exchange,提问作者Nevo Mashiach
相关产品推荐
相关产品推荐

