Python使用subprocess向已启动的smbclient进程模拟回车并交互的方法
解决方法
你之前的代码使用communicate()方法存在局限性:该方法会一次性发送输入、读取所有输出后直接关闭子进程,无法实现多轮交互。要实现和运行中进程的交互,需要在初始化Popen时指定stdin=subprocess.PIPE开启输入通道,配合手动读写标准输入输出实现需求。
可用实现代码
import subprocess def read_until_prompt(proc, prompt="smb:>"): """读取子进程输出直到匹配到提示符,返回读取到的内容""" output = "" while True: char = proc.stdout.read(1) if not char: # 进程已退出 break output += char if output.endswith(prompt): break return output # 初始化子进程,开启stdin管道,使用text模式自动处理编解码 ip = '172.17.0.2' cmd = f'smbclient \\\\%s\\netlogon' % ip p = subprocess.Popen( cmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, # 把标准错误合并到标准输出,避免读取阻塞 text=True, bufsize=1 # 行缓冲 ) # 1. 发送回车(空字符串加换行就是回车输入) p.stdin.write('\n') p.stdin.flush() # 读取回车后的输出,判断来宾账户状态 first_output = read_until_prompt(p) guest_enabled = 'smb:>' in first_output print(f"来宾账户是否启用:{guest_enabled}") # 2. 执行其他命令,分别存储输出 # 示例:执行ls命令 p.stdin.write('ls\n') p.stdin.flush() ls_output = read_until_prompt(p) print("ls命令输出:", ls_output) # 示例:执行help命令 p.stdin.write('help\n') p.stdin.flush() help_output = read_until_prompt(p) print("help命令输出:", help_output) # 最后发送quit命令退出进程 p.stdin.write('quit\n') p.stdin.flush() p.wait()
关键注意点
- 初始化
Popen时必须传入stdin=subprocess.PIPE才可以向运行中的子进程发送输入 text=True参数会自动处理字符串和字节的转换,不需要手动调用encode()/decode(),Python3.7及以上版本支持,你的3.8.10环境可以正常使用- 每次调用
stdin.write()后必须调用flush()清空缓冲区,否则输入会留在Python进程的缓冲区内,不会发送给子进程 - 示例中将
stderr合并到stdout,避免同时读两个管道可能出现的阻塞问题,如果你需要单独存储错误输出,可以单独读取stderr,需要配合select模块处理IO多路复用避免阻塞 - 所有交互完成后要主动发送退出命令(smbclient下为
quit)并等待进程退出,避免产生僵尸进程
内容的提问来源于stack exchange,提问作者dangerSudo666
相关产品推荐
相关产品推荐

