0

我创建了 Python GUI,它将命令列表作为输入并通过 Telnet 或 SSH 会话执行该列表。在打开 SSH 会话(在 Python 中使用 Paramiko)时,我在 for 循环中使用此代码在各种设备上运行命令:

                    stdin.write(command+"\n")
                    then = time.time()
                    timeout=10.0
                    while not stdout.channel.exit_status_ready():

                        if timeout is not None:
                            timeTest =time.time() - then
                            if timeout <= timeTest:
                                break 

                    # Only print data if there is data to read in the channel
                        if stdout.channel.recv_ready():

                            # Write data from stdout
                            temp=str(stdout.channel.recv(1024))
                            print temp
                            if (temp.endswith(delim)) or (temp.endswith("# ")) :
                                print "successful exit"
                                break

该代码设计用于安装了 BusyBox 的调制解调器。因此,用户输入命令以打开busybox 并在BusyBox shell 中运行一系列命令是很常见的。正如您在这行代码“if (temp.endswith(delim)) 或 (temp.endswith("# "))”中所见,当检测到“ # "(这意味着命令已经完成输出)。

我遇到的问题是 BusyBox 没有将命令提示符打印到标准输出或调试行“print temp”中。为什么是这样?命令输出(例如 ls -l)成功打印到标准输出,但不是命令提示符或busybox介绍消息:当用户在这些调制解调器上输入busybox时,会打印介绍消息“BusyBox v1.17.2 (2014-10-02 10:50:35 PDT)内置外壳(ash)输入“帮助”以获取内置命令列表。” 这也不会打印到 STDOUT。这迫使代码利用在busybox中执行的每个命令的超时,这是不希望的,即它很慢,并且可能有命令输出花费的时间比所需的超时时间长,因此最好查找命令提示符。

这个问题是由于在 BusyBox 中实施了 ash 造成的吗?有没有办法接收命令提示符文本?

4

2 回答 2

0

第一:如果您在以编程方式调用 shell 时尝试识别 shell 提示,那么您做错了。

如果您exec_command()对要运行的每个命令在新通道(通过相同的传输)上使用,您将为每个命令获得一个单独的 stdout、stderr 等;单独报告该命令的退出状态,并且永远不需要猜测一条输出是来自命令还是来自外壳。

第二:如果你真的想这样做(同样,你不应该这样做!),你应该在通话invoke_shell()后使用get_pty(),而不是exec_command('sh').

于 2014-12-09T23:14:10.330 回答
0

请参阅IEEE 标准 1003.1中的条目PS1(指定发出提示的变量)(已添加重点):

PS1

每次交互式 shell 准备读取命令时,该变量的值都应进行参数扩展并写入标准错误。默认值为“$”。对于具有特定的附加实现定义权限的用户,默认值可能是另一个实现定义的值。外壳应替换字符“!”的每个实例 在 PS1 中带有要键入的下一个命令的历史文件编号。逃避“!” 和另外一个 '!' (即 "!!" )应放置文字字符 '!' 在提示中。本卷 POSIX.1-2008 仅针对支持 User Portability Utilities 选项的系统指定变量的影响。

因此,任何符合 POSIX 的 shell——不仅是busybox ash,还有 ksh、dash、bash 和所有其他的——必须将其提示符写入stderr,而不是stdout.


那么,您的简单解决方法是从 读取stderr或使用重定向来组合流(exec 2>&1例如,正在运行)。

于 2014-12-09T18:35:45.343 回答